diff --git a/.changeset/few-ways-beam.md b/.changeset/few-ways-beam.md new file mode 100644 index 0000000000..b0026452fd --- /dev/null +++ b/.changeset/few-ways-beam.md @@ -0,0 +1,6 @@ +--- +'@swisspost/design-system-documentation': major +'@swisspost/design-system-components': major +--- + +Renamed the "dropdown" variant to "menu" for the `post-language-switch` and `post-language-option` components. diff --git a/.changeset/moody-coats-kneel.md b/.changeset/moody-coats-kneel.md new file mode 100644 index 0000000000..53f3529886 --- /dev/null +++ b/.changeset/moody-coats-kneel.md @@ -0,0 +1,5 @@ +--- +'@swisspost/design-system-components': patch +--- + +Updated style and keyboard navigation of `post-language-switch`. diff --git a/packages/components/cypress/e2e/language-option.cy.ts b/packages/components/cypress/e2e/language-option.cy.ts index a3ad3c5b74..72ce65db0b 100644 --- a/packages/components/cypress/e2e/language-option.cy.ts +++ b/packages/components/cypress/e2e/language-option.cy.ts @@ -4,7 +4,7 @@ describe('language-option', () => { describe('button', () => { beforeEach(() => { cy.getComponent('language-option', LANGUAGE_OPTION_ID); - cy.get('@language-option').shadow().find('button').as('button'); + cy.get('@language-option').find('button').as('button'); }); it('should render', () => { @@ -12,7 +12,7 @@ describe('language-option', () => { }); it('should not render an anchor', () => { - cy.get('@language-option').shadow().find('a').should('not.exist'); + cy.get('@language-option').find('a').should('not.exist'); }); it('should render a button with correct properties', () => { @@ -35,7 +35,7 @@ describe('language-option', () => { describe('anchor', () => { beforeEach(() => { cy.getComponent('language-option', LANGUAGE_OPTION_ID, 'anchor'); - cy.get('@language-option').shadow().find('a').as('anchor'); + cy.get('@language-option').find('a').as('anchor'); }); it('should render', () => { @@ -43,7 +43,7 @@ describe('language-option', () => { }); it('should not render a button', () => { - cy.get('@language-option').shadow().find('button').should('not.exist'); + cy.get('@language-option').find('button').should('not.exist'); }); it('should render an anchor', () => { diff --git a/packages/components/src/components/post-header/post-header.tsx b/packages/components/src/components/post-header/post-header.tsx index fa1d21ecb1..3d0cf0487d 100644 --- a/packages/components/src/components/post-header/post-header.tsx +++ b/packages/components/src/components/post-header/post-header.tsx @@ -123,7 +123,7 @@ export class PostHeader { } private switchLanguageSwitchMode() { - const variant: SwitchVariant = this.device === 'desktop' ? 'dropdown' : 'list'; + const variant: SwitchVariant = this.device === 'desktop' ? 'menu' : 'list'; this.host.querySelector('post-language-switch')?.setAttribute('variant', variant); } diff --git a/packages/components/src/components/post-language-option/post-language-option.scss b/packages/components/src/components/post-language-option/post-language-option.scss index 314839d3d8..a1e9dd1695 100644 --- a/packages/components/src/components/post-language-option/post-language-option.scss +++ b/packages/components/src/components/post-language-option/post-language-option.scss @@ -1,64 +1,83 @@ @use '@swisspost/design-system-styles/core' as post; +@use '@swisspost/design-system-styles/mixins/utilities' as utilities-mx; -:host { +post-language-option { display: inline-block; - width: fit-content; -} -button { - @include post.reset-button; -} + button { + @include post.reset-button; + } -a { - color: inherit; - text-decoration: none; -} + a { + color: inherit; + text-decoration: none; + } -:is(a, button) { - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - height: 100%; - width: 100%; - padding: var(--post-language-option-padding); + :is(a, button) { + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + height: 100%; + width: 100%; + padding: var(--post-language-option-padding); + border-radius: 2px; + @include utilities-mx.focus-style; + } } -.post-language-option-list { - @include post.focus-style; - border-radius: 2px; - width: 40px; - height: 40px; +post-language-option:where([variant='list']) { + :is(a, button) { + width: 40px; + height: 40px; - &[aria-current='true'], - &[aria-current='page'] { - background-color: #050400; - color: #fff; + &:hover { + color: #504f4b; + } + + &[aria-current='true'], + &[aria-current='page'] { + background-color: #050400; + color: #fff; + + &:hover { + background-color: #504f4b; + } + } } } -.post-language-option-dropdown { - padding-block: 13px; - padding-inline: 24px; - box-sizing: border-box; - position: relative; +post-language-option:where([variant='menu']) { + width: 100%; + + :is(a, button) { + padding-block: 13px; + padding-inline: 24px; + box-sizing: border-box; + position: relative; + left: -1px; + width: calc(100% + 2px); + + &[aria-current='true'], + &[aria-current='page'] { + &::after { + content: ''; + left: 0; + height: 3px; + background-color: #050400; + width: 100%; + display: block; + position: absolute; + bottom: 3px; + } - &[aria-current='true'], - &[aria-current='page'] { - &::after { - content: ''; - left: -2px; - height: 3px; - background-color: #504f4b; - width: calc(100% + 4px); - display: block; - position: absolute; - bottom: 3px; + &:hover::after { + background-color: #504f4b; + } } - &:focus::after { - width: calc(100% - 5px); - left: 2px; + &:hover { + color: #504f4b; } } } diff --git a/packages/components/src/components/post-language-option/post-language-option.tsx b/packages/components/src/components/post-language-option/post-language-option.tsx index 6e8bd502a1..3e993a989c 100644 --- a/packages/components/src/components/post-language-option/post-language-option.tsx +++ b/packages/components/src/components/post-language-option/post-language-option.tsx @@ -19,7 +19,6 @@ import { SwitchVariant } from '../post-language-switch/switch-variants'; @Component({ tag: 'post-language-option', styleUrl: 'post-language-option.scss', - shadow: true, }) export class PostLanguageOption { @Element() host: HTMLPostLanguageOptionElement; @@ -124,27 +123,33 @@ export class PostLanguageOption { render() { const lang = this.code.toLowerCase(); + const emitOnKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Enter' || e.key === ' ') { + this.emitChange(); + } + }; + return ( - + {this.url ? ( this.emitChange()} + onKeyDown={emitOnKeyDown} > ) : ( diff --git a/packages/components/src/components/post-language-option/readme.md b/packages/components/src/components/post-language-option/readme.md index 8aff93a8a1..181bfabea9 100644 --- a/packages/components/src/components/post-language-option/readme.md +++ b/packages/components/src/components/post-language-option/readme.md @@ -7,13 +7,13 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| ------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ----------- | -| `active` | `active` | If set to `true`, the language option is considered the current language for the page. | `boolean` | `undefined` | -| `code` _(required)_ | `code` | The ISO 639 language code, formatted according to [RFC 5646 (also known as BCP 47)](https://datatracker.ietf.org/doc/html/rfc5646). For example, "de". | `string` | `undefined` | -| `name` | `name` | The full name of the language. For example, "Deutsch". | `string` | `undefined` | -| `url` | `url` | The URL used for the href attribute of the internal anchor. This field is optional; if not provided, a button will be used internally instead of an anchor. | `string` | `undefined` | -| `variant` | `variant` | The variant of the post-language-switch parent (dynamically set by the parent) | `"dropdown" \| "list"` | `undefined` | +| Property | Attribute | Description | Type | Default | +| ------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----------- | +| `active` | `active` | If set to `true`, the language option is considered the current language for the page. | `boolean` | `undefined` | +| `code` _(required)_ | `code` | The ISO 639 language code, formatted according to [RFC 5646 (also known as BCP 47)](https://datatracker.ietf.org/doc/html/rfc5646). For example, "de". | `string` | `undefined` | +| `name` | `name` | The full name of the language. For example, "Deutsch". | `string` | `undefined` | +| `url` | `url` | The URL used for the href attribute of the internal anchor. This field is optional; if not provided, a button will be used internally instead of an anchor. | `string` | `undefined` | +| `variant` | `variant` | The variant of the post-language-switch parent (dynamically set by the parent) | `"list" \| "menu"` | `undefined` | ## Events diff --git a/packages/components/src/components/post-language-switch/post-language-switch.scss b/packages/components/src/components/post-language-switch/post-language-switch.scss index f0cc236912..769dfde594 100644 --- a/packages/components/src/components/post-language-switch/post-language-switch.scss +++ b/packages/components/src/components/post-language-switch/post-language-switch.scss @@ -3,16 +3,26 @@ @use '@swisspost/design-system-styles/mixins/button' as button-mx; @use '@swisspost/design-system-styles/mixins/utilities' as utilities-mx; @use '@swisspost/design-system-styles/components/header/mixins' as header-mx; +@use '@swisspost/design-system-styles/mixins/media'; tokens.$default-map: components.$post-button; :host { display: block; + + @include media.max(lg) { + display: flex !important; + gap: 0.5rem; + } } .post-language-switch-dropdown-container { display: flex; flex-direction: column; + + > * { + width: 100%; + } } .post-language-switch-trigger { diff --git a/packages/components/src/components/post-language-switch/post-language-switch.tsx b/packages/components/src/components/post-language-switch/post-language-switch.tsx index c26cf8b7f8..57abc67e87 100644 --- a/packages/components/src/components/post-language-switch/post-language-switch.tsx +++ b/packages/components/src/components/post-language-switch/post-language-switch.tsx @@ -77,7 +77,7 @@ export class PostLanguageSwitch { }); } - componentShouldUpdate() { + componentWillUpdate() { this.updateChildrenVariant(); } @@ -100,7 +100,7 @@ export class PostLanguageSwitch { }); // Hides the dropdown when an option has been clicked - if (this.variant === 'dropdown') { + if (this.variant === 'menu') { const menu = this.host.shadowRoot.querySelector('post-menu') as HTMLPostMenuElement; menu.toggle(menu); } @@ -133,10 +133,8 @@ export class PostLanguageSwitch { - -
- -
+ +
); diff --git a/packages/components/src/components/post-language-switch/readme.md b/packages/components/src/components/post-language-switch/readme.md index 8beb610dfa..483f8d0e4a 100644 --- a/packages/components/src/components/post-language-switch/readme.md +++ b/packages/components/src/components/post-language-switch/readme.md @@ -5,11 +5,11 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| ------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ----------- | -| `caption` | `caption` | A title for the list of language options | `string` | `undefined` | -| `description` | `description` | A descriptive text for the list of language options | `string` | `undefined` | -| `variant` | `variant` | Variant that determines the rendering of the language switch either as a list (used on mobile in the header) or a dropdown (used on desktop in the header) | `"dropdown" \| "list"` | `'list'` | +| Property | Attribute | Description | Type | Default | +| ------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----------- | +| `caption` | `caption` | A title for the list of language options | `string` | `undefined` | +| `description` | `description` | A descriptive text for the list of language options | `string` | `undefined` | +| `variant` | `variant` | Variant that determines the rendering of the language switch either as a list (used on mobile in the header) or a dropdown (used on desktop in the header) | `"list" \| "menu"` | `'list'` | ## Dependencies diff --git a/packages/components/src/components/post-language-switch/switch-variants.ts b/packages/components/src/components/post-language-switch/switch-variants.ts index 2473e44f8f..7220d28a4e 100644 --- a/packages/components/src/components/post-language-switch/switch-variants.ts +++ b/packages/components/src/components/post-language-switch/switch-variants.ts @@ -1,3 +1,3 @@ -export const SWITCH_VARIANTS = ['list', 'dropdown'] as const; +export const SWITCH_VARIANTS = ['list', 'menu'] as const; export type SwitchVariant = (typeof SWITCH_VARIANTS)[number]; diff --git a/packages/documentation/src/stories/components/language-switch/language-switch.stories.ts b/packages/documentation/src/stories/components/language-switch/language-switch.stories.ts index e3cb30133e..0b71cac4e9 100644 --- a/packages/documentation/src/stories/components/language-switch/language-switch.stories.ts +++ b/packages/documentation/src/stories/components/language-switch/language-switch.stories.ts @@ -65,7 +65,7 @@ function renderLanguageSwitchAsLinks(args: Partial DE , ) => { - return schemes( - () => html` -
- ${meta.render?.({ ...context.args }, context)} -
- `, - ); + return schemes(() => html` ${meta.render?.({ ...context.args }, context)} `); }, };