diff --git a/src/elements/checkbox/checkbox-group/checkbox-group.stories.ts b/src/elements/checkbox/checkbox-group/checkbox-group.stories.ts index 0c431500ba..3311446cf2 100644 --- a/src/elements/checkbox/checkbox-group/checkbox-group.stories.ts +++ b/src/elements/checkbox/checkbox-group/checkbox-group.stories.ts @@ -234,7 +234,7 @@ const size: InputType = { control: { type: 'inline-radio', }, - options: ['m', 's'], + options: ['m', 's', 'xs'], table: { category: 'Checkbox group', }, @@ -359,6 +359,12 @@ export const horizontalSizeM: StoryObj = { args: { ...checkboxArgs, size: 'm' }, }; +export const horizontalSizeXS: StoryObj = { + render: DefaultTemplate, + argTypes: checkboxArgTypes, + args: { ...checkboxArgs, size: 'xs' }, +}; + export const horizontalDisabled: StoryObj = { render: DefaultTemplate, argTypes: checkboxArgTypes, diff --git a/src/elements/checkbox/checkbox-group/checkbox-group.visual.spec.ts b/src/elements/checkbox/checkbox-group/checkbox-group.visual.spec.ts index 6174fc6b8b..473bc62b83 100644 --- a/src/elements/checkbox/checkbox-group/checkbox-group.visual.spec.ts +++ b/src/elements/checkbox/checkbox-group/checkbox-group.visual.spec.ts @@ -121,6 +121,13 @@ describe('sbb-checkbox-group', () => { }), ); + it( + `${orientation} size=xs ${visualDiffDefault.name}`, + visualDiffDefault.with(async (setup) => { + await setup.withFixture(checkboxesTemplate({ ...args, size: 'xs' })); + }), + ); + it( `${orientation} disabled ${visualDiffDefault.name}`, visualDiffDefault.with(async (setup) => { diff --git a/src/elements/checkbox/checkbox-panel/__snapshots__/checkbox-panel.snapshot.spec.snap.js b/src/elements/checkbox/checkbox-panel/__snapshots__/checkbox-panel.snapshot.spec.snap.js index c82c86ab1f..9e6bc79e03 100644 --- a/src/elements/checkbox/checkbox-panel/__snapshots__/checkbox-panel.snapshot.spec.snap.js +++ b/src/elements/checkbox/checkbox-panel/__snapshots__/checkbox-panel.snapshot.spec.snap.js @@ -28,7 +28,7 @@ snapshots["sbb-checkbox-panel renders unchecked Shadow DOM"] = - + @@ -75,7 +75,10 @@ snapshots["sbb-checkbox-panel renders checked Shadow DOM"] = - + @@ -121,7 +124,10 @@ snapshots["sbb-checkbox-panel renders indeterminate Shadow DOM"] = - + @@ -167,7 +173,10 @@ snapshots["sbb-checkbox-panel renders unchecked disabled Shadow DOM"] = - + diff --git a/src/elements/checkbox/checkbox-panel/checkbox-panel.ts b/src/elements/checkbox/checkbox-panel/checkbox-panel.ts index b5ed7b8c02..50fd83cb53 100644 --- a/src/elements/checkbox/checkbox-panel/checkbox-panel.ts +++ b/src/elements/checkbox/checkbox-panel/checkbox-panel.ts @@ -6,7 +6,7 @@ import { type PropertyValues, type TemplateResult, } from 'lit'; -import { customElement } from 'lit/decorators.js'; +import { customElement, property } from 'lit/decorators.js'; import { slotState } from '../../core/decorators.js'; import { EventEmitter } from '../../core/eventing.js'; @@ -15,7 +15,12 @@ import type { SbbDisabledStateChange, SbbStateChange, } from '../../core/interfaces/types.js'; -import { panelCommonStyle, SbbPanelMixin, SbbUpdateSchedulerMixin } from '../../core/mixins.js'; +import { + panelCommonStyle, + SbbPanelMixin, + type SbbPanelSize, + SbbUpdateSchedulerMixin, +} from '../../core/mixins.js'; import { checkboxCommonStyle, SbbCheckboxCommonElementMixin } from '../common.js'; import '../../screen-reader-only.js'; @@ -51,6 +56,16 @@ export class SbbCheckboxPanelElement extends SbbPanelMixin( panelConnected: 'panelConnected', } as const; + /** Size variant. */ + @property({ reflect: true }) + public set size(value: SbbPanelSize) { + this._size = value; + } + public get size(): SbbPanelSize { + return this.group?.size ? (this.group.size === 'xs' ? 's' : this.group.size) : this._size; + } + private _size: SbbPanelSize = 'm'; + /** * @internal * Internal event that emits whenever the state of the checkbox diff --git a/src/elements/checkbox/checkbox-panel/readme.md b/src/elements/checkbox/checkbox-panel/readme.md index 80cb20c72a..37d678e681 100644 --- a/src/elements/checkbox/checkbox-panel/readme.md +++ b/src/elements/checkbox/checkbox-panel/readme.md @@ -51,6 +51,14 @@ The component's label can be displayed in bold using the `sbb-text--bold` class ``` +The component has two `size`, named `s` and `m` (default). +If the component is used within a group, the size is inherited from it; +since the `sbb-checkbox-group` has also `xs` size, this case will fall back to `s`. + +```html + Size +``` + ## Events Consumers can listen to the native `change` event on the `sbb-checkbox-panel` component to intercept the input's change; @@ -78,7 +86,7 @@ If you don't want the label to appear next to the checkbox, you can use `aria-la | `indeterminate` | `indeterminate` | public | `boolean` | `false` | Whether the checkbox is indeterminate. | | `name` | `name` | public | `string` | | Name of the form element. Will be read from name attribute. | | `required` | `required` | public | `boolean` | `false` | Whether the component is required. | -| `size` | `size` | public | `SbbCheckboxSize` | `'m'` | Label size variant, either m or s. | +| `size` | `size` | public | `SbbPanelSize` | `'m'` | Size variant. | | `value` | `value` | public | `string \| null` | `null` | Value of the form element. | ## Events diff --git a/src/elements/checkbox/checkbox/__snapshots__/checkbox.snapshot.spec.snap.js b/src/elements/checkbox/checkbox/__snapshots__/checkbox.snapshot.spec.snap.js index 597a94a318..727d86d072 100644 --- a/src/elements/checkbox/checkbox/__snapshots__/checkbox.snapshot.spec.snap.js +++ b/src/elements/checkbox/checkbox/__snapshots__/checkbox.snapshot.spec.snap.js @@ -18,7 +18,7 @@ snapshots["sbb-checkbox should render unchecked Shadow DOM"] = - + @@ -53,7 +53,10 @@ snapshots["sbb-checkbox should render checked Shadow DOM"] = - + @@ -88,7 +91,10 @@ snapshots["sbb-checkbox should render indeterminate Shadow DOM"] = - + @@ -123,7 +129,10 @@ snapshots["sbb-checkbox should render unchecked disabled Shadow DOM"] = - + diff --git a/src/elements/checkbox/checkbox/checkbox.stories.ts b/src/elements/checkbox/checkbox/checkbox.stories.ts index ce201000a3..4a2e57bdd4 100644 --- a/src/elements/checkbox/checkbox/checkbox.stories.ts +++ b/src/elements/checkbox/checkbox/checkbox.stories.ts @@ -23,7 +23,7 @@ const size: InputType = { control: { type: 'inline-radio', }, - options: ['m', 's'], + options: ['m', 's', 'xs'], }; const checked: InputType = { @@ -173,6 +173,11 @@ export const sizeM: StoryObj = { argTypes: defaultArgTypes, args: { ...defaultArgs, size: size.options![0] }, }; +export const sizeXS: StoryObj = { + render: Template, + argTypes: defaultArgTypes, + args: { ...defaultArgs, size: size.options![2] }, +}; export const longLabel: StoryObj = { render: Template, argTypes: defaultArgTypes, diff --git a/src/elements/checkbox/checkbox/checkbox.ts b/src/elements/checkbox/checkbox/checkbox.ts index 890c24b3d0..fff6a5cbc1 100644 --- a/src/elements/checkbox/checkbox/checkbox.ts +++ b/src/elements/checkbox/checkbox/checkbox.ts @@ -4,7 +4,11 @@ import { customElement, property } from 'lit/decorators.js'; import { slotState } from '../../core/decorators.js'; import type { SbbIconPlacement } from '../../core/interfaces.js'; import { SbbIconNameMixin } from '../../icon.js'; -import { SbbCheckboxCommonElementMixin, checkboxCommonStyle } from '../common.js'; +import { + SbbCheckboxCommonElementMixin, + checkboxCommonStyle, + type SbbCheckboxSize, +} from '../common.js'; import checkboxStyle from './checkbox.scss?lit&inline'; @@ -30,6 +34,16 @@ export class SbbCheckboxElement extends SbbCheckboxCommonElementMixin( didChange: 'didChange', } as const; + /** Size variant. */ + @property({ reflect: true }) + public set size(value: SbbCheckboxSize) { + this._size = value; + } + public get size(): SbbCheckboxSize { + return this.group?.size ?? this._size; + } + private _size: SbbCheckboxSize = 'm'; + /** The label position relative to the labelIcon. Defaults to end */ @property({ attribute: 'icon-placement', reflect: true }) public iconPlacement: SbbIconPlacement = 'end'; @@ -44,6 +58,7 @@ export class SbbCheckboxElement extends SbbCheckboxCommonElementMixin( ?checked=${this.checked} ?indeterminate=${this.indeterminate} ?disabled=${this.disabled || this.formDisabled} + size=${this.size} > diff --git a/src/elements/checkbox/checkbox/checkbox.visual.spec.ts b/src/elements/checkbox/checkbox/checkbox.visual.spec.ts index d9cecff44f..a957e81558 100644 --- a/src/elements/checkbox/checkbox/checkbox.visual.spec.ts +++ b/src/elements/checkbox/checkbox/checkbox.visual.spec.ts @@ -62,6 +62,13 @@ describe('sbb-checkbox', () => { }), ); + it( + `${state} size=xs`, + visualDiffDefault.with(async (setup) => { + await setup.withFixture(template({ ...defaultArgs, size: 'xs' })); + }), + ); + for (const iconPlacement of ['start', 'end']) { it( `${state} iconPlacement=${iconPlacement}`, diff --git a/src/elements/checkbox/checkbox/readme.md b/src/elements/checkbox/checkbox/readme.md index a47cae7b99..389f60190c 100644 --- a/src/elements/checkbox/checkbox/readme.md +++ b/src/elements/checkbox/checkbox/readme.md @@ -43,10 +43,12 @@ The component can be displayed in `disabled` or `required` state by using the se ## Style -The component has two `size`, named `s` and `m` (default). +The component has three `size`, named `xs`, `s` and `m` (default). ```html -Size +Size + +Size ``` The component's label can be displayed in bold using the `sbb-text--bold` class on a wrapper tag: @@ -90,7 +92,7 @@ If you don't want the label to appear next to the checkbox, you can use `aria-la | `indeterminate` | `indeterminate` | public | `boolean` | `false` | Whether the checkbox is indeterminate. | | `name` | `name` | public | `string` | | Name of the form element. Will be read from name attribute. | | `required` | `required` | public | `boolean` | `false` | Whether the component is required. | -| `size` | `size` | public | `SbbCheckboxSize` | `'m'` | Label size variant, either m or s. | +| `size` | `size` | public | `SbbCheckboxSize` | `'m'` | Size variant. | | `value` | `value` | public | `string \| null` | `null` | Value of the form element. | ## Events diff --git a/src/elements/checkbox/common/checkbox-common.scss b/src/elements/checkbox/common/checkbox-common.scss index 269d752e6a..85ddeed432 100644 --- a/src/elements/checkbox/common/checkbox-common.scss +++ b/src/elements/checkbox/common/checkbox-common.scss @@ -34,6 +34,10 @@ :host([size='s']) & { @include sbb.text-s--regular; } + + :host([size='xs']) & { + @include sbb.text-xs--regular; + } } .sbb-checkbox__inner { diff --git a/src/elements/checkbox/common/checkbox-common.ts b/src/elements/checkbox/common/checkbox-common.ts index 36cd4eea30..09f0f6cc2c 100644 --- a/src/elements/checkbox/common/checkbox-common.ts +++ b/src/elements/checkbox/common/checkbox-common.ts @@ -10,7 +10,7 @@ import { } from '../../core/mixins.js'; import type { SbbCheckboxGroupElement } from '../checkbox-group.js'; -export type SbbCheckboxSize = 's' | 'm'; +export type SbbCheckboxSize = 'xs' | 's' | 'm'; export declare class SbbCheckboxCommonElementMixinType extends SbbFormAssociatedCheckboxMixinType @@ -18,9 +18,6 @@ export declare class SbbCheckboxCommonElementMixinType { public indeterminate: boolean; - public set size(value: SbbCheckboxSize); - public get size(): SbbCheckboxSize; - public get group(): SbbCheckboxGroupElement | null; } @@ -35,16 +32,6 @@ export const SbbCheckboxCommonElementMixin = > /** Whether the checkbox is indeterminate. */ @property({ type: Boolean }) public indeterminate = false; - /** Label size variant, either m or s. */ - @property({ reflect: true }) - public set size(value: SbbCheckboxSize) { - this._size = value; - } - public get size(): SbbCheckboxSize { - return this.group?.size ?? this._size; - } - private _size: SbbCheckboxSize = 'm'; - /** Reference to the connected checkbox group. */ public get group(): SbbCheckboxGroupElement | null { return this._group; diff --git a/src/elements/core/mixins/panel-mixin.ts b/src/elements/core/mixins/panel-mixin.ts index 688a5ad848..447fc9bb96 100644 --- a/src/elements/core/mixins/panel-mixin.ts +++ b/src/elements/core/mixins/panel-mixin.ts @@ -11,6 +11,8 @@ export declare class SbbPanelMixinType { public expansionState?: string; } +export type SbbPanelSize = 's' | 'm'; + /** * Mixin for common panel behaviors */ 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 4aa4f7d31b..e5cf286c57 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 @@ -9,13 +9,16 @@ import { import { customElement, property } from 'lit/decorators.js'; import { slotState } from '../../core/decorators.js'; -import { panelCommonStyle, SbbPanelMixin, SbbUpdateSchedulerMixin } from '../../core/mixins.js'; +import { + panelCommonStyle, + SbbPanelMixin, + type SbbPanelSize, + SbbUpdateSchedulerMixin, +} from '../../core/mixins.js'; import { radioButtonCommonStyle, SbbRadioButtonCommonElementMixin } from '../common.js'; import '../../screen-reader-only.js'; -export type SbbRadioButtonPanelSize = 's' | 'm'; - /** /** * It displays a radio button enhanced with the panel design. @@ -42,13 +45,13 @@ export class SbbRadioButtonPanelElement extends SbbPanelMixin( * Size variant. */ @property({ reflect: true }) - public set size(value: SbbRadioButtonPanelSize) { + public set size(value: SbbPanelSize) { this._size = value; } - public get size(): SbbRadioButtonPanelSize { + public get size(): SbbPanelSize { return this.group?.size ? (this.group.size === 'xs' ? 's' : this.group.size) : this._size; } - private _size: SbbRadioButtonPanelSize = 'm'; + private _size: SbbPanelSize = 'm'; protected override async willUpdate(changedProperties: PropertyValues): Promise { super.willUpdate(changedProperties); diff --git a/src/elements/radio-button/radio-button-panel/readme.md b/src/elements/radio-button/radio-button-panel/readme.md index b40199053e..f6adba7bd3 100644 --- a/src/elements/radio-button/radio-button-panel/readme.md +++ b/src/elements/radio-button/radio-button-panel/readme.md @@ -64,7 +64,7 @@ The component's label can be displayed in bold using the `sbb-text--bold` class | `disabled` | `disabled` | public | `boolean` | `false` | Whether the radio button is disabled. | | `group` | - | public | `SbbRadioButtonGroupElement \| null` | `null` | Reference to the connected radio button group. | | `required` | `required` | public | `boolean` | `false` | Whether the radio button is required. | -| `size` | `size` | public | `SbbRadioButtonPanelSize` | `'m'` | Size variant. | +| `size` | `size` | public | `SbbPanelSize` | `'m'` | Size variant. | | `value` | `value` | public | `string \| undefined` | | Value of radio button. | ## Methods diff --git a/src/elements/visual-checkbox/readme.md b/src/elements/visual-checkbox/readme.md index 155236f8fe..03544c8ac1 100644 --- a/src/elements/visual-checkbox/readme.md +++ b/src/elements/visual-checkbox/readme.md @@ -12,13 +12,24 @@ It has four different states related to the properties `checked`, `indeterminate - an indeterminate state (`checked` unset and `indeterminate` set to `true`): a horizontal line is displayed in the square; - a disabled state (`disabled` set to `true`): a grayed out empty square is shown. +## Style + +The component has three `size`, named `xs`, `s` and `m` (default). + +```html + + + +``` + ## Properties -| Name | Attribute | Privacy | Type | Default | Description | -| --------------- | --------------- | ------- | --------- | ------- | ---------------------------------- | -| `checked` | `checked` | public | `boolean` | `false` | Checked state. | -| `disabled` | `disabled` | public | `boolean` | `false` | Whether the component is disabled. | -| `indeterminate` | `indeterminate` | public | `boolean` | `false` | Indeterminate state. | -| `negative` | `negative` | public | `boolean` | `false` | Negative coloring variant flag. | +| Name | Attribute | Privacy | Type | Default | Description | +| --------------- | --------------- | ------- | ----------------- | ------- | ---------------------------------- | +| `checked` | `checked` | public | `boolean` | `false` | Checked state. | +| `disabled` | `disabled` | public | `boolean` | `false` | Whether the component is disabled. | +| `indeterminate` | `indeterminate` | public | `boolean` | `false` | Indeterminate state. | +| `negative` | `negative` | public | `boolean` | `false` | Negative coloring variant flag. | +| `size` | `size` | public | `SbbCheckboxSize` | `'m'` | Size of the checkbox. | diff --git a/src/elements/visual-checkbox/visual-checkbox.scss b/src/elements/visual-checkbox/visual-checkbox.scss index 2bba13c1ef..d09e9735b6 100644 --- a/src/elements/visual-checkbox/visual-checkbox.scss +++ b/src/elements/visual-checkbox/visual-checkbox.scss @@ -20,6 +20,10 @@ display: block; } +:host([size='xs']) { + --sbb-visual-checkbox-dimension: #{sbb.px-to-rem-build(20)}; +} + :host([negative]) { --sbb-visual-checkbox-background-color: var(--sbb-color-midnight); --sbb-visual-checkbox-border-color: var(--sbb-color-smoke); diff --git a/src/elements/visual-checkbox/visual-checkbox.stories.ts b/src/elements/visual-checkbox/visual-checkbox.stories.ts index 35a855f64b..789518b792 100644 --- a/src/elements/visual-checkbox/visual-checkbox.stories.ts +++ b/src/elements/visual-checkbox/visual-checkbox.stories.ts @@ -32,11 +32,19 @@ const negative: InputType = { }, }; +const size: InputType = { + control: { + type: 'inline-radio', + }, + options: ['m', 's', 'xs'], +}; + const defaultArgTypes: ArgTypes = { checked, indeterminate, disabled, negative, + size, }; const defaultArgs: Args = { @@ -44,6 +52,7 @@ const defaultArgs: Args = { indeterminate: false, disabled: false, negative: false, + size: size.options![0], }; const Template = (args: Args): TemplateResult => @@ -121,6 +130,30 @@ export const DisabledIndeterminateNegative: StoryObj = { args: { ...defaultArgs, indeterminate: true, disabled: true, negative: true }, }; +export const SizeXS: StoryObj = { + render: Template, + argTypes: defaultArgTypes, + args: { ...defaultArgs, size: size.options![2] }, +}; + +export const SizeXSChecked: StoryObj = { + render: Template, + argTypes: defaultArgTypes, + args: { ...defaultArgs, size: size.options![2], checked: true }, +}; + +export const SizeXSIndeterminate: StoryObj = { + render: Template, + argTypes: defaultArgTypes, + args: { ...defaultArgs, size: size.options![2], indeterminate: true }, +}; + +export const SizeXSNegative: StoryObj = { + render: Template, + argTypes: defaultArgTypes, + args: { ...defaultArgs, size: size.options![2], negative: true }, +}; + const meta: Meta = { parameters: { backgroundColor: (context: StoryContext) => diff --git a/src/elements/visual-checkbox/visual-checkbox.ts b/src/elements/visual-checkbox/visual-checkbox.ts index 0ea6ee2ca3..8234a4c820 100644 --- a/src/elements/visual-checkbox/visual-checkbox.ts +++ b/src/elements/visual-checkbox/visual-checkbox.ts @@ -2,6 +2,7 @@ import type { CSSResultGroup, TemplateResult } from 'lit'; import { html, LitElement, nothing } from 'lit'; import { customElement, property } from 'lit/decorators.js'; +import type { SbbCheckboxSize } from '../checkbox/common.js'; import { SbbDisabledMixin, SbbNegativeMixin } from '../core/mixins.js'; import style from './visual-checkbox.scss?lit&inline'; @@ -19,14 +20,17 @@ export class SbbVisualCheckboxElement extends SbbDisabledMixin(SbbNegativeMixin( /** Indeterminate state. */ @property({ reflect: true, type: Boolean }) public indeterminate = false; + /** Size of the checkbox. */ + @property({ reflect: true }) public size: SbbCheckboxSize = 'm'; + protected override render(): TemplateResult { return html` ${this.checked || this.indeterminate ? html` { - const cases = { - state: [ - { indeterminate: undefined, checked: true }, - { indeterminate: undefined, checked: false }, - { indeterminate: true, checked: true }, - ], + const states = [ + { indeterminate: undefined, checked: true }, + { indeterminate: undefined, checked: false }, + { indeterminate: true, checked: true }, + ]; + + const visualStates = { disabled: [false, true], negative: [false, true], forcedColors: [false, true], }; + const size = ['xs', 's', 'm']; + describeViewports({ viewports: ['zero'] }, () => { let root: HTMLElement; - describeEach(cases, ({ state, disabled, negative, forcedColors }) => { + describeEach({ states, ...visualStates }, ({ states, disabled, negative, forcedColors }) => { beforeEach(async function () { root = await visualRegressionFixture( html``, @@ -47,5 +50,24 @@ describe(`sbb-visual-checkbox`, () => { }), ); }); + + describeEach({ states, size }, ({ states, size }) => { + beforeEach(async function () { + root = await visualRegressionFixture( + html``, + ); + }); + + it( + visualDiffDefault.name, + visualDiffDefault.with((setup) => { + setup.withSnapshotElement(root); + }), + ); + }); }); });