diff --git a/src/elements/checkbox/checkbox-group/checkbox-group.scss b/src/elements/checkbox/checkbox-group/checkbox-group.scss index 58d0f4c71b..4363e6089f 100644 --- a/src/elements/checkbox/checkbox-group/checkbox-group.scss +++ b/src/elements/checkbox/checkbox-group/checkbox-group.scss @@ -29,7 +29,7 @@ $breakpoints: 'zero', 'micro', 'small', 'medium', 'large', 'wide', 'ultra'; } } -:host([data-has-selection-expansion-panel]) { +:host([data-has-panel]) { --sbb-checkbox-group-width: 100%; ::slotted(sbb-checkbox-panel) { @@ -37,7 +37,7 @@ $breakpoints: 'zero', 'micro', 'small', 'medium', 'large', 'wide', 'ultra'; } } -:host([data-has-selection-expansion-panel][orientation='vertical']) { +:host([data-has-panel][orientation='vertical']) { --sbb-checkbox-group-gap: var(--sbb-spacing-fixed-2x) var(--sbb-spacing-fixed-4x); } @@ -53,11 +53,7 @@ $breakpoints: 'zero', 'micro', 'small', 'medium', 'large', 'wide', 'ultra'; } } - :host( - [orientation='vertical'][horizontal-from='#{$breakpoint}']:not( - [data-has-selection-expansion-panel] - ) - ) { + :host([orientation='vertical'][horizontal-from='#{$breakpoint}']:not([data-has-panel])) { --sbb-checkbox-group-width: max-content; } } diff --git a/src/elements/checkbox/checkbox-group/checkbox-group.ts b/src/elements/checkbox/checkbox-group/checkbox-group.ts index d86ac589c3..72f5baf99b 100644 --- a/src/elements/checkbox/checkbox-group/checkbox-group.ts +++ b/src/elements/checkbox/checkbox-group/checkbox-group.ts @@ -57,7 +57,7 @@ export class SbbCheckboxGroupElement extends SbbDisabledMixin(LitElement) { const signal = this._abort.signal; this.addEventListener('keydown', (e) => this._handleKeyDown(e), { signal }); this.toggleAttribute( - 'data-has-selection-expansion-panel', + 'data-has-panel', !!this.querySelector?.('sbb-selection-expansion-panel, sbb-checkbox-panel'), ); } diff --git a/src/elements/checkbox/checkbox-panel/readme.md b/src/elements/checkbox/checkbox-panel/readme.md index 7a27a94bd8..80cb20c72a 100644 --- a/src/elements/checkbox/checkbox-panel/readme.md +++ b/src/elements/checkbox/checkbox-panel/readme.md @@ -2,10 +2,14 @@ The `sbb-checkbox-panel` component provides the same functionality as a native ` ## Slots -It is possible to provide a label via an unnamed slot; additionally the slote named `subtext` can be used to provide a subtext and the slot named `suffix` can be used to provide suffix items. +It is possible to provide a label via an unnamed slot; +additionally the slots named `subtext` can be used to provide a subtext and +the slot named `suffix` can be used to provide suffix items. +If you use a , the slot `badge` is automatically assigned. ```html + % Label Subtext Suffix diff --git a/src/elements/radio-button/radio-button-group/radio-button-group.scss b/src/elements/radio-button/radio-button-group/radio-button-group.scss index bd80a77cba..2eb4e8dd86 100644 --- a/src/elements/radio-button/radio-button-group/radio-button-group.scss +++ b/src/elements/radio-button/radio-button-group/radio-button-group.scss @@ -31,11 +31,11 @@ $breakpoints: 'zero', 'micro', 'small', 'medium', 'large', 'wide', 'ultra'; } } -:host([data-has-selection-expansion-panel]) { +:host([data-has-panel]) { --sbb-radio-button-group-width: 100%; } -:host([data-has-selection-expansion-panel][orientation='vertical']) { +:host([data-has-panel][orientation='vertical']) { --sbb-radio-button-group-gap: var(--sbb-spacing-fixed-2x) var(--sbb-spacing-fixed-4x); } @@ -51,11 +51,7 @@ $breakpoints: 'zero', 'micro', 'small', 'medium', 'large', 'wide', 'ultra'; } } - :host( - [orientation='vertical'][horizontal-from='#{$breakpoint}']:not( - [data-has-selection-expansion-panel] - ) - ) { + :host([orientation='vertical'][horizontal-from='#{$breakpoint}']:not([data-has-panel])) { --sbb-radio-button-group-width: max-content; } } diff --git a/src/elements/radio-button/radio-button-group/radio-button-group.ts b/src/elements/radio-button/radio-button-group/radio-button-group.ts index 0ab3a7397e..79c32e6be2 100644 --- a/src/elements/radio-button/radio-button-group/radio-button-group.ts +++ b/src/elements/radio-button/radio-button-group/radio-button-group.ts @@ -8,7 +8,6 @@ import { hostAttributes } from '../../core/decorators.js'; import { EventEmitter } from '../../core/eventing.js'; import type { SbbHorizontalFrom, SbbOrientation, SbbStateChange } from '../../core/interfaces.js'; import { SbbDisabledMixin } from '../../core/mixins.js'; -import type { SbbSelectionExpansionPanelElement } from '../../selection-expansion-panel.js'; import type { SbbRadioButtonSize, SbbRadioButtonStateChange } from '../common.js'; import type { SbbRadioButtonPanelElement } from '../radio-button-panel.js'; import type { SbbRadioButtonElement } from '../radio-button.js'; @@ -92,7 +91,7 @@ export class SbbRadioButtonGroupElement extends SbbDisabledMixin(LitElement) { } } - private _hasPanelElement: boolean = false; + private _hasSelectionExpansionPanelElement: boolean = false; private _didLoad = false; private _abort = new SbbConnectedAbortController(this); @@ -147,10 +146,13 @@ export class SbbRadioButtonGroupElement extends SbbDisabledMixin(LitElement) { }, ); this.addEventListener('keydown', (e) => this._handleKeyDown(e), { signal }); - this._hasPanelElement = !!this.querySelector?.( - 'sbb-selection-expansion-panel, sbb-radio-button-panel', + this._hasSelectionExpansionPanelElement = !!this.querySelector?.( + 'sbb-selection-expansion-panel', + ); + this.toggleAttribute( + 'data-has-panel', + !!this.querySelector?.('sbb-selection-expansion-panel, sbb-radio-button-panel'), ); - this.toggleAttribute('data-has-selection-expansion-panel', this._hasPanelElement); this._updateRadios(this.value); } @@ -239,11 +241,8 @@ export class SbbRadioButtonGroupElement extends SbbDisabledMixin(LitElement) { private _getRadioTabIndex(radio: SbbRadioButtonElement | SbbRadioButtonPanelElement): number { const isSelected: boolean = radio.checked && !radio.disabled && !this.disabled; - const isParentPanelWithContent: boolean = - radio.parentElement?.localName === 'sbb-selection-expansion-panel' && - (radio.parentElement as SbbSelectionExpansionPanelElement).hasContent; - return isSelected || (this._hasPanelElement && isParentPanelWithContent) ? 0 : -1; + return isSelected || this._hasSelectionExpansionPanelElement ? 0 : -1; } private _handleKeyDown(evt: KeyboardEvent): void { @@ -269,11 +268,7 @@ export class SbbRadioButtonGroupElement extends SbbDisabledMixin(LitElement) { ); const nextIndex: number = getNextElementIndex(evt, current, enabledRadios.length); - // Selection on arrow keypress is allowed only if all the selection-panels have no content. - const allPanelsHaveNoContent: boolean = ( - Array.from(this.querySelectorAll?.('sbb-selection-expansion-panel')) || [] - ).every((e: SbbSelectionExpansionPanelElement) => !e.hasContent); - if (!this._hasPanelElement || (this._hasPanelElement && allPanelsHaveNoContent)) { + if (!this._hasSelectionExpansionPanelElement) { enabledRadios[nextIndex].select(); } diff --git a/src/elements/radio-button/radio-button-panel/readme.md b/src/elements/radio-button/radio-button-panel/readme.md index 19041ee304..78151f4360 100644 --- a/src/elements/radio-button/radio-button-panel/readme.md +++ b/src/elements/radio-button/radio-button-panel/readme.md @@ -9,10 +9,14 @@ The `sbb-radio-button-panel` component provides the same functionality as a nati ## Slots -It is possible to provide a label via an unnamed slot; additionally the slote named `subtext` can be used to provide a subtext and the slot named `suffix` can be used to provide suffix items. +It is possible to provide a label via an unnamed slot; +additionally the slots named `subtext` can be used to provide a subtext and +the slot named `suffix` can be used to provide suffix items. +If you use a , the slot `badge` is automatically assigned. ```html + % Label Subtext Suffix diff --git a/src/elements/selection-expansion-panel/__snapshots__/selection-expansion-panel.snapshot.spec.snap.js b/src/elements/selection-expansion-panel/__snapshots__/selection-expansion-panel.snapshot.spec.snap.js index a23612fc31..dedcbd0ac0 100644 --- a/src/elements/selection-expansion-panel/__snapshots__/selection-expansion-panel.snapshot.spec.snap.js +++ b/src/elements/selection-expansion-panel/__snapshots__/selection-expansion-panel.snapshot.spec.snap.js @@ -25,15 +25,7 @@ snapshots["sbb-selection-expansion-panel renders DOM"] = role="text" slot="badge" > - - % - - - from CHF - - - 19.99 - + %
@@ -76,7 +68,7 @@ snapshots["sbb-selection-expansion-panel renders A11y tree Chrome"] = "children": [ { "role": "checkbox", - "name": "% from CHF 19.99 ​ Value one Suffix Subtext , collapsed", + "name": "% ​ Value one Suffix Subtext , collapsed", "checked": false } ] @@ -93,7 +85,7 @@ snapshots["sbb-selection-expansion-panel renders A11y tree Firefox"] = "children": [ { "role": "checkbox", - "name": "% from CHF 19.99 ​ Value one Suffix Subtext , collapsed" + "name": "% ​ Value one Suffix Subtext , collapsed" } ] } diff --git a/src/elements/selection-expansion-panel/readme.md b/src/elements/selection-expansion-panel/readme.md index ee6d61659f..0480d6c071 100644 --- a/src/elements/selection-expansion-panel/readme.md +++ b/src/elements/selection-expansion-panel/readme.md @@ -1,5 +1,5 @@ The `sbb-selection-expansion-panel` component wraps either a [sbb-checkbox-panel](/docs/elements-sbb-checkbox-sbb-checkbox-panel--docs) -or a [sbb-radio-button-panel](/docs/elements-sbb-radio-button-sbb-radio-button-panel--docs) that can optionally toggle a content section. +or a [sbb-radio-button-panel](/docs/elements-sbb-radio-button-sbb-radio-button-panel--docs) that can toggle a content section. The content section can be opened by checking `sbb-checkbox-panel` or selecting the `sbb-radio-button-panel`. Additionally, clicking on all the upper area sets the checked state and therefore opens the content; @@ -13,12 +13,8 @@ or a [sbb-checkbox-group](/docs/elements-sbb-checkbox-sbb-checkbox-group--docs). ```html - - % - from CHF - 19.99 - + % Value Subtext @@ -37,12 +33,8 @@ or a [sbb-checkbox-group](/docs/elements-sbb-checkbox-sbb-checkbox-group--docs). ```html - - % - from CHF - 19.99 - + % Value Subtext diff --git a/src/elements/selection-expansion-panel/selection-expansion-panel.snapshot.spec.ts b/src/elements/selection-expansion-panel/selection-expansion-panel.snapshot.spec.ts index eb8003588b..e677645a99 100644 --- a/src/elements/selection-expansion-panel/selection-expansion-panel.snapshot.spec.ts +++ b/src/elements/selection-expansion-panel/selection-expansion-panel.snapshot.spec.ts @@ -14,19 +14,13 @@ describe(`sbb-selection-expansion-panel`, () => { describe('renders', () => { beforeEach(async () => { - // Note: for easier testing, we add the slot="badge" - // to which would not be needed in real. element = await fixture(html` Value one Subtext Suffix - - % - from CHF - 19.99 - + %
Inner content
diff --git a/src/elements/selection-expansion-panel/selection-expansion-panel.spec.ts b/src/elements/selection-expansion-panel/selection-expansion-panel.spec.ts index 731af9e33a..90a39fb47a 100644 --- a/src/elements/selection-expansion-panel/selection-expansion-panel.spec.ts +++ b/src/elements/selection-expansion-panel/selection-expansion-panel.spec.ts @@ -8,7 +8,6 @@ import { type SbbCheckboxElement, type SbbCheckboxGroupElement, } from '../checkbox.js'; -import { tabKey } from '../core/testing/private/keys.js'; import { fixture } from '../core/testing/private.js'; import { EventSpy, waitForCondition, waitForLitRender } from '../core/testing.js'; import { @@ -142,9 +141,7 @@ describe(`sbb-selection-expansion-panel`, () => { willOpenEventSpy = new EventSpy(SbbSelectionExpansionPanelElement.events.willOpen); didOpenEventSpy = new EventSpy(SbbSelectionExpansionPanelElement.events.didOpen); - wrapper = await fixture(getPageContent('radio-button'), { - modules: ['./selection-expansion-panel.ts', '../button.ts', '../radio-button.ts'], - }); + wrapper = await fixture(getPageContent('radio-button')); elements = Array.from(wrapper.querySelectorAll('sbb-selection-expansion-panel')); firstPanel = wrapper.querySelector( '#sbb-selection-expansion-panel-1', @@ -265,81 +262,6 @@ describe(`sbb-selection-expansion-panel`, () => { }); }); - describe('with radio group with no slotted content', () => { - it('focus selected, the focus and select on keyboard navigation', async () => { - const wrapperNoContent = await fixture( - html` - - - Value one - - - Value two - - - Value three - - - Value four - - - `, - { - modules: ['./selection-expansion-panel.ts', '../radio-button.ts'], - }, - ); - const firstInputNoContent = - wrapperNoContent.querySelector('#input-no-content-1')!; - const secondInputNoContent = - wrapperNoContent.querySelector('#input-no-content-2')!; - const fourthInputNoContent = - wrapperNoContent.querySelector('#input-no-content-4')!; - const firstPanel = - wrapperNoContent.querySelector('#no-content-1')!; - const secondPanel = - wrapperNoContent.querySelector('#no-content-2')!; - - expect(firstPanel).to.have.attribute('data-state', 'closed'); - expect(secondPanel).to.have.attribute('data-state', 'closed'); - - await sendKeys({ press: tabKey }); - await waitForLitRender(wrapperNoContent); - expect(document.activeElement!.id).to.be.equal(secondInputNoContent.id); - - await sendKeys({ press: 'ArrowUp' }); - await waitForLitRender(wrapperNoContent); - expect(document.activeElement!.id).to.be.equal(firstInputNoContent.id); - expect(secondInputNoContent.checked).to.be.false; - expect(firstInputNoContent.checked).to.be.true; - - await sendKeys({ press: 'ArrowRight' }); - await waitForLitRender(wrapperNoContent); - expect(document.activeElement!.id).to.be.equal(secondInputNoContent.id); - expect(firstInputNoContent.checked).to.be.false; - expect(secondInputNoContent.checked).to.be.true; - - await sendKeys({ press: 'ArrowDown' }); - await waitForLitRender(wrapperNoContent); - expect(document.activeElement!.id).to.be.equal(fourthInputNoContent.id); - expect(secondInputNoContent.checked).to.be.false; - expect(fourthInputNoContent.checked).to.be.true; - - await sendKeys({ press: 'ArrowLeft' }); - await waitForLitRender(wrapperNoContent); - expect(document.activeElement!.id).to.be.equal(secondInputNoContent.id); - expect(fourthInputNoContent.checked).to.be.false; - expect(secondInputNoContent.checked).to.be.true; - }); - }); - describe('with nested radio buttons', () => { let nestedElement: SbbRadioButtonGroupElement; let panel1: SbbSelectionExpansionPanelElement; @@ -355,31 +277,26 @@ describe(`sbb-selection-expansion-panel`, () => { willCloseEventSpy = new EventSpy(SbbSelectionExpansionPanelElement.events.willClose); didCloseEventSpy = new EventSpy(SbbSelectionExpansionPanelElement.events.didClose); - nestedElement = await fixture( - html` - - - - Main Option 1 - - Suboption 1 - Suboption 2 - - - - - Main Option 2 - - Suboption 3 - Suboption 4 - - - - `, - { - modules: ['./selection-expansion-panel.ts', '../radio-button.ts'], - }, - ); + nestedElement = await fixture(html` + + + + Main Option 1 + + Suboption 1 + Suboption 2 + + + + + Main Option 2 + + Suboption 3 + Suboption 4 + + + + `); panel1 = nestedElement.querySelector('#panel1')!; panel2 = nestedElement.querySelector('#panel2')!; }); @@ -497,36 +414,31 @@ describe(`sbb-selection-expansion-panel`, () => { describe('with template tag manipulation', () => { it('should initialize the group correctly after append', async () => { - const root = await fixture( - html` -
- - - -
- `, - { - modules: ['./selection-expansion-panel.ts', '../radio-button.ts'], - }, - ); + const root = await fixture(html` +
+ + + +
+ `); const radioGroup = root.querySelector('sbb-radio-button-group')!; const selectionPanels = Array.from( @@ -568,9 +480,7 @@ describe(`sbb-selection-expansion-panel`, () => { willCloseEventSpy = new EventSpy(SbbSelectionExpansionPanelElement.events.willClose); didCloseEventSpy = new EventSpy(SbbSelectionExpansionPanelElement.events.didClose); - wrapper = await fixture(getPageContent('checkbox'), { - modules: ['./selection-expansion-panel.ts', '../button.ts', '../checkbox.ts'], - }); + wrapper = await fixture(getPageContent('checkbox')); elements = Array.from(wrapper.querySelectorAll('sbb-selection-expansion-panel')); firstPanel = wrapper.querySelector( '#sbb-selection-expansion-panel-1', @@ -708,28 +618,25 @@ describe(`sbb-selection-expansion-panel`, () => { let nestedElement: SbbCheckboxGroupElement; beforeEach(async () => { - nestedElement = await fixture( - html` - - - Main Option 1 - - Suboption 1 - Suboption 2 - - - - - Main Option 2 - - Suboption 3 - Suboption 4 - - - - `, - { modules: ['../checkbox.ts', './selection-expansion-panel.ts'] }, - ); + nestedElement = await fixture(html` + + + Main Option 1 + + Suboption 1 + Suboption 2 + + + + + Main Option 2 + + Suboption 3 + Suboption 4 + + + + `); }); it('should display expanded label correctly', async () => { diff --git a/src/elements/selection-expansion-panel/selection-expansion-panel.ts b/src/elements/selection-expansion-panel/selection-expansion-panel.ts index 8209cfafe9..9030d5ae11 100644 --- a/src/elements/selection-expansion-panel/selection-expansion-panel.ts +++ b/src/elements/selection-expansion-panel/selection-expansion-panel.ts @@ -100,9 +100,8 @@ export class SbbSelectionExpansionPanelElement extends SbbHydrationMixin(LitElem /** * Whether it has an expandable content - * @internal */ - public get hasContent(): boolean { + private get _hasContent(): boolean { // We cannot use the NamedSlots because it's too slow to initialize return this.querySelectorAll?.('[slot="content"]').length > 0; } @@ -137,7 +136,7 @@ export class SbbSelectionExpansionPanelElement extends SbbHydrationMixin(LitElem } private _updateState(): void { - if (!this.hasContent) { + if (!this._hasContent) { return; } @@ -208,7 +207,7 @@ export class SbbSelectionExpansionPanelElement extends SbbHydrationMixin(LitElem return; } - if (!this.hasContent) { + if (!this._hasContent) { panelElement.expansionState = ''; return; }