From 3957f462003089cfb4b8f9497d9db18a914c0db8 Mon Sep 17 00:00:00 2001 From: Davide Mininni Date: Wed, 28 Aug 2024 10:44:44 +0200 Subject: [PATCH] feat: add size s with bottom-up approach --- .../checkbox/checkbox-group/checkbox-group.ts | 13 ------- .../checkbox/checkbox-panel/checkbox-panel.ts | 30 +++++++++++++--- src/elements/core/mixins/panel-mixin.ts | 4 +++ .../radio-button-group/radio-button-group.ts | 13 ------- .../radio-button-panel/radio-button-panel.ts | 34 ++++++++++++++----- 5 files changed, 55 insertions(+), 39 deletions(-) diff --git a/src/elements/checkbox/checkbox-group/checkbox-group.ts b/src/elements/checkbox/checkbox-group/checkbox-group.ts index 3109002d48d..b26a4150d48 100644 --- a/src/elements/checkbox/checkbox-group/checkbox-group.ts +++ b/src/elements/checkbox/checkbox-group/checkbox-group.ts @@ -7,7 +7,6 @@ import { SbbConnectedAbortController } from '../../core/controllers.js'; import { slotState } from '../../core/decorators.js'; import type { SbbHorizontalFrom, SbbOrientation } from '../../core/interfaces.js'; import { SbbDisabledMixin } from '../../core/mixins.js'; -import type { SbbSelectionExpansionPanelElement } from '../../selection-expansion-panel.js'; import type { SbbCheckboxPanelElement } from '../checkbox-panel.js'; import type { SbbCheckboxElement } from '../checkbox.js'; import type { SbbCheckboxSize } from '../common.js'; @@ -48,15 +47,6 @@ export class SbbCheckboxGroupElement extends SbbDisabledMixin(LitElement) { ); } - /** List of contained selection-expansion-panel elements. */ - private get _expansionPanels(): SbbSelectionExpansionPanelElement[] { - return ( - Array.from(this.querySelectorAll?.('sbb-selection-expansion-panel') ?? []).filter( - (el) => el.closest('sbb-checkbox-group') === this, - ) - ); - } - private _abort: SbbConnectedAbortController = new SbbConnectedAbortController(this); public override connectedCallback(): void { @@ -80,9 +70,6 @@ export class SbbCheckboxGroupElement extends SbbDisabledMixin(LitElement) { } if (changedProperties.has('size')) { this.checkboxes.forEach((c) => c.requestUpdate?.('size')); - this._expansionPanels.forEach((e) => - e.setAttribute('data-size', this.size === 'xs' ? 's' : this.size), - ); } } diff --git a/src/elements/checkbox/checkbox-panel/checkbox-panel.ts b/src/elements/checkbox/checkbox-panel/checkbox-panel.ts index c6ea63bb1a4..97fb8fd2378 100644 --- a/src/elements/checkbox/checkbox-panel/checkbox-panel.ts +++ b/src/elements/checkbox/checkbox-panel/checkbox-panel.ts @@ -19,8 +19,10 @@ import { panelCommonStyle, SbbPanelMixin, type SbbPanelSize, + panelObserverConfig, SbbUpdateSchedulerMixin, } from '../../core/mixins.js'; +import { AgnosticMutationObserver } from '../../core/observers.js'; import { checkboxCommonStyle, SbbCheckboxCommonElementMixin } from '../common.js'; import '../../screen-reader-only.js'; @@ -77,6 +79,25 @@ export class SbbCheckboxPanelElement extends SbbPanelMixin( { bubbles: true }, ); + private _panelAttributeObserver = new AgnosticMutationObserver( + (mutationsList: MutationRecord[]) => this._onPanelAttributesChange(mutationsList), + ); + + private _onPanelAttributesChange(mutationsList: MutationRecord[]): void { + for (const mutation of mutationsList) { + if (mutation.attributeName === 'size') { + if (!this.group || this.group.size === this.size) { + this.closest?.('sbb-selection-expansion-panel')?.setAttribute('data-size', this.size); + } + } + } + } + + public override connectedCallback(): void { + super.connectedCallback(); + this._panelAttributeObserver.observe(this, panelObserverConfig); + } + protected override async willUpdate(changedProperties: PropertyValues): Promise { super.willUpdate(changedProperties); @@ -93,12 +114,11 @@ export class SbbCheckboxPanelElement extends SbbPanelMixin( this.stateChange.emit({ type: 'disabled', disabled: this.disabled }); } } + } - if (changedProperties.has('size')) { - if (!this.group) { - this.closest?.('sbb-selection-expansion-panel')?.setAttribute('data-size', this.size); - } - } + public override disconnectedCallback(): void { + super.disconnectedCallback(); + this._panelAttributeObserver.disconnect(); } protected override render(): TemplateResult { diff --git a/src/elements/core/mixins/panel-mixin.ts b/src/elements/core/mixins/panel-mixin.ts index 447fc9bb96f..5480f9af52e 100644 --- a/src/elements/core/mixins/panel-mixin.ts +++ b/src/elements/core/mixins/panel-mixin.ts @@ -13,6 +13,10 @@ export declare class SbbPanelMixinType { export type SbbPanelSize = 's' | 'm'; +export const panelObserverConfig: MutationObserverInit = { + attributeFilter: ['size'], +}; + /** * Mixin for common panel behaviors */ 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 ef44d1621fc..ed100e5c05f 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, slotState } 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 { SbbRadioButtonStateChange, SbbRadioButtonSize } from '../common.js'; import type { SbbRadioButtonPanelElement } from '../radio-button-panel.js'; import type { SbbRadioButtonElement } from '../radio-button.js'; @@ -87,15 +86,6 @@ export class SbbRadioButtonGroupElement extends SbbDisabledMixin(LitElement) { ).filter((el) => el.closest?.('sbb-radio-button-group') === this); } - /** List of contained selection-expansion-panel elements. */ - private get _expansionPanels(): SbbSelectionExpansionPanelElement[] { - return ( - Array.from(this.querySelectorAll?.('sbb-selection-expansion-panel') ?? []).filter( - (el) => el.closest('sbb-radio-button-group') === this, - ) - ); - } - private get _enabledRadios(): (SbbRadioButtonElement | SbbRadioButtonPanelElement)[] | undefined { if (!this.disabled) { return this.radioButtons.filter((r) => !r.disabled); @@ -180,9 +170,6 @@ export class SbbRadioButtonGroupElement extends SbbDisabledMixin(LitElement) { } if (changedProperties.has('size')) { this.radioButtons.forEach((r) => r.requestUpdate?.('size')); - this._expansionPanels.forEach((e) => - e.setAttribute('data-size', this.size === 'xs' ? 's' : this.size), - ); } } diff --git a/src/elements/radio-button/radio-button-panel/radio-button-panel.ts b/src/elements/radio-button/radio-button-panel/radio-button-panel.ts index b72e2894cef..8e49ca135ba 100644 --- a/src/elements/radio-button/radio-button-panel/radio-button-panel.ts +++ b/src/elements/radio-button/radio-button-panel/radio-button-panel.ts @@ -13,8 +13,10 @@ import { panelCommonStyle, SbbPanelMixin, type SbbPanelSize, + panelObserverConfig, SbbUpdateSchedulerMixin, } from '../../core/mixins.js'; +import { AgnosticMutationObserver } from '../../core/observers.js'; import { radioButtonCommonStyle, SbbRadioButtonCommonElementMixin } from '../common.js'; import '../../screen-reader-only.js'; @@ -41,9 +43,7 @@ export class SbbRadioButtonPanelElement extends SbbPanelMixin( panelConnected: 'panelConnected', } as const; - /** - * Size variant. - */ + /** Size variant. */ @property({ reflect: true }) public set size(value: SbbPanelSize) { this._size = value; @@ -53,18 +53,36 @@ export class SbbRadioButtonPanelElement extends SbbPanelMixin( } private _size: SbbPanelSize = 'm'; + private _panelAttributeObserver = new AgnosticMutationObserver( + (mutationsList: MutationRecord[]) => this._onPanelAttributesChange(mutationsList), + ); + + private _onPanelAttributesChange(mutationsList: MutationRecord[]): void { + for (const mutation of mutationsList) { + if (mutation.attributeName === 'size') { + if (!this.group || this.group.size === this.size) { + this.closest?.('sbb-selection-expansion-panel')?.setAttribute('data-size', this.size); + } + } + } + } + + public override connectedCallback(): void { + super.connectedCallback(); + this._panelAttributeObserver.observe(this, panelObserverConfig); + } + protected override async willUpdate(changedProperties: PropertyValues): Promise { super.willUpdate(changedProperties); if (changedProperties.has('checked')) { this.toggleAttribute('data-checked', this.checked); } + } - if (changedProperties.has('size')) { - if (!this.group) { - this.closest?.('sbb-selection-expansion-panel')?.setAttribute('data-size', this.size); - } - } + public override disconnectedCallback(): void { + super.disconnectedCallback(); + this._panelAttributeObserver.disconnect(); } protected override render(): TemplateResult {