diff --git a/.changeset/wild-bees-laugh.md b/.changeset/wild-bees-laugh.md
new file mode 100644
index 0000000000..25c1d126a9
--- /dev/null
+++ b/.changeset/wild-bees-laugh.md
@@ -0,0 +1,8 @@
+---
+'@swisspost/design-system-documentation': minor
+'@swisspost/design-system-components': minor
+'@swisspost/design-system-components-angular': minor
+'@swisspost/design-system-components-react': minor
+---
+
+Added a `post-collapsible-trigger` component to properly handle the role, ARIA attributes, and event listeners for elements that toggle a `post-collapsible`.
diff --git a/packages/components-angular/projects/consumer-app/src/app/routes/home/home.component.html b/packages/components-angular/projects/consumer-app/src/app/routes/home/home.component.html
index 58327c6fe3..57d7de325f 100644
--- a/packages/components-angular/projects/consumer-app/src/app/routes/home/home.component.html
+++ b/packages/components-angular/projects/consumer-app/src/app/routes/home/home.component.html
@@ -30,7 +30,10 @@
Post Card-Control
Post Collapsible
-
+
+
+
+
Contentus momentus vero siteos et accusam iretea et justo.
diff --git a/packages/components/cypress/e2e/accordion.cy.ts b/packages/components/cypress/e2e/accordion.cy.ts
index 9d8bdd7cc7..372947bb72 100644
--- a/packages/components/cypress/e2e/accordion.cy.ts
+++ b/packages/components/cypress/e2e/accordion.cy.ts
@@ -16,17 +16,17 @@ describe('accordion', () => {
});
it('should only show the first element as expanded', () => {
- cy.get('@collapsibles').first().find('.collapse').should('be.visible');
+ cy.get('@collapsibles').first().shadow().find('post-collapsible').should('be.visible');
});
it('should show the last element as expanded after clicking it', () => {
cy.get('@collapsibles').last().click();
- cy.get('@collapsibles').last().find('.collapse').should('be.visible');
+ cy.get('@collapsibles').last().shadow().find('post-collapsible').should('be.visible');
});
it('should not show the first element as expanded after clicking the last element', () => {
cy.get('@collapsibles').last().click();
- cy.get('@collapsibles').first().find('.collapse').should('be.hidden');
+ cy.get('@collapsibles').first().shadow().find('post-collapsible').should('be.hidden');
});
it('should propagate "postToggle" event from post-accordion-item on post-accordion', () => {
@@ -73,12 +73,12 @@ describe('accordion', () => {
it('should show the last element as expanded after clicking it', () => {
cy.get('@collapsibles').last().click();
- cy.get('@collapsibles').last().find('.collapse').should('be.visible');
+ cy.get('@collapsibles').last().shadow().find('post-collapsible').should('be.visible');
});
it('should still show the first element as expanded after clicking the last element', () => {
cy.get('@collapsibles').last().click();
- cy.get('@collapsibles').first().find('.collapse').should('be.visible');
+ cy.get('@collapsibles').first().shadow().find('post-collapsible').should('be.visible');
});
});
});
diff --git a/packages/components/cypress/e2e/collapsible.cy.ts b/packages/components/cypress/e2e/collapsible.cy.ts
index f7d2d8a5b7..5ae83f7e9a 100644
--- a/packages/components/cypress/e2e/collapsible.cy.ts
+++ b/packages/components/cypress/e2e/collapsible.cy.ts
@@ -3,57 +3,75 @@ const COLLAPSIBLE_ID = '6a91848c-16ec-4a23-bc45-51c797b5b2c3';
describe('collapsible', () => {
describe('default', () => {
beforeEach(() => {
- cy.getComponent('collapsible', COLLAPSIBLE_ID);
- cy.get('@collapsible').find('.collapse').as('collapse');
- cy.get(`#button--${COLLAPSIBLE_ID}--default`).as('toggler');
+ cy.getComponents(COLLAPSIBLE_ID, 'default', 'post-collapsible', 'post-collapsible-trigger');
+ cy.get('@collapsible-trigger').find('.btn').as('trigger');
});
- it('should render', () => {
+ it('should have a collapsible', () => {
cy.get('@collapsible').should('exist');
});
- it('should have a collapse', () => {
- cy.get('@collapse').should('exist');
+ it('should have a trigger', () => {
+ cy.get('@trigger').should('exist');
});
- it('should have a toggle button', () => {
- cy.get('@toggler').should('exist');
+ it('should show the collapsible', () => {
+ cy.get('@collapsible').should(`be.visible`);
});
- it('should be expanded', () => {
- cy.get('@collapse').should(`be.visible`);
+ it('should set the correct ARIA attribute on the trigger', () => {
+ cy.get('@collapsible')
+ .invoke('attr', 'id')
+ .then(collapsibleId => {
+ cy.get('@trigger').should('have.attr', 'aria-controls', collapsibleId);
+ });
+ cy.get('@trigger').should('have.attr', 'aria-expanded', 'true');
});
- it('should be collapsed after clicking on the toggle button once', () => {
- cy.get('@toggler').click();
- cy.get('@collapse').should(`be.hidden`);
+ it('should hide the collapsible after clicking on the trigger once', () => {
+ cy.get('@trigger').click();
+ cy.get('@collapsible').should(`be.hidden`);
});
- it('should be expanded after clicking on the toggle button twice', () => {
- cy.get('@toggler').dblclick();
- cy.get('@collapse').should(`be.visible`);
+ it('should update the "aria-expanded" attribute after hiding the collapsible', () => {
+ cy.get('@trigger').click();
+ cy.get('@trigger').should('have.attr', 'aria-expanded', 'false');
+ });
+
+ it('should show the collapsible after clicking on the trigger twice', () => {
+ cy.get('@trigger').dblclick();
+ cy.get('@collapsible').should(`be.visible`);
+ });
+
+ it('should update the "aria-expanded" attribute after showing the collapsible', () => {
+ cy.get('@trigger').dblclick();
+ cy.get('@trigger').should('have.attr', 'aria-expanded', 'true');
});
});
describe('initially collapsed', () => {
beforeEach(() => {
- cy.getComponent('collapsible', COLLAPSIBLE_ID, 'initially-collapsed');
- cy.get('@collapsible').find('.collapse').as('collapse');
- cy.get(`#button--${COLLAPSIBLE_ID}--initially-collapsed`).as('toggler');
+ cy.getComponents(
+ COLLAPSIBLE_ID,
+ 'initially-collapsed',
+ 'post-collapsible',
+ 'post-collapsible-trigger',
+ );
+ cy.get('@collapsible-trigger').find('.btn').as('trigger');
});
- it('should be collapsed', () => {
- cy.get('@collapse').should(`be.hidden`);
+ it('should hide the collapsible', () => {
+ cy.get('@collapsible').should(`be.hidden`);
});
- it('should be expanded after clicking on the toggle button once', () => {
- cy.get('@toggler').click();
- cy.get('@collapse').should(`be.visible`);
+ it('should show the collapsible after clicking on the trigger once', () => {
+ cy.get('@trigger').click();
+ cy.get('@collapsible').should(`be.visible`);
});
- it('should be collapsed after clicking on the toggle button twice', () => {
- cy.get('@toggler').dblclick();
- cy.get('@collapse').should(`be.hidden`);
+ it('should hide the collapsible after clicking on the trigger twice', () => {
+ cy.get('@trigger').dblclick();
+ cy.get('@collapsible').should(`be.hidden`);
});
});
});
diff --git a/packages/components/cypress/support/commands.ts b/packages/components/cypress/support/commands.ts
index 29e8f58b8c..20f89a741e 100644
--- a/packages/components/cypress/support/commands.ts
+++ b/packages/components/cypress/support/commands.ts
@@ -49,10 +49,16 @@ export const isInViewport = function (_chai: Chai.ChaiStatic) {
chai.use(isInViewport);
Cypress.Commands.add('getComponent', (component: string, id: string, story = 'default') => {
+ cy.getComponents(id, story, component);
+});
+
+Cypress.Commands.add('getComponents', (id: string, story: string, ...components: string[]) => {
cy.visit(`/iframe.html?id=${id}--${story}`);
- const alias = component.replace(/^post-/, '');
- cy.get(`post-${alias}`, { timeout: 30000 }).as(alias);
+ components.forEach(component => {
+ const alias = component.replace(/^post-/, '');
+ cy.get(`post-${alias}.hydrated`, { timeout: 30000 }).as(alias);
+ });
cy.injectAxe();
});
diff --git a/packages/components/cypress/support/index.d.ts b/packages/components/cypress/support/index.d.ts
index d7b6a2cd32..96fbc79c05 100644
--- a/packages/components/cypress/support/index.d.ts
+++ b/packages/components/cypress/support/index.d.ts
@@ -2,6 +2,7 @@ declare global {
namespace Cypress {
interface Chainable {
getComponent(component: string, id: string, story?: string): Chainable;
+ getComponents(id: string, story: string, ...component: string[]): Chainable;
getSnapshots(component: string): Chainable;
checkAriaExpanded(
controlledElementSelector: string,
diff --git a/packages/components/src/components.d.ts b/packages/components/src/components.d.ts
index c4a14afe4f..afd3aef23b 100644
--- a/packages/components/src/components.d.ts
+++ b/packages/components/src/components.d.ts
@@ -134,6 +134,16 @@ export namespace Components {
*/
"toggle": (open?: boolean) => Promise;
}
+ interface PostCollapsibleTrigger {
+ /**
+ * Link the trigger to a post-collapsible with this id
+ */
+ "for": string;
+ /**
+ * Update the "aria-controls" and "aria-expanded" attributes on the trigger button
+ */
+ "update": () => Promise;
+ }
/**
* @class PostIcon - representing a stencil component
*/
@@ -393,6 +403,12 @@ declare global {
prototype: HTMLPostCollapsibleElement;
new (): HTMLPostCollapsibleElement;
};
+ interface HTMLPostCollapsibleTriggerElement extends Components.PostCollapsibleTrigger, HTMLStencilElement {
+ }
+ var HTMLPostCollapsibleTriggerElement: {
+ prototype: HTMLPostCollapsibleTriggerElement;
+ new (): HTMLPostCollapsibleTriggerElement;
+ };
/**
* @class PostIcon - representing a stencil component
*/
@@ -490,6 +506,7 @@ declare global {
"post-alert": HTMLPostAlertElement;
"post-card-control": HTMLPostCardControlElement;
"post-collapsible": HTMLPostCollapsibleElement;
+ "post-collapsible-trigger": HTMLPostCollapsibleTriggerElement;
"post-icon": HTMLPostIconElement;
"post-popover": HTMLPostPopoverElement;
"post-popovercontainer": HTMLPostPopovercontainerElement;
@@ -608,6 +625,12 @@ declare namespace LocalJSX {
*/
"onPostToggle"?: (event: PostCollapsibleCustomEvent) => void;
}
+ interface PostCollapsibleTrigger {
+ /**
+ * Link the trigger to a post-collapsible with this id
+ */
+ "for"?: string;
+ }
/**
* @class PostIcon - representing a stencil component
*/
@@ -747,6 +770,7 @@ declare namespace LocalJSX {
"post-alert": PostAlert;
"post-card-control": PostCardControl;
"post-collapsible": PostCollapsible;
+ "post-collapsible-trigger": PostCollapsibleTrigger;
"post-icon": PostIcon;
"post-popover": PostPopover;
"post-popovercontainer": PostPopovercontainer;
@@ -770,6 +794,7 @@ declare module "@stencil/core" {
*/
"post-card-control": LocalJSX.PostCardControl & JSXBase.HTMLAttributes;
"post-collapsible": LocalJSX.PostCollapsible & JSXBase.HTMLAttributes;
+ "post-collapsible-trigger": LocalJSX.PostCollapsibleTrigger & JSXBase.HTMLAttributes;
/**
* @class PostIcon - representing a stencil component
*/
diff --git a/packages/components/src/components/post-collapsible-trigger/post-collapsible-trigger.tsx b/packages/components/src/components/post-collapsible-trigger/post-collapsible-trigger.tsx
new file mode 100644
index 0000000000..9c049ae06d
--- /dev/null
+++ b/packages/components/src/components/post-collapsible-trigger/post-collapsible-trigger.tsx
@@ -0,0 +1,119 @@
+import { Component, Element, Listen, Method, Prop, Watch } from '@stencil/core';
+import { version } from 'typescript';
+import { checkNonEmpty, checkType, debounce } from '@/utils';
+import { PostCollapsibleCustomEvent } from '@/components';
+
+@Component({
+ tag: 'post-collapsible-trigger',
+})
+export class PostCollapsibleTrigger {
+ private trigger?: HTMLButtonElement;
+ private observer = new MutationObserver(() => this.setTrigger());
+
+ @Element() host: HTMLPostCollapsibleTriggerElement;
+
+ /**
+ * Link the trigger to a post-collapsible with this id
+ */
+ @Prop() for: string;
+
+ /**
+ * Set the "aria-controls" and "aria-expanded" attributes on the trigger to match the state of the controlled post-collapsible
+ */
+ @Watch('for')
+ setAriaAttributes() {
+ checkNonEmpty(this.for, 'The post-collapsible-trigger "for" prop is required.');
+ checkType(this.for, 'string', 'The post-collapsible-trigger "for" prop should be a id.');
+
+ void this.update();
+ }
+
+ /**
+ * Initiate a mutation observer that updates the trigger whenever necessary
+ */
+ connectedCallback() {
+ this.observer.observe(this.host, { childList: true, subtree: true });
+ }
+
+ /**
+ * Add the "data-version" to the host element and set the trigger
+ */
+ componentDidLoad() {
+ this.host.setAttribute('data-version', version);
+ this.setTrigger();
+
+ if (!this.trigger) console.warn('The post-collapsible-trigger must contain a button.');
+ }
+
+ /**
+ * Disconnect the mutation observer
+ */
+ disconnectedCallback() {
+ this.observer.disconnect();
+ }
+
+ /**
+ * Update the "aria-expanded" attribute on the trigger anytime the controlled post-collapsible is toggled
+ */
+ @Listen('postToggle', { target: 'document' })
+ setAriaExpanded(e: PostCollapsibleCustomEvent) {
+ if (!this.trigger || !e.target.isEqualNode(this.collapsible)) return;
+ this.trigger.setAttribute('aria-expanded', `${e.detail}`);
+ }
+
+ /**
+ * Update the "aria-controls" and "aria-expanded" attributes on the trigger button
+ */
+ @Method()
+ async update() {
+ this.debouncedUpdate();
+ }
+
+ private debouncedUpdate = debounce(() => {
+ if (!this.trigger) return;
+
+ // add the provided id to the aria-controls list
+ const ariaControls = this.trigger.getAttribute('aria-controls');
+ if (!ariaControls?.includes(this.for)) {
+ const newAriaControls = ariaControls ? `${ariaControls} ${this.for}` : this.for;
+ this.trigger.setAttribute('aria-controls', newAriaControls);
+ }
+
+ // set the aria-expanded to `false` if the controlled collapsible is collapsed or undefined, set it to `true` otherwise
+ const isCollapsed = this.collapsible?.collapsed;
+ const newAriaExpanded = isCollapsed !== undefined ? !isCollapsed : undefined;
+ this.trigger.setAttribute('aria-expanded', `${newAriaExpanded}`);
+ });
+
+ /**
+ * Toggle the post-collapsible controlled by the trigger
+ */
+ private async toggleCollapsible() {
+ await this.collapsible?.toggle();
+ }
+
+ /**
+ * Retrieve the post-collapsible controlled by the trigger
+ */
+ private get collapsible(): HTMLPostCollapsibleElement | null {
+ const ref = document.getElementById(this.for);
+ if (ref && ref.localName === 'post-collapsible') {
+ return ref as HTMLPostCollapsibleElement;
+ }
+
+ return null;
+ }
+
+ /**
+ * Find the button and add the proper event listener and ARIA attributes to it
+ */
+ private setTrigger() {
+ const trigger = this.host.querySelector('button');
+ if (!trigger || (this.trigger && trigger.isEqualNode(this.trigger))) return;
+
+ this.trigger = trigger;
+
+ this.trigger.addEventListener('click', () => this.toggleCollapsible());
+ this.setAriaAttributes();
+ }
+}
diff --git a/packages/components/src/components/post-collapsible-trigger/readme.md b/packages/components/src/components/post-collapsible-trigger/readme.md
new file mode 100644
index 0000000000..3c5f16db95
--- /dev/null
+++ b/packages/components/src/components/post-collapsible-trigger/readme.md
@@ -0,0 +1,30 @@
+# post-collapsible-trigger
+
+
+
+
+
+
+## Properties
+
+| Property | Attribute | Description | Type | Default |
+| -------- | --------- | --------------------------------------------------- | -------- | ----------- |
+| `for` | `for` | Link the trigger to a post-collapsible with this id | `string` | `undefined` |
+
+
+## Methods
+
+### `update() => Promise`
+
+Update the "aria-controls" and "aria-expanded" attributes on the trigger button
+
+#### Returns
+
+Type: `Promise`
+
+
+
+
+----------------------------------------------
+
+*Built with [StencilJS](https://stenciljs.com/)*
diff --git a/packages/components/src/components/post-collapsible/post-collapsible.scss b/packages/components/src/components/post-collapsible/post-collapsible.scss
index 0aaf688255..20947d5cd1 100644
--- a/packages/components/src/components/post-collapsible/post-collapsible.scss
+++ b/packages/components/src/components/post-collapsible/post-collapsible.scss
@@ -1,7 +1,4 @@
:host {
display: block;
-}
-
-.collapse {
overflow: hidden;
}
diff --git a/packages/components/src/components/post-collapsible/post-collapsible.tsx b/packages/components/src/components/post-collapsible/post-collapsible.tsx
index 41a29b4323..7473f56975 100644
--- a/packages/components/src/components/post-collapsible/post-collapsible.tsx
+++ b/packages/components/src/components/post-collapsible/post-collapsible.tsx
@@ -7,7 +7,6 @@ import {
Host,
Method,
Prop,
- State,
Watch,
} from '@stencil/core';
import { version } from '@root/package.json';
@@ -26,12 +25,9 @@ import { checkEmptyOrType, isMotionReduced } from '@/utils';
export class PostCollapsible {
private isLoaded = false;
private isOpen = true;
- private collapsible: HTMLElement;
@Element() host: HTMLPostCollapsibleElement;
- @State() id: string;
-
/**
* If `true`, the element is initially collapsed otherwise it is displayed.
*/
@@ -57,13 +53,11 @@ export class PostCollapsible {
this.validateCollapsed();
}
- componentWillRender() {
- this.id = this.host.id || `c${crypto.randomUUID()}`;
- }
-
componentDidLoad() {
if (this.collapsed) void this.toggle(false);
this.isLoaded = true;
+
+ this.updateTriggers();
}
/**
@@ -78,7 +72,7 @@ export class PostCollapsible {
this.isOpen = !this.isOpen;
if (this.isLoaded) this.postToggle.emit(this.isOpen);
- const animation = open ? expand(this.collapsible) : collapse(this.collapsible);
+ const animation = open ? expand(this.host) : collapse(this.host);
if (!this.isLoaded || isMotionReduced()) animation.finish();
@@ -89,12 +83,21 @@ export class PostCollapsible {
return this.isOpen;
}
+ /**
+ * Update all post-collapsible-trigger elements referring to the collapsible
+ */
+ private updateTriggers() {
+ const triggers: NodeListOf = document.querySelectorAll(
+ `post-collapsible-trigger[for=${this.host.id}]`,
+ );
+
+ triggers.forEach(trigger => trigger.update());
+ }
+
render() {
return (
-
-
(this.collapsible = el)}>
-
-
+
+
);
}
diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts
index 6ad5b611b6..0130213e14 100644
--- a/packages/components/src/index.ts
+++ b/packages/components/src/index.ts
@@ -6,6 +6,7 @@ export { PostAccordionItem } from './components/post-accordion-item/post-accordi
export { PostAlert } from './components/post-alert/post-alert';
export { PostCardControl } from './components/post-card-control/post-card-control';
export { PostCollapsible } from './components/post-collapsible/post-collapsible';
+export { PostCollapsibleTrigger } from './components/post-collapsible-trigger/post-collapsible-trigger';
export { PostIcon } from './components/post-icon/post-icon';
export { PostPopover } from './components/post-popover/post-popover';
export { PostPopovercontainer } from './components/post-popovercontainer/post-popovercontainer';
diff --git a/packages/components/src/utils/debounce.ts b/packages/components/src/utils/debounce.ts
new file mode 100644
index 0000000000..fe68e14988
--- /dev/null
+++ b/packages/components/src/utils/debounce.ts
@@ -0,0 +1,7 @@
+export function debounce(callback: (...args: T) => void, timeout = 200) {
+ let id: ReturnType;
+ return (...args: T) => {
+ if (id) clearTimeout(id);
+ id = setTimeout(callback, timeout, ...args);
+ };
+}
diff --git a/packages/components/src/utils/index.ts b/packages/components/src/utils/index.ts
index 6756aaf369..b9ed27b33f 100644
--- a/packages/components/src/utils/index.ts
+++ b/packages/components/src/utils/index.ts
@@ -1,3 +1,4 @@
export * from './property-checkers';
+export * from './debounce';
export * from './is-motion-reduced';
export * from './sass-export';
diff --git a/packages/components/src/utils/tests/debounce.spec.ts b/packages/components/src/utils/tests/debounce.spec.ts
new file mode 100644
index 0000000000..d48eb5b757
--- /dev/null
+++ b/packages/components/src/utils/tests/debounce.spec.ts
@@ -0,0 +1,48 @@
+import { debounce } from '../debounce';
+
+const timeout = 50;
+
+describe('debounce', () => {
+ let callback: jest.MockedFn<(...args: unknown[]) => void>;
+ let debouncedCallback: (...args: unknown[]) => void;
+
+ beforeEach(() => {
+ callback = jest.fn();
+ debouncedCallback = debounce(callback, timeout);
+ });
+
+ it('should wait until the provided timeout elapses before executing the callback function', done => {
+ debouncedCallback();
+
+ setTimeout(() => {
+ expect(callback).not.toHaveBeenCalled();
+ }, timeout / 2);
+
+ setTimeout(() => {
+ expect(callback).toHaveBeenCalled();
+ done();
+ }, timeout * 2);
+ });
+
+ it('should only execute the callback function once when the timeout elapses', done => {
+ debouncedCallback();
+ debouncedCallback();
+ debouncedCallback();
+
+ setTimeout(() => {
+ expect(callback).toHaveBeenCalledTimes(1);
+ done();
+ }, timeout * 2);
+ });
+
+ it('should pass all provided arguments to the callback function', done => {
+ const args = [25, 'myArg', false];
+
+ debouncedCallback(...args);
+
+ setTimeout(() => {
+ expect(callback).toHaveBeenCalledWith(...args);
+ done();
+ }, timeout * 2);
+ });
+});
diff --git a/packages/documentation/src/stories/components/collapsible/collapsible.docs.mdx b/packages/documentation/src/stories/components/collapsible/collapsible.docs.mdx
index ab60064f56..60f4145bda 100644
--- a/packages/documentation/src/stories/components/collapsible/collapsible.docs.mdx
+++ b/packages/documentation/src/stories/components/collapsible/collapsible.docs.mdx
@@ -24,19 +24,13 @@ To make the collapsible content hidden by default, just use the `collapsible="tr
-### Custom Trigger
+### Programmatic Toggle
-The `` component offers a `.toggle()` method that allows to trigger the collapse programmatically.
+The `` component offers a `.toggle()` method that allows you to trigger the collapse programmatically.
This method is asynchronous and returns a promise that resolves with the current open state.
-It optionally takes a boolean parameter that forces open when `true` or close when `false`.
+It optionally takes a boolean parameter: `true` forces it open, and `false` forces it closed.
-
-To ensure good accessibility, identify the collapsible with an `id`,
-then add an `aria-controls` attribute to your control element referencing this `id`.
-Also make sure to add an `aria-expanded` attribute to the control element:
-if the collapsible element is closed, the attribute on the control element must have a value of `aria-expanded="false"`
-and `aria-expanded="true"` otherwise.
diff --git a/packages/documentation/src/stories/components/collapsible/collapsible.snapshot.stories.ts b/packages/documentation/src/stories/components/collapsible/collapsible.snapshot.stories.ts
index 38e0585172..552139bb72 100644
--- a/packages/documentation/src/stories/components/collapsible/collapsible.snapshot.stories.ts
+++ b/packages/documentation/src/stories/components/collapsible/collapsible.snapshot.stories.ts
@@ -2,13 +2,12 @@ import { html } from 'lit';
import type { Args, StoryContext, StoryObj } from '@storybook/web-components';
import { bombArgs } from '@/utils';
-import meta, { Default } from './collapsible.stories';
+import meta from './collapsible.stories';
const { id, ...metaWithoutId } = meta;
export default {
...metaWithoutId,
- decorators: [],
title: 'Snapshots',
};
@@ -16,21 +15,26 @@ type Story = StoryObj;
export const Collapsible: Story = {
render: (_args: Args, context: StoryContext) => {
- const templateVariants = bombArgs({
- collapsed: [false, true],
- }).map((args: Args) => {
- return html`
-