Accordion
<gui-accordion> stacks sections that open and close under their headers. Each item is a native
<details> you write, so it works with the keyboard and screen readers out of the box. The
element styles the items and keeps one open at a time.
Shipping
Returns
Warranty
import { GuiAccordion, GuiAccordionItem } from '@golemui/gui-components/react';import '@golemui/gui-components/index.css';
export function AccordionBasic() { return ( <GuiAccordion> <GuiAccordionItem> <details open> <summary id="faq-shipping">Shipping</summary> <section role="region" aria-labelledby="faq-shipping"> Orders ship within two working days, from our warehouse in Leeds. </section> </details> </GuiAccordionItem> <GuiAccordionItem> <details> <summary id="faq-returns">Returns</summary> <section role="region" aria-labelledby="faq-returns"> Send anything back within 30 days, at no cost. </section> </details> </GuiAccordionItem> <GuiAccordionItem> <details> <summary id="faq-warranty">Warranty</summary> <section role="region" aria-labelledby="faq-warranty"> Every notebook has a two-year warranty. </section> </details> </GuiAccordionItem> </GuiAccordion> );}import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';import '@golemui/gui-components/accordion';import '@golemui/gui-components/accordion-item';
@Component({ selector: 'app-accordion-basic', schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <gui-accordion> <gui-accordion-item> <details open> <summary id="faq-shipping">Shipping</summary> <section role="region" aria-labelledby="faq-shipping"> Orders ship within two working days, from our warehouse in Leeds. </section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="faq-returns">Returns</summary> <section role="region" aria-labelledby="faq-returns"> Send anything back within 30 days, at no cost. </section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="faq-warranty">Warranty</summary> <section role="region" aria-labelledby="faq-warranty"> Every notebook has a two-year warranty. </section> </details> </gui-accordion-item> </gui-accordion> `,})export class AccordionBasicComponent {}<script setup lang="ts">import '@golemui/gui-components/accordion';import '@golemui/gui-components/accordion-item';import '@golemui/gui-components/index.css';</script>
<template> <gui-accordion> <gui-accordion-item> <details open> <summary id="faq-shipping">Shipping</summary> <section role="region" aria-labelledby="faq-shipping"> Orders ship within two working days, from our warehouse in Leeds. </section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="faq-returns">Returns</summary> <section role="region" aria-labelledby="faq-returns"> Send anything back within 30 days, at no cost. </section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="faq-warranty">Warranty</summary> <section role="region" aria-labelledby="faq-warranty"> Every notebook has a two-year warranty. </section> </details> </gui-accordion-item> </gui-accordion></template>import { LitElement, html } from 'lit';import { customElement } from 'lit/decorators.js';import '@golemui/gui-components/accordion';import '@golemui/gui-components/accordion-item';import '@golemui/gui-components/index.css';
@customElement('accordion-basic')export class AccordionBasic extends LitElement { protected override createRenderRoot() { return this; }
override render() { return html` <gui-accordion> <gui-accordion-item> <details open> <summary id="faq-shipping">Shipping</summary> <section role="region" aria-labelledby="faq-shipping"> Orders ship within two working days, from our warehouse in Leeds. </section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="faq-returns">Returns</summary> <section role="region" aria-labelledby="faq-returns"> Send anything back within 30 days, at no cost. </section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="faq-warranty">Warranty</summary> <section role="region" aria-labelledby="faq-warranty"> Every notebook has a two-year warranty. </section> </details> </gui-accordion-item> </gui-accordion> `; }}<gui-accordion> <gui-accordion-item> <details open> <summary id="faq-shipping">Shipping</summary> <section role="region" aria-labelledby="faq-shipping"> Orders ship within two working days, from our warehouse in Leeds. </section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="faq-returns">Returns</summary> <section role="region" aria-labelledby="faq-returns"> Send anything back within 30 days, at no cost. </section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="faq-warranty">Warranty</summary> <section role="region" aria-labelledby="faq-warranty"> Every notebook has a two-year warranty. </section> </details> </gui-accordion-item></gui-accordion>The element’s entry point is @golemui/gui-components/accordion, which registers
<gui-accordion> and its part, <gui-accordion-item>, and nothing else. To install the package
and load the stylesheet, see Installation.
The @golemui/gui-components/react components have typed props and an on* prop for each event. React 18 or later.
import { GuiAccordion, GuiAccordionItem } from '@golemui/gui-components/react';import '@golemui/gui-components/index.css';
export function AccordionExample() { return ( <GuiAccordion multiple > <GuiAccordionItem> <details open> <summary id="faq-shipping">Shipping</summary> <section role="region" aria-labelledby="faq-shipping">…</section> </details> </GuiAccordionItem> </GuiAccordion> );}Add CUSTOM_ELEMENTS_SCHEMA to the component that uses the tags, and the stylesheet to styles in angular.json.
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';import '@golemui/gui-components/accordion';
@Component({ selector: 'app-accordion-example', schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <gui-accordion multiple > <gui-accordion-item> <details open> <summary id="faq-shipping">Shipping</summary> <section role="region" aria-labelledby="faq-shipping">…</section> </details> </gui-accordion-item> </gui-accordion> `,})export class AccordionExampleComponent {}"styles": ["node_modules/@golemui/gui-components/lib/styles/index.css"]Tell Vue's compiler that gui-* tags are custom elements, and add the typings once for typed props and @gui-* handlers.
<script setup lang="ts">import '@golemui/gui-components/accordion';import '@golemui/gui-components/index.css';</script>
<template> <gui-accordion multiple > <gui-accordion-item> <details open> <summary id="faq-shipping">Shipping</summary> <section role="region" aria-labelledby="faq-shipping">…</section> </details> </gui-accordion-item> </gui-accordion></template>vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('gui-') } },});import type {} from '@golemui/gui-components/vue';The page's stylesheet styles the gui-* elements, so it only reaches them outside a shadow root. Render the host component into the light DOM too, as below, or load the stylesheet into its shadow root.
import { LitElement, html } from 'lit';import { customElement } from 'lit/decorators.js';import '@golemui/gui-components/accordion';import '@golemui/gui-components/index.css';
@customElement('accordion-example')export class AccordionExample extends LitElement { protected override createRenderRoot() { return this; }
override render() { return html` <gui-accordion multiple > <gui-accordion-item> <details open> <summary id="faq-shipping">Shipping</summary> <section role="region" aria-labelledby="faq-shipping">…</section> </details> </gui-accordion-item> </gui-accordion> `; }}With any bundler, such as Vite. Import the element once, anywhere, and use the tag in your markup.
<gui-accordion multiple> <gui-accordion-item> <details open> <summary id="faq-shipping">Shipping</summary> <section role="region" aria-labelledby="faq-shipping">…</section> </details> </gui-accordion-item></gui-accordion>
<script type="module" src="./main.js"></script>import '@golemui/gui-components/accordion';import '@golemui/gui-components/index.css';Put an item inside it for each section, each one a <details> with its <summary> as the
header. Put the content in a <section role="region"> named by its summary: the stylesheet draws the
content’s box on it, and screen readers can find the open section by its header. The element
never adds or removes your content, so your framework renders the items like any other markup.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
multiple | boolean | false | Lets several items be open at once. |
Events
Every event bubbles and is composed, so you can listen on any ancestor.
| Event | Description |
|---|---|
gui-toggle | An item opened or closed: the event's target is the item, and detail.open its new state. The items an opening closes fire theirs after the opened item's. |
Examples
Section titled “Examples”Several open items
Section titled “Several open items”By default, opening an item closes the one that was open. With multiple, items open and close
on their own.
Account
Notifications
import { GuiAccordion, GuiAccordionItem, GuiCheckbox, GuiTextinput,} from '@golemui/gui-components/react';import '@golemui/gui-components/index.css';
export function AccordionMultiple() { return ( <GuiAccordion multiple> <GuiAccordionItem> <details open> <summary id="settings-account">Account</summary> <section role="region" aria-labelledby="settings-account"> <GuiTextinput label="Display name" value="Grace Hopper" /> </section> </details> </GuiAccordionItem> <GuiAccordionItem> <details open> <summary id="settings-notifications">Notifications</summary> <section role="region" aria-labelledby="settings-notifications"> <GuiCheckbox label="Email me when someone mentions me" value /> </section> </details> </GuiAccordionItem> </GuiAccordion> );}import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';import '@golemui/gui-components/accordion';import '@golemui/gui-components/accordion-item';import '@golemui/gui-components/checkbox';import '@golemui/gui-components/textinput';
@Component({ selector: 'app-accordion-multiple', schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <gui-accordion multiple> <gui-accordion-item> <details open> <summary id="settings-account">Account</summary> <section role="region" aria-labelledby="settings-account"> <gui-textinput label="Display name" value="Grace Hopper" ></gui-textinput> </section> </details> </gui-accordion-item> <gui-accordion-item> <details open> <summary id="settings-notifications">Notifications</summary> <section role="region" aria-labelledby="settings-notifications"> <gui-checkbox label="Email me when someone mentions me" value="true" ></gui-checkbox> </section> </details> </gui-accordion-item> </gui-accordion> `,})export class AccordionMultipleComponent {}<script setup lang="ts">import '@golemui/gui-components/accordion';import '@golemui/gui-components/accordion-item';import '@golemui/gui-components/checkbox';import '@golemui/gui-components/textinput';import '@golemui/gui-components/index.css';</script>
<template> <gui-accordion :multiple="true"> <gui-accordion-item> <details open> <summary id="settings-account">Account</summary> <section role="region" aria-labelledby="settings-account"> <gui-textinput label="Display name" value="Grace Hopper" ></gui-textinput> </section> </details> </gui-accordion-item> <gui-accordion-item> <details open> <summary id="settings-notifications">Notifications</summary> <section role="region" aria-labelledby="settings-notifications"> <gui-checkbox label="Email me when someone mentions me" :value="true" ></gui-checkbox> </section> </details> </gui-accordion-item> </gui-accordion></template>import { LitElement, html } from 'lit';import { customElement } from 'lit/decorators.js';import '@golemui/gui-components/accordion';import '@golemui/gui-components/accordion-item';import '@golemui/gui-components/checkbox';import '@golemui/gui-components/textinput';import '@golemui/gui-components/index.css';
@customElement('accordion-multiple')export class AccordionMultiple extends LitElement { protected override createRenderRoot() { return this; }
override render() { return html` <gui-accordion multiple> <gui-accordion-item> <details open> <summary id="settings-account">Account</summary> <section role="region" aria-labelledby="settings-account"> <gui-textinput label="Display name" value="Grace Hopper" ></gui-textinput> </section> </details> </gui-accordion-item> <gui-accordion-item> <details open> <summary id="settings-notifications">Notifications</summary> <section role="region" aria-labelledby="settings-notifications"> <gui-checkbox label="Email me when someone mentions me" value="true" ></gui-checkbox> </section> </details> </gui-accordion-item> </gui-accordion> `; }}<gui-accordion multiple> <gui-accordion-item> <details open> <summary id="settings-account">Account</summary> <section role="region" aria-labelledby="settings-account"> <gui-textinput label="Display name" value="Grace Hopper"></gui-textinput> </section> </details> </gui-accordion-item> <gui-accordion-item> <details open> <summary id="settings-notifications">Notifications</summary> <section role="region" aria-labelledby="settings-notifications"> <gui-checkbox label="Email me when someone mentions me" value="true"></gui-checkbox> </section> </details> </gui-accordion-item></gui-accordion>Responding to a change
Section titled “Responding to a change”Each item fires gui-toggle when the user opens or closes it, with the new state in
detail.open. The event bubbles, so listen on the accordion and read the item from
event.target. When an opening closes another item, the closed item fires its gui-toggle after
the opened one’s. Open each question below in turn.
How do seats work?
Can I cancel at any time?
import { useState } from 'react';import { GuiAccordion, GuiAccordionItem } from '@golemui/gui-components/react';import type { GuiToggleEventDetail } from '@golemui/gui-components';import '@golemui/gui-components/index.css';
export function AccordionEvents() { const [log, setLog] = useState('');
const onToggle = (question: string) => (event: CustomEvent<GuiToggleEventDetail>) => setLog( (log) => `${log}${event.detail.open ? 'Opened' : 'Closed'} "${question}". `, );
return ( <> <GuiAccordion id="plan-faq"> <GuiAccordionItem onGuiToggle={onToggle('How do seats work?')}> <details open> <summary id="plan-faq-seats">How do seats work?</summary> <section role="region" aria-labelledby="plan-faq-seats"> You pay for each member of your workspace. Guests are free. </section> </details> </GuiAccordionItem> <GuiAccordionItem onGuiToggle={onToggle('Can I cancel at any time?')}> <details> <summary id="plan-faq-cancel">Can I cancel at any time?</summary> <section role="region" aria-labelledby="plan-faq-cancel"> Yes. Your plan stays active until the end of the billing period. </section> </details> </GuiAccordionItem> </GuiAccordion> <p id="plan-faq-log" role="status"> {log} </p> </> );}import { Component, CUSTOM_ELEMENTS_SCHEMA, signal } from '@angular/core';import type { GuiAccordionItemEvents, GuiEventMap,} from '@golemui/gui-components';import '@golemui/gui-components/accordion';import '@golemui/gui-components/accordion-item';
type ItemEvent<K extends keyof typeof GuiAccordionItemEvents> = GuiEventMap< typeof GuiAccordionItemEvents>[K];
@Component({ selector: 'app-accordion-events', schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <gui-accordion id="plan-faq"> <gui-accordion-item (gui-toggle)="onToggle('How do seats work?', $event)"> <details open> <summary id="plan-faq-seats">How do seats work?</summary> <section role="region" aria-labelledby="plan-faq-seats"> You pay for each member of your workspace. Guests are free. </section> </details> </gui-accordion-item> <gui-accordion-item (gui-toggle)="onToggle('Can I cancel at any time?', $event)" > <details> <summary id="plan-faq-cancel">Can I cancel at any time?</summary> <section role="region" aria-labelledby="plan-faq-cancel"> Yes. Your plan stays active until the end of the billing period. </section> </details> </gui-accordion-item> </gui-accordion> <p id="plan-faq-log" role="status">{{ log() }}</p> `,})export class AccordionEventsComponent { log = signal('');
onToggle(question: string, event: Event) { const { open } = (event as ItemEvent<'gui-toggle'>).detail; this.log.update( (log) => log + `${open ? 'Opened' : 'Closed'} "${question}". `, ); }}<script setup lang="ts">import { ref } from 'vue';import '@golemui/gui-components/accordion';import '@golemui/gui-components/accordion-item';import '@golemui/gui-components/index.css';
const log = ref('');
function onToggle(question: string, open: boolean) { log.value += `${open ? 'Opened' : 'Closed'} "${question}". `;}</script>
<template> <gui-accordion id="plan-faq"> <gui-accordion-item @gui-toggle="onToggle('How do seats work?', $event.detail.open)" > <details open> <summary id="plan-faq-seats">How do seats work?</summary> <section role="region" aria-labelledby="plan-faq-seats"> You pay for each member of your workspace. Guests are free. </section> </details> </gui-accordion-item> <gui-accordion-item @gui-toggle="onToggle('Can I cancel at any time?', $event.detail.open)" > <details> <summary id="plan-faq-cancel">Can I cancel at any time?</summary> <section role="region" aria-labelledby="plan-faq-cancel"> Yes. Your plan stays active until the end of the billing period. </section> </details> </gui-accordion-item> </gui-accordion> <p id="plan-faq-log" role="status">{{ log }}</p></template>import { LitElement, html } from 'lit';import { customElement, state } from 'lit/decorators.js';import type { GuiAccordionEvents, GuiEventMap } from '@golemui/gui-components';import '@golemui/gui-components/accordion';import '@golemui/gui-components/accordion-item';import '@golemui/gui-components/index.css';
type AccordionEvent<K extends keyof typeof GuiAccordionEvents> = GuiEventMap< typeof GuiAccordionEvents>[K];
@customElement('accordion-events')export class AccordionEvents extends LitElement { @state() private log = '';
protected override createRenderRoot() { return this; }
private onToggle(event: AccordionEvent<'gui-toggle'>) { if (!(event.target instanceof Element)) return; const question = event.target.querySelector('summary')?.textContent; this.log += `${event.detail.open ? 'Opened' : 'Closed'} "${question}". `; }
override render() { return html` <gui-accordion id="plan-faq" @gui-toggle=${this.onToggle}> <gui-accordion-item> <details open> <summary id="plan-faq-seats">How do seats work?</summary> <section role="region" aria-labelledby="plan-faq-seats"> You pay for each member of your workspace. Guests are free. </section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="plan-faq-cancel">Can I cancel at any time?</summary> <section role="region" aria-labelledby="plan-faq-cancel"> Yes. Your plan stays active until the end of the billing period. </section> </details> </gui-accordion-item> </gui-accordion> <p id="plan-faq-log" role="status">${this.log}</p> `; }}<gui-accordion id="plan-faq"> <gui-accordion-item> <details open> <summary id="plan-faq-seats">How do seats work?</summary> <section role="region" aria-labelledby="plan-faq-seats"> You pay for each member of your workspace. Guests are free. </section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="plan-faq-cancel">Can I cancel at any time?</summary> <section role="region" aria-labelledby="plan-faq-cancel"> Yes. Your plan stays active until the end of the billing period. </section> </details> </gui-accordion-item></gui-accordion><p id="plan-faq-log" role="status"></p>
<script type="module"> const log = document.querySelector('#plan-faq-log');
document.querySelector('#plan-faq').addEventListener('gui-toggle', (event) => { const question = event.target.querySelector('summary').textContent; log.textContent += `${event.detail.open ? 'Opened' : 'Closed'} "${question}". `; });</script>Opening items from your code
Section titled “Opening items from your code”Set open on an item to open or close it yourself. Setting it fires no gui-toggle, and it
doesn’t close the other items, even without multiple.
Version 2.1
Version 2.0
import { useState } from 'react';import { GuiAccordion, GuiAccordionItem, GuiButton,} from '@golemui/gui-components/react';import '@golemui/gui-components/index.css';
const releases = [ { id: 'release-2-1', title: 'Version 2.1', notes: 'Dark mode and a new calendar.', }, { id: 'release-2-0', title: 'Version 2.0', notes: 'Shared projects and comments.', },];
export function AccordionControlled() { const [open, setOpen] = useState(releases.map(() => false));
return ( <> <GuiButton id="release-expand" variant="outlined" size="sm" label="Expand all" onClick={() => setOpen(releases.map(() => true))} /> <GuiAccordion id="release-history" multiple> {releases.map((release, index) => ( <GuiAccordionItem key={release.id} open={open[index]} onGuiToggle={(event) => setOpen((current) => current.map((value, i) => i === index ? event.detail.open : value, ), ) } > <details> <summary id={release.id}>{release.title}</summary> <section role="region" aria-labelledby={release.id}> {release.notes} </section> </details> </GuiAccordionItem> ))} </GuiAccordion> </> );}import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, viewChildren,} from '@angular/core';import type { GuiAccordionItem } from '@golemui/gui-components';import '@golemui/gui-components/accordion';import '@golemui/gui-components/accordion-item';import '@golemui/gui-components/button';
@Component({ selector: 'app-accordion-controlled', schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <gui-button id="release-expand" variant="outlined" size="sm" label="Expand all" (click)="expandAll()" ></gui-button> <gui-accordion id="release-history" multiple> <gui-accordion-item #item> <details> <summary id="release-2-1">Version 2.1</summary> <section role="region" aria-labelledby="release-2-1"> Dark mode and a new calendar. </section> </details> </gui-accordion-item> <gui-accordion-item #item> <details> <summary id="release-2-0">Version 2.0</summary> <section role="region" aria-labelledby="release-2-0"> Shared projects and comments. </section> </details> </gui-accordion-item> </gui-accordion> `,})export class AccordionControlledComponent { items = viewChildren<string, ElementRef<GuiAccordionItem>>('item', { read: ElementRef, });
expandAll() { for (const item of this.items()) item.nativeElement.open = true; }}<script setup lang="ts">import { ref } from 'vue';import '@golemui/gui-components/accordion';import '@golemui/gui-components/accordion-item';import '@golemui/gui-components/button';import '@golemui/gui-components/index.css';
const open = ref([false, false]);
function expandAll() { open.value = [true, true];}</script>
<template> <gui-button id="release-expand" variant="outlined" size="sm" label="Expand all" @click="expandAll" ></gui-button> <gui-accordion id="release-history" :multiple="true"> <gui-accordion-item :open="open[0]" @gui-toggle="open[0] = $event.detail.open" > <details> <summary id="release-2-1">Version 2.1</summary> <section role="region" aria-labelledby="release-2-1"> Dark mode and a new calendar. </section> </details> </gui-accordion-item> <gui-accordion-item :open="open[1]" @gui-toggle="open[1] = $event.detail.open" > <details> <summary id="release-2-0">Version 2.0</summary> <section role="region" aria-labelledby="release-2-0"> Shared projects and comments. </section> </details> </gui-accordion-item> </gui-accordion></template>import { LitElement, html } from 'lit';import { customElement, queryAll } from 'lit/decorators.js';import type { GuiAccordionItem } from '@golemui/gui-components';import '@golemui/gui-components/accordion';import '@golemui/gui-components/accordion-item';import '@golemui/gui-components/button';import '@golemui/gui-components/index.css';
@customElement('accordion-controlled')export class AccordionControlled extends LitElement { @queryAll('#release-history gui-accordion-item') private items!: NodeListOf<GuiAccordionItem>;
protected override createRenderRoot() { return this; }
private expandAll() { for (const item of this.items) item.open = true; }
override render() { return html` <gui-button id="release-expand" variant="outlined" size="sm" label="Expand all" @click=${this.expandAll} ></gui-button> <gui-accordion id="release-history" multiple> <gui-accordion-item> <details> <summary id="release-2-1">Version 2.1</summary> <section role="region" aria-labelledby="release-2-1"> Dark mode and a new calendar. </section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="release-2-0">Version 2.0</summary> <section role="region" aria-labelledby="release-2-0"> Shared projects and comments. </section> </details> </gui-accordion-item> </gui-accordion> `; }}<gui-button id="release-expand" variant="outlined" size="sm" label="Expand all"></gui-button><gui-accordion id="release-history" multiple> <gui-accordion-item> <details> <summary id="release-2-1">Version 2.1</summary> <section role="region" aria-labelledby="release-2-1">Dark mode and a new calendar.</section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="release-2-0">Version 2.0</summary> <section role="region" aria-labelledby="release-2-0">Shared projects and comments.</section> </details> </gui-accordion-item></gui-accordion>
<script type="module"> const items = document.querySelectorAll('#release-history gui-accordion-item');
document.querySelector('#release-expand').addEventListener('click', () => { for (const item of items) item.open = true; });</script>gui-accordion-item
Section titled “gui-accordion-item”<gui-accordion-item> is an item of an accordion: it holds one <details>, and keeps its open
property in step with the details, both ways. Without open set, it takes the details’ own
state, so <details open> is all you need to start an item open. An item outside an accordion
works on its own, with the same look, as a single section that opens and closes.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
open | boolean | – | Whether the item is open. Without a value it takes the details' own open. Setting it fires no gui-toggle. |
Events
Every event bubbles and is composed, so you can listen on any ancestor.
| Event | Description |
|---|---|
gui-toggle | The user opened or closed the item, or its accordion closed it because the user opened another. detail.open is the new state. |
Styling
Section titled “Styling”Anatomy
Section titled “Anatomy”<gui-accordion> and its items render nothing of their own: the anatomy is your markup. The item
reflects its state in the open attribute, and the stylesheet draws the arrow at the end of each
summary with CSS:
<gui-accordion> <gui-accordion-item open> <details open> <summary id="faq-shipping">Shipping</summary> <section role="region" aria-labelledby="faq-shipping"> Orders ship within two working days, from our warehouse in Leeds. </section> </details> </gui-accordion-item> <gui-accordion-item> <details> <summary id="faq-returns">Returns</summary> <section role="region" aria-labelledby="faq-returns">…</section> </details> </gui-accordion-item> <!-- …one item per section --></gui-accordion>The parts have no classes. Style them by tag:
| Selector | Part |
|---|---|
gui-accordion | The stack of items. |
gui-accordion[multiple] | An accordion that lets several items open. |
gui-accordion-item | An item. |
gui-accordion-item[open] | An open item. |
gui-accordion-item > details > summary | The header. |
gui-accordion-item > details > summary::after | The arrow. It turns over while the item is open. |
gui-accordion-item section[role='region'] | The content’s box. |
Tokens
Section titled “Tokens”The accordion reads these design tokens. Set them on :root to change every accordion, or on any
element to change the accordions inside it:
| Token | What it styles |
|---|---|
--gui-bg-default | The background of the headers and the content. |
--gui-border-default | The borders of the headers and the content. |
--gui-text-default | The text, the arrow, and the border and ring of the focused header. |
--gui-space-3 | The padding of the headers and the content, and the space around the accordion. |
--gui-font-family | The font. |
--gui-font-sm | The text size. |
--gui-caret-shape, --gui-caret-image | The shape of the arrow. See Carets. |
/* Left-aligned, roomier headers. */gui-accordion-item > details > summary { text-align: start;}
.faq { --gui-space-3: 1rem;}To restyle beyond the tokens, see Overriding styles; for dark mode and the Clay theme, see Themes and dark mode.
Accessibility
Section titled “Accessibility”- Native disclosure. Each header is a native
<summary>: browsers expose it as a button and announce whether its section is expanded. The element adds no ARIA of its own. - Regions. A
<section role="region">named by its summary witharia-labelledbylets screen reader users jump to the open section by its header. For a long list of items, leave out the role, so the page doesn’t fill with landmarks. - Arrow. The arrow is drawn with CSS, so screen readers don’t read it, and it keeps the text color in forced-colors modes.
- Before the upgrade. The details work on their own before the element loads, such as in a page rendered on the server: only closing the other items waits for the element. See Server rendering.
| Key | Action |
|---|---|
| Tab | Moves focus from header to header, and into the open sections. |
| Enter | Opens or closes the focused item. |
| Space | Opens or closes the focused item. |
What every element shares is in Accessibility.