From dcef51de2a5333d2d00be54b2e329234f58b7341 Mon Sep 17 00:00:00 2001 From: Tommmaso Menga Date: Thu, 29 Aug 2024 10:31:09 +0200 Subject: [PATCH 01/15] feat(button-action-elements): keep elements focusable when disabled --- src/elements/button/button/button.ts | 4 +- .../button/mini-button/mini-button.ts | 6 ++- .../secondary-button/secondary-button.ts | 4 +- .../button/tertiary-button/tertiary-button.ts | 4 +- .../transparent-button/transparent-button.ts | 4 +- src/elements/core/mixins/disabled-mixin.ts | 38 +++++++++++++++++++ .../expansion-panel-header.ts | 4 +- .../block-link-button/block-link-button.ts | 4 +- src/elements/link/link-button/link-button.ts | 4 +- src/elements/menu/menu-button/menu-button.ts | 4 +- src/elements/tag/tag/tag.ts | 4 +- 11 files changed, 60 insertions(+), 20 deletions(-) diff --git a/src/elements/button/button/button.ts b/src/elements/button/button/button.ts index f956f86828..f28717e1a1 100644 --- a/src/elements/button/button/button.ts +++ b/src/elements/button/button/button.ts @@ -2,7 +2,7 @@ import type { CSSResultGroup } from 'lit'; import { customElement } from 'lit/decorators.js'; import { SbbButtonBaseElement } from '../../core/base-elements.js'; -import { SbbDisabledTabIndexActionMixin } from '../../core/mixins.js'; +import { SbbFocusableDisabledActionMixin } from '../../core/mixins.js'; import { buttonCommonStyle, buttonPrimaryStyle, SbbButtonCommonElementMixin } from '../common.js'; /** @@ -13,7 +13,7 @@ import { buttonCommonStyle, buttonPrimaryStyle, SbbButtonCommonElementMixin } fr */ @customElement('sbb-button') export class SbbButtonElement extends SbbButtonCommonElementMixin( - SbbDisabledTabIndexActionMixin(SbbButtonBaseElement), + SbbFocusableDisabledActionMixin(SbbButtonBaseElement), ) { public static override styles: CSSResultGroup = [buttonCommonStyle, buttonPrimaryStyle]; } diff --git a/src/elements/button/mini-button/mini-button.ts b/src/elements/button/mini-button/mini-button.ts index a7fd7bb56f..fa364199b9 100644 --- a/src/elements/button/mini-button/mini-button.ts +++ b/src/elements/button/mini-button/mini-button.ts @@ -1,7 +1,7 @@ import type { CSSResultGroup } from 'lit'; import { customElement } from 'lit/decorators.js'; -import { SbbDisabledTabIndexActionMixin } from '../../core/mixins.js'; +import { SbbFocusableDisabledActionMixin } from '../../core/mixins.js'; import { SbbMiniButtonBaseElement } from './mini-button-base-element.js'; import style from './mini-button.scss?lit&inline'; @@ -13,7 +13,9 @@ import style from './mini-button.scss?lit&inline'; * @slot icon - Slot used to display the icon, if one is set */ @customElement('sbb-mini-button') -export class SbbMiniButtonElement extends SbbDisabledTabIndexActionMixin(SbbMiniButtonBaseElement) { +export class SbbMiniButtonElement extends SbbFocusableDisabledActionMixin( + SbbMiniButtonBaseElement, +) { public static override styles: CSSResultGroup = style; } diff --git a/src/elements/button/secondary-button/secondary-button.ts b/src/elements/button/secondary-button/secondary-button.ts index 415f2d3cdb..f365c64c94 100644 --- a/src/elements/button/secondary-button/secondary-button.ts +++ b/src/elements/button/secondary-button/secondary-button.ts @@ -2,7 +2,7 @@ import type { CSSResultGroup } from 'lit'; import { customElement } from 'lit/decorators.js'; import { SbbButtonBaseElement } from '../../core/base-elements.js'; -import { SbbDisabledTabIndexActionMixin } from '../../core/mixins.js'; +import { SbbFocusableDisabledActionMixin } from '../../core/mixins.js'; import { buttonCommonStyle, buttonSecondaryStyle, SbbButtonCommonElementMixin } from '../common.js'; /** @@ -13,7 +13,7 @@ import { buttonCommonStyle, buttonSecondaryStyle, SbbButtonCommonElementMixin } */ @customElement('sbb-secondary-button') export class SbbSecondaryButtonElement extends SbbButtonCommonElementMixin( - SbbDisabledTabIndexActionMixin(SbbButtonBaseElement), + SbbFocusableDisabledActionMixin(SbbButtonBaseElement), ) { public static override styles: CSSResultGroup = [buttonCommonStyle, buttonSecondaryStyle]; } diff --git a/src/elements/button/tertiary-button/tertiary-button.ts b/src/elements/button/tertiary-button/tertiary-button.ts index 02c656130b..928dffa9b2 100644 --- a/src/elements/button/tertiary-button/tertiary-button.ts +++ b/src/elements/button/tertiary-button/tertiary-button.ts @@ -2,7 +2,7 @@ import type { CSSResultGroup } from 'lit'; import { customElement } from 'lit/decorators.js'; import { SbbButtonBaseElement } from '../../core/base-elements.js'; -import { SbbDisabledTabIndexActionMixin } from '../../core/mixins.js'; +import { SbbFocusableDisabledActionMixin } from '../../core/mixins.js'; import { buttonCommonStyle, buttonTertiaryStyle, SbbButtonCommonElementMixin } from '../common.js'; /** @@ -13,7 +13,7 @@ import { buttonCommonStyle, buttonTertiaryStyle, SbbButtonCommonElementMixin } f */ @customElement('sbb-tertiary-button') export class SbbTertiaryButtonElement extends SbbButtonCommonElementMixin( - SbbDisabledTabIndexActionMixin(SbbButtonBaseElement), + SbbFocusableDisabledActionMixin(SbbButtonBaseElement), ) { public static override styles: CSSResultGroup = [buttonCommonStyle, buttonTertiaryStyle]; } diff --git a/src/elements/button/transparent-button/transparent-button.ts b/src/elements/button/transparent-button/transparent-button.ts index b8fbb74862..616f453bbf 100644 --- a/src/elements/button/transparent-button/transparent-button.ts +++ b/src/elements/button/transparent-button/transparent-button.ts @@ -2,7 +2,7 @@ import type { CSSResultGroup } from 'lit'; import { customElement } from 'lit/decorators.js'; import { SbbButtonBaseElement } from '../../core/base-elements.js'; -import { SbbDisabledTabIndexActionMixin } from '../../core/mixins.js'; +import { SbbFocusableDisabledActionMixin } from '../../core/mixins.js'; import { buttonCommonStyle, buttonTransparentStyle, @@ -17,7 +17,7 @@ import { */ @customElement('sbb-transparent-button') export class SbbTransparentButtonElement extends SbbButtonCommonElementMixin( - SbbDisabledTabIndexActionMixin(SbbButtonBaseElement), + SbbFocusableDisabledActionMixin(SbbButtonBaseElement), ) { public static override styles: CSSResultGroup = [buttonCommonStyle, buttonTransparentStyle]; } diff --git a/src/elements/core/mixins/disabled-mixin.ts b/src/elements/core/mixins/disabled-mixin.ts index 233fe2e1cf..873af649bf 100644 --- a/src/elements/core/mixins/disabled-mixin.ts +++ b/src/elements/core/mixins/disabled-mixin.ts @@ -1,6 +1,8 @@ import type { LitElement, PropertyValues } from 'lit'; import { property } from 'lit/decorators.js'; +import { hostAttributes } from '../decorators.js'; + import type { AbstractConstructor } from './constructor.js'; export declare class SbbDisabledMixinType { @@ -69,3 +71,39 @@ export const SbbDisabledTabIndexActionMixin = & T; }; + +/** + * Extends `SbbDisabledMixin` with the `aria-disabled` and the `tabindex` handling. + * For a11y purposes, keeps the element focusable even when disabled + */ +// eslint-disable-next-line @typescript-eslint/naming-convention +export const SbbFocusableDisabledActionMixin = >( + superClass: T, +): AbstractConstructor & T => { + @hostAttributes({ + tabindex: '0', + }) + abstract class SbbFocusableDisabledAction + extends SbbDisabledMixin(superClass) + implements SbbDisabledMixinType + { + public override connectedCallback(): void { + super.connectedCallback(); + } + + protected override willUpdate(changedProperties: PropertyValues): void { + super.willUpdate(changedProperties); + + if (!changedProperties.has('disabled')) { + return; + } + + if (this.disabled) { + this.setAttribute('aria-disabled', 'true'); + } else { + this.removeAttribute('aria-disabled'); + } + } + } + return SbbFocusableDisabledAction as AbstractConstructor & T; +}; diff --git a/src/elements/expansion-panel/expansion-panel-header/expansion-panel-header.ts b/src/elements/expansion-panel/expansion-panel-header/expansion-panel-header.ts index 59ddc3bddb..1687c3e3ff 100644 --- a/src/elements/expansion-panel/expansion-panel-header/expansion-panel-header.ts +++ b/src/elements/expansion-panel/expansion-panel-header/expansion-panel-header.ts @@ -5,7 +5,7 @@ import { SbbButtonBaseElement } from '../../core/base-elements.js'; import { SbbConnectedAbortController, SbbSlotStateController } from '../../core/controllers.js'; import { hostAttributes } from '../../core/decorators.js'; import { EventEmitter } from '../../core/eventing.js'; -import { SbbDisabledTabIndexActionMixin } from '../../core/mixins.js'; +import { SbbFocusableDisabledActionMixin } from '../../core/mixins.js'; import { SbbIconNameMixin } from '../../icon.js'; import type { SbbExpansionPanelElement } from '../expansion-panel.js'; @@ -22,7 +22,7 @@ import style from './expansion-panel-header.scss?lit&inline'; @hostAttributes({ slot: 'header', }) -export class SbbExpansionPanelHeaderElement extends SbbDisabledTabIndexActionMixin( +export class SbbExpansionPanelHeaderElement extends SbbFocusableDisabledActionMixin( SbbIconNameMixin(SbbButtonBaseElement), ) { public static override styles: CSSResultGroup = style; diff --git a/src/elements/link/block-link-button/block-link-button.ts b/src/elements/link/block-link-button/block-link-button.ts index 114492c085..65763c2332 100644 --- a/src/elements/link/block-link-button/block-link-button.ts +++ b/src/elements/link/block-link-button/block-link-button.ts @@ -1,7 +1,7 @@ import { customElement } from 'lit/decorators.js'; import { SbbButtonBaseElement } from '../../core/base-elements.js'; -import { SbbDisabledTabIndexActionMixin } from '../../core/mixins.js'; +import { SbbFocusableDisabledActionMixin } from '../../core/mixins.js'; import { SbbBlockLinkCommonElementMixin } from '../common.js'; /** @@ -12,7 +12,7 @@ import { SbbBlockLinkCommonElementMixin } from '../common.js'; */ @customElement('sbb-block-link-button') export class SbbBlockLinkButtonElement extends SbbBlockLinkCommonElementMixin( - SbbDisabledTabIndexActionMixin(SbbButtonBaseElement), + SbbFocusableDisabledActionMixin(SbbButtonBaseElement), ) {} declare global { diff --git a/src/elements/link/link-button/link-button.ts b/src/elements/link/link-button/link-button.ts index a04569a680..7a58555138 100644 --- a/src/elements/link/link-button/link-button.ts +++ b/src/elements/link/link-button/link-button.ts @@ -1,7 +1,7 @@ import { customElement } from 'lit/decorators.js'; import { SbbButtonBaseElement } from '../../core/base-elements.js'; -import { SbbDisabledTabIndexActionMixin } from '../../core/mixins.js'; +import { SbbFocusableDisabledActionMixin } from '../../core/mixins.js'; import { SbbInlineLinkCommonElementMixin } from '../common.js'; /** @@ -11,7 +11,7 @@ import { SbbInlineLinkCommonElementMixin } from '../common.js'; */ @customElement('sbb-link-button') export class SbbLinkButtonElement extends SbbInlineLinkCommonElementMixin( - SbbDisabledTabIndexActionMixin(SbbButtonBaseElement), + SbbFocusableDisabledActionMixin(SbbButtonBaseElement), ) {} declare global { diff --git a/src/elements/menu/menu-button/menu-button.ts b/src/elements/menu/menu-button/menu-button.ts index 1602155c61..2477187f6f 100644 --- a/src/elements/menu/menu-button/menu-button.ts +++ b/src/elements/menu/menu-button/menu-button.ts @@ -1,7 +1,7 @@ import { customElement } from 'lit/decorators.js'; import { SbbButtonBaseElement } from '../../core/base-elements.js'; -import { SbbDisabledTabIndexActionMixin } from '../../core/mixins.js'; +import { SbbFocusableDisabledActionMixin } from '../../core/mixins.js'; import { SbbMenuActionCommonElementMixin } from '../common.js'; /** @@ -13,7 +13,7 @@ import { SbbMenuActionCommonElementMixin } from '../common.js'; * to modify horizontal padding. */ @customElement('sbb-menu-button') -export class SbbMenuButtonElement extends SbbDisabledTabIndexActionMixin( +export class SbbMenuButtonElement extends SbbFocusableDisabledActionMixin( SbbMenuActionCommonElementMixin(SbbButtonBaseElement), ) {} diff --git a/src/elements/tag/tag/tag.ts b/src/elements/tag/tag/tag.ts index 999058bdd0..4bbf3ac227 100644 --- a/src/elements/tag/tag/tag.ts +++ b/src/elements/tag/tag/tag.ts @@ -6,7 +6,7 @@ import { SbbButtonBaseElement } from '../../core/base-elements.js'; import { SbbConnectedAbortController } from '../../core/controllers.js'; import { slotState } from '../../core/decorators.js'; import { EventEmitter } from '../../core/eventing.js'; -import { SbbDisabledTabIndexActionMixin } from '../../core/mixins.js'; +import { SbbFocusableDisabledActionMixin } from '../../core/mixins.js'; import { SbbIconNameMixin } from '../../icon.js'; import type { SbbTagGroupElement } from '../tag-group.js'; @@ -27,7 +27,7 @@ export type SbbTagSize = 's' | 'm'; @customElement('sbb-tag') @slotState() export class SbbTagElement extends SbbIconNameMixin( - SbbDisabledTabIndexActionMixin(SbbButtonBaseElement), + SbbFocusableDisabledActionMixin(SbbButtonBaseElement), ) { public static override styles: CSSResultGroup = style; public static readonly events = { From 493bff80e1def1a220fac971668ec86c09d233f9 Mon Sep 17 00:00:00 2001 From: Tommmaso Menga Date: Thu, 29 Aug 2024 10:55:51 +0200 Subject: [PATCH 02/15] chore: update snapshots --- .../button/button/__snapshots__/button.snapshot.spec.snap.js | 1 + .../__snapshots__/secondary-button.snapshot.spec.snap.js | 1 + .../__snapshots__/tertiary-button.snapshot.spec.snap.js | 1 + .../__snapshots__/transparent-button.snapshot.spec.snap.js | 1 + .../menu/menu/__snapshots__/menu.snapshot.spec.snap.js | 2 ++ .../step-label/__snapshots__/step-label.snapshot.spec.snap.js | 4 ++-- src/elements/tag/tag/__snapshots__/tag.snapshot.spec.snap.js | 1 + 7 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/elements/button/button/__snapshots__/button.snapshot.spec.snap.js b/src/elements/button/button/__snapshots__/button.snapshot.spec.snap.js index 5b09526685..dd05fa2417 100644 --- a/src/elements/button/button/__snapshots__/button.snapshot.spec.snap.js +++ b/src/elements/button/button/__snapshots__/button.snapshot.spec.snap.js @@ -15,6 +15,7 @@ snapshots["sbb-button renders a sbb-button without icon DOM"] = negative="" role="button" size="m" + tabindex="0" type="button" value="value" > diff --git a/src/elements/button/secondary-button/__snapshots__/secondary-button.snapshot.spec.snap.js b/src/elements/button/secondary-button/__snapshots__/secondary-button.snapshot.spec.snap.js index 38e2636b9e..c96b262da2 100644 --- a/src/elements/button/secondary-button/__snapshots__/secondary-button.snapshot.spec.snap.js +++ b/src/elements/button/secondary-button/__snapshots__/secondary-button.snapshot.spec.snap.js @@ -15,6 +15,7 @@ snapshots["sbb-secondary-button renders a sbb-secondary-button without icon DOM" negative="" role="button" size="m" + tabindex="0" type="button" value="value" > diff --git a/src/elements/button/tertiary-button/__snapshots__/tertiary-button.snapshot.spec.snap.js b/src/elements/button/tertiary-button/__snapshots__/tertiary-button.snapshot.spec.snap.js index 3edcafe35e..c957239301 100644 --- a/src/elements/button/tertiary-button/__snapshots__/tertiary-button.snapshot.spec.snap.js +++ b/src/elements/button/tertiary-button/__snapshots__/tertiary-button.snapshot.spec.snap.js @@ -15,6 +15,7 @@ snapshots["sbb-tertiary-button renders a sbb-tertiary-button without icon DOM"] negative="" role="button" size="m" + tabindex="0" type="button" value="value" > diff --git a/src/elements/button/transparent-button/__snapshots__/transparent-button.snapshot.spec.snap.js b/src/elements/button/transparent-button/__snapshots__/transparent-button.snapshot.spec.snap.js index f52df9c0cd..c063d3faeb 100644 --- a/src/elements/button/transparent-button/__snapshots__/transparent-button.snapshot.spec.snap.js +++ b/src/elements/button/transparent-button/__snapshots__/transparent-button.snapshot.spec.snap.js @@ -15,6 +15,7 @@ snapshots["sbb-transparent-button renders a sbb-transparent-button without icon negative="" role="button" size="m" + tabindex="0" type="button" value="value" > diff --git a/src/elements/menu/menu/__snapshots__/menu.snapshot.spec.snap.js b/src/elements/menu/menu/__snapshots__/menu.snapshot.spec.snap.js index 2b9b6c9495..e9538be206 100644 --- a/src/elements/menu/menu/__snapshots__/menu.snapshot.spec.snap.js +++ b/src/elements/menu/menu/__snapshots__/menu.snapshot.spec.snap.js @@ -38,6 +38,7 @@ snapshots["sbb-menu renders DOM"] = disabled="" icon-name="pen-small" role="button" + tabindex="0" > Edit @@ -111,6 +112,7 @@ snapshots["sbb-menu renders with list DOM"] = icon-name="pen-small" role="button" slot="li-1" + tabindex="0" > Edit diff --git a/src/elements/stepper/step-label/__snapshots__/step-label.snapshot.spec.snap.js b/src/elements/stepper/step-label/__snapshots__/step-label.snapshot.spec.snap.js index 8be9a14bb1..e07063b681 100644 --- a/src/elements/stepper/step-label/__snapshots__/step-label.snapshot.spec.snap.js +++ b/src/elements/stepper/step-label/__snapshots__/step-label.snapshot.spec.snap.js @@ -121,8 +121,8 @@ snapshots["sbb-step-label A11y tree Firefox"] = "name": "", "children": [ { - "role": "text", - "name": "" + "role": "tab", + "name": "Label" } ] } diff --git a/src/elements/tag/tag/__snapshots__/tag.snapshot.spec.snap.js b/src/elements/tag/tag/__snapshots__/tag.snapshot.spec.snap.js index 0ad644e0a3..c80c1e2a05 100644 --- a/src/elements/tag/tag/__snapshots__/tag.snapshot.spec.snap.js +++ b/src/elements/tag/tag/__snapshots__/tag.snapshot.spec.snap.js @@ -86,6 +86,7 @@ snapshots["sbb-tag renders disabled with icon and amount DOM"] = icon-name="circle-information-small" role="button" size="m" + tabindex="0" value="information" > Info From 05a5ddcef81667a42f05c221b1430a773bca7038 Mon Sep 17 00:00:00 2001 From: Tommmaso Menga Date: Thu, 29 Aug 2024 12:10:40 +0200 Subject: [PATCH 03/15] chore: update snapshots --- .../step-label/__snapshots__/step-label.snapshot.spec.snap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/elements/stepper/step-label/__snapshots__/step-label.snapshot.spec.snap.js b/src/elements/stepper/step-label/__snapshots__/step-label.snapshot.spec.snap.js index e07063b681..8be9a14bb1 100644 --- a/src/elements/stepper/step-label/__snapshots__/step-label.snapshot.spec.snap.js +++ b/src/elements/stepper/step-label/__snapshots__/step-label.snapshot.spec.snap.js @@ -121,8 +121,8 @@ snapshots["sbb-step-label A11y tree Firefox"] = "name": "", "children": [ { - "role": "tab", - "name": "Label" + "role": "text", + "name": "" } ] } From 134e06ebb7a567f75811070c5bd4954bb805106c Mon Sep 17 00:00:00 2001 From: Tommmaso Menga Date: Thu, 29 Aug 2024 14:18:42 +0200 Subject: [PATCH 04/15] build(visual-regression-app): fix title pills --- .../test-case/test-title-chip-list/test-title-chip-list.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/visual-regression-app/src/components/test-case/test-title-chip-list/test-title-chip-list.ts b/src/visual-regression-app/src/components/test-case/test-title-chip-list/test-title-chip-list.ts index aeafbd68e4..a12cfff843 100644 --- a/src/visual-regression-app/src/components/test-case/test-title-chip-list/test-title-chip-list.ts +++ b/src/visual-regression-app/src/components/test-case/test-title-chip-list/test-title-chip-list.ts @@ -9,7 +9,7 @@ import style from './test-title-chip-list.scss?lit&inline'; * - simple => "key=value" patterns * - complex => "key=( key=value-... ) */ -const paramsRegex = /(?[a-zA-Z]*=\(.*\))|(?[a-zA-Z]+=[a-zA-Z0-9-]*)/gm; +const paramsRegex = /(?[a-zA-Z]*=\(.*\))|(?[a-zA-Z]+=[a-zA-Z0-9]*)/gm; type DescribeEachItem = { key: string; From aebbfdf4b2ac9f6024f5ed9da723e5e48e162147 Mon Sep 17 00:00:00 2001 From: Tommmaso Menga Date: Mon, 2 Sep 2024 10:22:50 +0200 Subject: [PATCH 05/15] docs(button-elements): add a11y docs for disabled elements --- src/elements/button/button/readme.md | 6 ++++++ src/elements/button/mini-button/readme.md | 6 ++++++ src/elements/button/secondary-button/readme.md | 6 ++++++ src/elements/button/tertiary-button/readme.md | 6 ++++++ src/elements/button/transparent-button/readme.md | 6 ++++++ src/elements/expansion-panel/expansion-panel/readme.md | 6 ++++++ src/elements/link/block-link-button/readme.md | 8 ++++++++ src/elements/link/link-button/readme.md | 8 ++++++++ src/elements/menu/menu-button/readme.md | 8 ++++++++ src/elements/tag/tag/readme.md | 6 ++++++ 10 files changed, 66 insertions(+) diff --git a/src/elements/button/button/readme.md b/src/elements/button/button/readme.md index 07d5768ef8..254b5f928a 100644 --- a/src/elements/button/button/readme.md +++ b/src/elements/button/button/readme.md @@ -62,6 +62,12 @@ sbb-button { Use the accessibility properties in case of an icon-only button to describe the purpose of the `sbb-button` for screen-reader users. +### Disabled buttons + +Generally speaking, `disabled` elements are considered a bad pattern for a11y. They are invisible to assistive technology and do not provide the reason for which they are disabled. +To partially address the problem, disabled elements are kept focusable (other interactions are still prevented). +Still, the consumer's responsible for providing the reason for a disabled element. + ## Properties diff --git a/src/elements/button/mini-button/readme.md b/src/elements/button/mini-button/readme.md index 2914661af0..3b4acab184 100644 --- a/src/elements/button/mini-button/readme.md +++ b/src/elements/button/mini-button/readme.md @@ -70,6 +70,12 @@ sbb-mini-button { Use the accessibility properties to describe the purpose of the `sbb-mini-button` for screen-reader users. +### Disabled buttons + +Generally speaking, `disabled` elements are considered a bad pattern for a11y. They are invisible to assistive technology and do not provide the reason for which they are disabled. +To partially address the problem, disabled elements are kept focusable (other interactions are still prevented). +Still, the consumer's responsible for providing the reason for a disabled element. + ## Properties diff --git a/src/elements/button/secondary-button/readme.md b/src/elements/button/secondary-button/readme.md index 19fe5ecfd9..4e96d48615 100644 --- a/src/elements/button/secondary-button/readme.md +++ b/src/elements/button/secondary-button/readme.md @@ -67,6 +67,12 @@ sbb-secondary-button { Use the accessibility properties in case of an icon-only button to describe the purpose of the `sbb-secondary-button` for screen-reader users. +### Disabled buttons + +Generally speaking, `disabled` elements are considered a bad pattern for a11y. They are invisible to assistive technology and do not provide the reason for which they are disabled. +To partially address the problem, disabled elements are kept focusable (other interactions are still prevented). +Still, the consumer's responsible for providing the reason for a disabled element. + ## Properties diff --git a/src/elements/button/tertiary-button/readme.md b/src/elements/button/tertiary-button/readme.md index a887ea0d7e..db1d38a4ce 100644 --- a/src/elements/button/tertiary-button/readme.md +++ b/src/elements/button/tertiary-button/readme.md @@ -67,6 +67,12 @@ sbb-tertiary-button { Use the accessibility properties in case of an icon-only button to describe the purpose of the `sbb-tertiary-button` for screen-reader users. +### Disabled buttons + +Generally speaking, `disabled` elements are considered a bad pattern for a11y. They are invisible to assistive technology and do not provide the reason for which they are disabled. +To partially address the problem, disabled elements are kept focusable (other interactions are still prevented). +Still, the consumer's responsible for providing the reason for a disabled element. + ## Properties diff --git a/src/elements/button/transparent-button/readme.md b/src/elements/button/transparent-button/readme.md index 0cfa743e4f..c03a4a10c8 100644 --- a/src/elements/button/transparent-button/readme.md +++ b/src/elements/button/transparent-button/readme.md @@ -67,6 +67,12 @@ sbb-transparent-button { Use the accessibility properties in case of an icon-only button to describe the purpose of the `sbb-transparent-button` for screen-reader users. +### Disabled buttons + +Generally speaking, `disabled` elements are considered a bad pattern for a11y. They are invisible to assistive technology and do not provide the reason for which they are disabled. +To partially address the problem, disabled elements are kept focusable (other interactions are still prevented). +Still, the consumer's responsible for providing the reason for a disabled element. + ## Properties diff --git a/src/elements/expansion-panel/expansion-panel/readme.md b/src/elements/expansion-panel/expansion-panel/readme.md index 9f9a940218..0ee438bed4 100644 --- a/src/elements/expansion-panel/expansion-panel/readme.md +++ b/src/elements/expansion-panel/expansion-panel/readme.md @@ -74,6 +74,12 @@ and the header's `id` is set as `aria-labelledby` attribute on the content. The `expanded` attribute is used to correctly set the `aria-expanded` attribute on the header and the `aria-hidden` attribute on the content. +### Disabled elements + +Generally speaking, `disabled` elements are considered a bad pattern for a11y. They are invisible to assistive technology and do not provide the reason for which they are disabled. +To partially address the problem, disabled elements are kept focusable (other interactions are still prevented). +Still, the consumer's responsible for providing the reason for a disabled element. + ## Properties diff --git a/src/elements/link/block-link-button/readme.md b/src/elements/link/block-link-button/readme.md index 6d192a31ca..e88bd33e92 100644 --- a/src/elements/link/block-link-button/readme.md +++ b/src/elements/link/block-link-button/readme.md @@ -42,6 +42,14 @@ The component has three sizes (`xs`, `s`, which is the default, and `m`). Refunds ``` +## Accessibility + +### Disabled buttons + +Generally speaking, `disabled` elements are considered a bad pattern for a11y. They are invisible to assistive technology and do not provide the reason for which they are disabled. +To partially address the problem, disabled elements are kept focusable (other interactions are still prevented). +Still, the consumer's responsible for providing the reason for a disabled element. + ## Properties diff --git a/src/elements/link/link-button/readme.md b/src/elements/link/link-button/readme.md index 10b5ed0b10..3b89b4cd38 100644 --- a/src/elements/link/link-button/readme.md +++ b/src/elements/link/link-button/readme.md @@ -28,6 +28,14 @@ accepting its associated properties (`type`, `name`, `value` and `form`). ``` +## Accessibility + +### Disabled buttons + +Generally speaking, `disabled` elements are considered a bad pattern for a11y. They are invisible to assistive technology and do not provide the reason for which they are disabled. +To partially address the problem, disabled elements are kept focusable (other interactions are still prevented). +Still, the consumer's responsible for providing the reason for a disabled element. + ## Properties diff --git a/src/elements/menu/menu-button/readme.md b/src/elements/menu/menu-button/readme.md index 35976dc18a..fa4317a543 100644 --- a/src/elements/menu/menu-button/readme.md +++ b/src/elements/menu/menu-button/readme.md @@ -26,6 +26,14 @@ accepting its associated properties (`type`, `name`, `value` and `form`). Button ``` +## Accessibility + +### Disabled buttons + +Generally speaking, `disabled` elements are considered a bad pattern for a11y. They are invisible to assistive technology and do not provide the reason for which they are disabled. +To partially address the problem, disabled elements are kept focusable (other interactions are still prevented). +Still, the consumer's responsible for providing the reason for a disabled element. + ## Properties diff --git a/src/elements/tag/tag/readme.md b/src/elements/tag/tag/readme.md index 4fac36ac8b..cc6544e49a 100644 --- a/src/elements/tag/tag/readme.md +++ b/src/elements/tag/tag/readme.md @@ -53,6 +53,12 @@ It's recommended to check the parent's `sbb-tag-group` for the value. The component imitates an `button` element to provide an accessible experience. The state is reflected via `aria-pressed` attribute. +### Disabled elements + +Generally speaking, `disabled` elements are considered a bad pattern for a11y. They are invisible to assistive technology and do not provide the reason for which they are disabled. +To partially address the problem, disabled elements are kept focusable (other interactions are still prevented). +Still, the consumer's responsible for providing the reason for a disabled element. + ## Properties From db267aae8e01144f2c0aec2a340695940ca3c785 Mon Sep 17 00:00:00 2001 From: Jeremias Peier Date: Wed, 4 Sep 2024 18:13:53 +0200 Subject: [PATCH 06/15] fix: review open points --- .../__snapshots__/button-link.snapshot.spec.snap.js | 1 - .../secondary-button-link.snapshot.spec.snap.js | 1 - .../tertiary-button-link.snapshot.spec.snap.js | 1 - .../transparent-button-link.snapshot.spec.snap.js | 1 - src/elements/core/base-elements/link-base-element.ts | 1 - src/elements/core/decorators/host-attributes.ts | 6 +++--- src/elements/core/mixins/disabled-mixin.ts | 9 ++------- .../datepicker-toggle.snapshot.spec.snap.js | 2 ++ .../datepicker/datepicker-toggle/datepicker-toggle.ts | 1 + src/elements/menu/menu-link/menu-link.stories.ts | 2 +- src/elements/menu/menu/menu.ts | 5 +---- .../popover/popover-trigger/popover-trigger.spec.ts | 7 ++----- src/elements/popover/popover-trigger/popover-trigger.ts | 4 ++-- 13 files changed, 14 insertions(+), 27 deletions(-) diff --git a/src/elements/button/button-link/__snapshots__/button-link.snapshot.spec.snap.js b/src/elements/button/button-link/__snapshots__/button-link.snapshot.spec.snap.js index 7fc1b30dc8..799b0f3a6b 100644 --- a/src/elements/button/button-link/__snapshots__/button-link.snapshot.spec.snap.js +++ b/src/elements/button/button-link/__snapshots__/button-link.snapshot.spec.snap.js @@ -69,7 +69,6 @@ snapshots["sbb-button-link renders a disabled sbb-button-link with slotted icon aria-disabled="true" class="sbb-action-base sbb-button-link" href="https://www.sbb.ch" - tabindex="-1" > diff --git a/src/elements/button/secondary-button-link/__snapshots__/secondary-button-link.snapshot.spec.snap.js b/src/elements/button/secondary-button-link/__snapshots__/secondary-button-link.snapshot.spec.snap.js index 127a45a9b2..60ace59b4d 100644 --- a/src/elements/button/secondary-button-link/__snapshots__/secondary-button-link.snapshot.spec.snap.js +++ b/src/elements/button/secondary-button-link/__snapshots__/secondary-button-link.snapshot.spec.snap.js @@ -69,7 +69,6 @@ snapshots["sbb-secondary-button-link renders a disabled sbb-secondary-button-lin aria-disabled="true" class="sbb-action-base sbb-secondary-button-link" href="https://www.sbb.ch" - tabindex="-1" > diff --git a/src/elements/button/tertiary-button-link/__snapshots__/tertiary-button-link.snapshot.spec.snap.js b/src/elements/button/tertiary-button-link/__snapshots__/tertiary-button-link.snapshot.spec.snap.js index 4b43d862db..aeddcf925e 100644 --- a/src/elements/button/tertiary-button-link/__snapshots__/tertiary-button-link.snapshot.spec.snap.js +++ b/src/elements/button/tertiary-button-link/__snapshots__/tertiary-button-link.snapshot.spec.snap.js @@ -69,7 +69,6 @@ snapshots["sbb-tertiary-button-link renders a disabled sbb-tertiary-button-link aria-disabled="true" class="sbb-action-base sbb-tertiary-button-link" href="https://www.sbb.ch" - tabindex="-1" > diff --git a/src/elements/button/transparent-button-link/__snapshots__/transparent-button-link.snapshot.spec.snap.js b/src/elements/button/transparent-button-link/__snapshots__/transparent-button-link.snapshot.spec.snap.js index ed06233dd7..057802aba2 100644 --- a/src/elements/button/transparent-button-link/__snapshots__/transparent-button-link.snapshot.spec.snap.js +++ b/src/elements/button/transparent-button-link/__snapshots__/transparent-button-link.snapshot.spec.snap.js @@ -69,7 +69,6 @@ snapshots["sbb-transparent-button-link renders a disabled sbb-transparent-button aria-disabled="true" class="sbb-action-base sbb-transparent-button-link" href="https://www.sbb.ch" - tabindex="-1" > diff --git a/src/elements/core/base-elements/link-base-element.ts b/src/elements/core/base-elements/link-base-element.ts index baaf479936..28d76c12cd 100644 --- a/src/elements/core/base-elements/link-base-element.ts +++ b/src/elements/core/base-elements/link-base-element.ts @@ -71,7 +71,6 @@ export abstract class SbbLinkBaseElement extends SbbActionBaseElement { target=${this.target || nothing} rel=${this._evaluateRelAttribute()} aria-label=${this.accessibilityLabel || nothing} - tabindex=${this.maybeDisabled ? '-1' : nothing} aria-disabled=${this.maybeDisabled ? 'true' : nothing} > ${this.renderTemplate()} diff --git a/src/elements/core/decorators/host-attributes.ts b/src/elements/core/decorators/host-attributes.ts index e8956e82f3..400eb4c4f0 100644 --- a/src/elements/core/decorators/host-attributes.ts +++ b/src/elements/core/decorators/host-attributes.ts @@ -7,10 +7,10 @@ function applyAttributes( attributes: Record, ): void { for (const [name, value] of Object.entries(attributes)) { - if (value) { - instance.setAttribute(name, value); - } else { + if (!value) { instance.toggleAttribute(name, value !== null); + } else if (!instance.hasAttribute(name)) { + instance.setAttribute(name, value); } } } diff --git a/src/elements/core/mixins/disabled-mixin.ts b/src/elements/core/mixins/disabled-mixin.ts index 873af649bf..7c93f80530 100644 --- a/src/elements/core/mixins/disabled-mixin.ts +++ b/src/elements/core/mixins/disabled-mixin.ts @@ -1,8 +1,6 @@ import type { LitElement, PropertyValues } from 'lit'; import { property } from 'lit/decorators.js'; -import { hostAttributes } from '../decorators.js'; - import type { AbstractConstructor } from './constructor.js'; export declare class SbbDisabledMixinType { @@ -73,16 +71,13 @@ export const SbbDisabledTabIndexActionMixin = >( superClass: T, ): AbstractConstructor & T => { - @hostAttributes({ - tabindex: '0', - }) abstract class SbbFocusableDisabledAction extends SbbDisabledMixin(superClass) implements SbbDisabledMixinType diff --git a/src/elements/datepicker/datepicker-toggle/__snapshots__/datepicker-toggle.snapshot.spec.snap.js b/src/elements/datepicker/datepicker-toggle/__snapshots__/datepicker-toggle.snapshot.spec.snap.js index 5b9a2a3514..2d6e73ce6c 100644 --- a/src/elements/datepicker/datepicker-toggle/__snapshots__/datepicker-toggle.snapshot.spec.snap.js +++ b/src/elements/datepicker/datepicker-toggle/__snapshots__/datepicker-toggle.snapshot.spec.snap.js @@ -21,6 +21,7 @@ snapshots["sbb-datepicker-toggle renders Shadow DOM"] = disabled="" icon-name="calendar-small" role="button" + tabindex="-1" > extends SbbNegativeMixin( icon-name="calendar-small" aria-label=${i18nShowCalendar[this._language.current]} ?disabled=${!isServer && (!this._datePickerElement || this._disabled)} + tabindex=${!isServer && (!this._datePickerElement || this._disabled) ? -1 : 0} ?negative=${this.negative} data-icon-small ${ref((el?: Element) => (this._triggerElement = el as SbbPopoverTriggerElement))} diff --git a/src/elements/menu/menu-link/menu-link.stories.ts b/src/elements/menu/menu-link/menu-link.stories.ts index 679d4c79da..925732d30b 100644 --- a/src/elements/menu/menu-link/menu-link.stories.ts +++ b/src/elements/menu/menu-link/menu-link.stories.ts @@ -129,7 +129,7 @@ const defaultArgs: Args = { rel: undefined, download: false, disabled: false, - 'accessibility-label': accessibilityLabel, + 'accessibility-label': '', }; export const menuLink: StoryObj = { diff --git a/src/elements/menu/menu/menu.ts b/src/elements/menu/menu/menu.ts index 5bd09d01e4..0621896677 100644 --- a/src/elements/menu/menu/menu.ts +++ b/src/elements/menu/menu/menu.ts @@ -148,10 +148,7 @@ export class SbbMenuElement extends SbbNamedSlotListMixin< this.querySelectorAll( 'sbb-menu-button, sbb-menu-link', ), - ).filter( - (el: SbbMenuButtonElement | SbbMenuLinkElement) => - !el.disabled && interactivityChecker.isVisible(el), - ); + ).filter((el: SbbMenuButtonElement | SbbMenuLinkElement) => interactivityChecker.isVisible(el)); const current = enabledActions.findIndex((e: Element) => e === evt.target); const nextIndex = getNextElementIndex(evt, current, enabledActions.length); diff --git a/src/elements/popover/popover-trigger/popover-trigger.spec.ts b/src/elements/popover/popover-trigger/popover-trigger.spec.ts index e4e4422386..a0ea3b50c0 100644 --- a/src/elements/popover/popover-trigger/popover-trigger.spec.ts +++ b/src/elements/popover/popover-trigger/popover-trigger.spec.ts @@ -86,18 +86,15 @@ describe(`sbb-popover-trigger`, () => { expect(popover).to.have.attribute('data-state', 'opened'); }); - it("doesn't focus popover-trigger on keyboard event when disabled", async () => { - const changeSpy = new EventSpy('focus', element); - + it("doesn't open popover when disabled", async () => { element.disabled = true; popover.hoverTrigger = true; await waitForLitRender(element); - element.focus(); + element.click(); await waitForLitRender(element); - expect(changeSpy.count).not.to.be.greaterThan(0); expect(popover).to.have.attribute('data-state', 'closed'); }); }); diff --git a/src/elements/popover/popover-trigger/popover-trigger.ts b/src/elements/popover/popover-trigger/popover-trigger.ts index 58acc5b8b8..f0cde4e3b9 100644 --- a/src/elements/popover/popover-trigger/popover-trigger.ts +++ b/src/elements/popover/popover-trigger/popover-trigger.ts @@ -3,7 +3,7 @@ import { customElement } from 'lit/decorators.js'; import { SbbButtonBaseElement } from '../../core/base-elements.js'; import { hostContext } from '../../core/dom.js'; -import { SbbDisabledTabIndexActionMixin, SbbNegativeMixin } from '../../core/mixins.js'; +import { SbbFocusableDisabledActionMixin, SbbNegativeMixin } from '../../core/mixins.js'; import { SbbIconNameMixin } from '../../icon.js'; import style from './popover-trigger.scss?lit&inline'; @@ -14,7 +14,7 @@ import style from './popover-trigger.scss?lit&inline'; * @slot - Use the unnamed slot to add content to the `sbb-popover-trigger`. */ @customElement('sbb-popover-trigger') -export class SbbPopoverTriggerElement extends SbbDisabledTabIndexActionMixin( +export class SbbPopoverTriggerElement extends SbbFocusableDisabledActionMixin( SbbNegativeMixin(SbbIconNameMixin(SbbButtonBaseElement)), ) { public static override styles: CSSResultGroup = style; From e3cafe28d92dfd534ba7ded621fccd7f73f4a953 Mon Sep 17 00:00:00 2001 From: Jeremias Peier Date: Thu, 5 Sep 2024 09:25:39 +0200 Subject: [PATCH 07/15] fix: fix hostAttributes logic --- .../core/decorators/host-attributes.ts | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/elements/core/decorators/host-attributes.ts b/src/elements/core/decorators/host-attributes.ts index 400eb4c4f0..438741dffb 100644 --- a/src/elements/core/decorators/host-attributes.ts +++ b/src/elements/core/decorators/host-attributes.ts @@ -35,22 +35,41 @@ function applyAttributes( export const hostAttributes = (attributes: Record) => (target: AbstractConstructor) => (target as typeof ReactiveElement).addInitializer((instance: ReactiveElement) => { + const instanceWithHostAttributes = instance as ReactiveElement & { + hostAttributes: Record; + hostAttributeControllers: any[]; + }; + instanceWithHostAttributes.hostAttributes = { + ...(instanceWithHostAttributes.hostAttributes ?? {}), + ...attributes, + }; + if (!instanceWithHostAttributes.hostAttributeControllers) { + instanceWithHostAttributes.hostAttributeControllers = []; + } + if (isServer) { - applyAttributes(instance, attributes); + // TODO: Check whether we can accept having potential wrong attributes on SSR + applyAttributes(instanceWithHostAttributes, instanceWithHostAttributes.hostAttributes); } else { // It is not allowed to set attributes during constructor phase. Due to this we use a // controller to assign the attributes during lit initialization phase. // HostConnected or hostUpdate can be called either order. Due to that we apply in the // first occurrence and directly remove the controller, so it's only called once. - instance.addController({ + const controller = { hostConnected() { - applyAttributes(instance, attributes); - instance.removeController(this); + applyAttributes(instanceWithHostAttributes, instanceWithHostAttributes.hostAttributes); + instanceWithHostAttributes.hostAttributeControllers.forEach((cont) => + instanceWithHostAttributes.removeController(cont), + ); }, hostUpdate() { - applyAttributes(instance, attributes); - instance.removeController(this); + applyAttributes(instanceWithHostAttributes, instanceWithHostAttributes.hostAttributes); + instanceWithHostAttributes.hostAttributeControllers.forEach((cont) => + instanceWithHostAttributes.removeController(cont), + ); }, - }); + }; + instanceWithHostAttributes.addController(controller); + instanceWithHostAttributes.hostAttributeControllers.push(controller); } }); From 152e5dddb400cd9bce982b9ea3ef7c05038609be Mon Sep 17 00:00:00 2001 From: Jeremias Peier Date: Thu, 5 Sep 2024 10:26:04 +0200 Subject: [PATCH 08/15] fix: fix it the other way --- .../core/decorators/host-attributes.ts | 39 +++++-------------- .../datepicker-toggle/datepicker-toggle.ts | 14 ++++++- 2 files changed, 22 insertions(+), 31 deletions(-) diff --git a/src/elements/core/decorators/host-attributes.ts b/src/elements/core/decorators/host-attributes.ts index 438741dffb..e8956e82f3 100644 --- a/src/elements/core/decorators/host-attributes.ts +++ b/src/elements/core/decorators/host-attributes.ts @@ -7,10 +7,10 @@ function applyAttributes( attributes: Record, ): void { for (const [name, value] of Object.entries(attributes)) { - if (!value) { - instance.toggleAttribute(name, value !== null); - } else if (!instance.hasAttribute(name)) { + if (value) { instance.setAttribute(name, value); + } else { + instance.toggleAttribute(name, value !== null); } } } @@ -35,41 +35,22 @@ function applyAttributes( export const hostAttributes = (attributes: Record) => (target: AbstractConstructor) => (target as typeof ReactiveElement).addInitializer((instance: ReactiveElement) => { - const instanceWithHostAttributes = instance as ReactiveElement & { - hostAttributes: Record; - hostAttributeControllers: any[]; - }; - instanceWithHostAttributes.hostAttributes = { - ...(instanceWithHostAttributes.hostAttributes ?? {}), - ...attributes, - }; - if (!instanceWithHostAttributes.hostAttributeControllers) { - instanceWithHostAttributes.hostAttributeControllers = []; - } - if (isServer) { - // TODO: Check whether we can accept having potential wrong attributes on SSR - applyAttributes(instanceWithHostAttributes, instanceWithHostAttributes.hostAttributes); + applyAttributes(instance, attributes); } else { // It is not allowed to set attributes during constructor phase. Due to this we use a // controller to assign the attributes during lit initialization phase. // HostConnected or hostUpdate can be called either order. Due to that we apply in the // first occurrence and directly remove the controller, so it's only called once. - const controller = { + instance.addController({ hostConnected() { - applyAttributes(instanceWithHostAttributes, instanceWithHostAttributes.hostAttributes); - instanceWithHostAttributes.hostAttributeControllers.forEach((cont) => - instanceWithHostAttributes.removeController(cont), - ); + applyAttributes(instance, attributes); + instance.removeController(this); }, hostUpdate() { - applyAttributes(instanceWithHostAttributes, instanceWithHostAttributes.hostAttributes); - instanceWithHostAttributes.hostAttributeControllers.forEach((cont) => - instanceWithHostAttributes.removeController(cont), - ); + applyAttributes(instance, attributes); + instance.removeController(this); }, - }; - instanceWithHostAttributes.addController(controller); - instanceWithHostAttributes.hostAttributeControllers.push(controller); + }); } }); diff --git a/src/elements/datepicker/datepicker-toggle/datepicker-toggle.ts b/src/elements/datepicker/datepicker-toggle/datepicker-toggle.ts index a4729ab4c8..e74ab57201 100644 --- a/src/elements/datepicker/datepicker-toggle/datepicker-toggle.ts +++ b/src/elements/datepicker/datepicker-toggle/datepicker-toggle.ts @@ -104,6 +104,12 @@ export class SbbDatepickerToggleElement extends SbbNegativeMixin( this._datePickerController?.abort(); } + public override firstUpdated(changedProperties: PropertyValues): void { + super.firstUpdated(changedProperties); + // We have to rewrite the tabindex of the popover-trigger as the popover trigger itself sets the tabindex to always 0. + this._triggerElement.tabIndex = this._isDisabled() ? -1 : 0; + } + private _init(datePicker?: string | SbbDatepickerElement): void { this._datePickerController?.abort(); this._datePickerController = new AbortController(); @@ -190,13 +196,17 @@ export class SbbDatepickerToggleElement extends SbbNegativeMixin( return this._datePickerElement?.hasCustomNow() ? this._datePickerElement.now : undefined; } + private _isDisabled(): boolean { + return !isServer && (!this._datePickerElement || this._disabled); + } + protected override render(): TemplateResult { return html` (this._triggerElement = el as SbbPopoverTriggerElement))} From b6e5e1b5359a60eec6c82c31b7b65f4c0d504f53 Mon Sep 17 00:00:00 2001 From: Jeremias Peier Date: Thu, 5 Sep 2024 10:45:58 +0200 Subject: [PATCH 09/15] refactor: use mini button instead of popover trigger --- .../datepicker-toggle.snapshot.spec.snap.js | 24 +++++++++--------- .../datepicker-toggle/datepicker-toggle.scss | 2 +- .../datepicker-toggle.spec.ts | 25 +++++++++---------- .../datepicker-toggle/datepicker-toggle.ts | 20 ++++++++------- 4 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/elements/datepicker/datepicker-toggle/__snapshots__/datepicker-toggle.snapshot.spec.snap.js b/src/elements/datepicker/datepicker-toggle/__snapshots__/datepicker-toggle.snapshot.spec.snap.js index 2d6e73ce6c..f53c8eb612 100644 --- a/src/elements/datepicker/datepicker-toggle/__snapshots__/datepicker-toggle.snapshot.spec.snap.js +++ b/src/elements/datepicker/datepicker-toggle/__snapshots__/datepicker-toggle.snapshot.spec.snap.js @@ -8,22 +8,22 @@ snapshots["sbb-datepicker-toggle renders DOM"] = /* end snapshot sbb-datepicker-toggle renders DOM */ snapshots["sbb-datepicker-toggle renders Shadow DOM"] = -` + +