Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(components): fix post-togglebutton keyboard navigation #4242

Merged
merged 2 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/nice-cycles-provide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@swisspost/design-system-components': patch
---

Updated the `post-togglebutton` to function like a real button, including support for keyboard navigation and proper focus styles.
8 changes: 4 additions & 4 deletions packages/components/src/animations/slide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ const easing: string = 'ease';
const duration: number = 500;
const fill: FillMode = 'forwards';

export const slideUp = (el: HTMLElement, translateSize: string = '8rem'): Animation => {
export const slideUp = (el: HTMLElement, translateSize: string = '100%'): Animation => {
return el.animate(
[
{ transform: `translateY(-${translateSize})` }, // Starting position (no translation)
{ transform: `translateY(${translateSize})` }, // Starting position (no translation)
{ transform: 'translateY(0)' }, // End position
],
{
Expand All @@ -16,11 +16,11 @@ export const slideUp = (el: HTMLElement, translateSize: string = '8rem'): Animat
);
};

export const slideDown = (el: HTMLElement, translateSize: string = '8rem'): Animation => {
export const slideDown = (el: HTMLElement, translateSize: string = '100%'): Animation => {
return el.animate(
[
{ transform: 'translateY(0)' }, // Starting position (no translation)
{ transform: `translateY(-${translateSize})` }, // End position
{ transform: `translateY(${translateSize})` }, // End position
],
{
duration: duration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
tokens.$default-map: components.$post-floating-button;

:host {
--post-floating-button-translate-y: #{tokens.get('post-floating-button-translate-y')};
--post-floating-button-translate-y: calc(-1 * #{tokens.get('post-floating-button-translate-y')});
position: fixed;
top: tokens.get('post-floating-button-position-top');
right: tokens.get('post-floating-button-position-right');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export class PostBackToTop {

private translateY: string;

isBelowFold(): boolean {
private isBelowFold(): boolean {
return window.scrollY > window.innerHeight;
}

handleScroll = () => {
private handleScroll = () => {
this.belowFold = this.isBelowFold();
};

Expand All @@ -39,7 +39,7 @@ export class PostBackToTop {
}
}

scrollToTop() {
private scrollToTop() {
window.scrollTo({
top: 0,
});
Expand Down Expand Up @@ -72,7 +72,7 @@ export class PostBackToTop {
.getPropertyValue('--post-floating-button-translate-y');

if (!this.belowFold) {
this.el.style.transform = `translateY(-${this.translateY})`;
this.el.style.transform = `translateY(${this.translateY})`;
}

// Initial load
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
@use '@swisspost/design-system-styles/mixins/utilities';
@use '@swisspost/design-system-styles/functions/tokens';
@use '@swisspost/design-system-styles/tokens/helpers';

:host {
cursor: pointer;
outline-offset: tokens.get('focus-outline-offset', helpers.$post-focus) !important;
outline: tokens.get('focus-outline-color', helpers.$post-focus) none
tokens.get('focus-outline-width', helpers.$post-focus) !important;
}

:host(:focus-visible) {
outline-style: tokens.get('focus-border-style', helpers.$post-focus) !important;

@include utilities.high-contrast-mode() {
outline-color: Highlight !important;
}
}

:host([aria-pressed="true"]) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Host, h, Prop, Watch } from '@stencil/core';
import { Component, Host, h, Prop, Watch, Element } from '@stencil/core';
import { version } from '@root/package.json';
import { checkType } from '@/utils';

Expand All @@ -12,6 +12,8 @@ import { checkType } from '@/utils';
shadow: true,
})
export class PostTogglebutton {
@Element() host: HTMLPostTogglebuttonElement;

/**
* If `true`, the button is in the "on" state, otherwise it is in the "off" state.
*/
Expand All @@ -28,28 +30,32 @@ export class PostTogglebutton {

componentWillLoad() {
this.validateToggled();

// add event listener to not override listener that might be set on the host
this.host.addEventListener('click', () => this.handleClick());
this.host.addEventListener('keydown', (e: KeyboardEvent) => this.handleKeydown(e));
}

private handleClick = () => {
this.toggled = !this.toggled;
};

private handleKeydown = (event: KeyboardEvent) => {
if (event.key === 'Enter') {
this.toggled = !this.toggled;
// perform a click when enter or spaced are pressed to mimic the button behavior
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault(); // prevents the page from scrolling when space is pressed
this.host.click();
}
};

render() {
return (
<Host
slot="post-togglebutton"
tabindex="0"
data-version={version}
role="button"
tabindex="0"
aria-pressed={this.toggled.toString()}
onClick={this.handleClick}
onKeyDown={this.handleKeydown}
>
<slot />
</Host>
Expand Down
Loading