Stacked sections that expand one at a time, or several with multiple. Each section is a child sui-accordion-item with its own header row; this element owns the open set, routes header clicks and moves focus between headers. Reach for it when a page groups settings or details a reader opens on demand.
Usage
<sui-accordion aria-label="Basic">
<sui-accordion-item expanded heading="Company details" subtitle="Name, EIN and addresses">Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.</sui-accordion-item>
<sui-accordion-item heading="Tax settings" meta="2 to review">Indiana sales tax registered. Kentucky registration is pending.</sui-accordion-item>
<sui-accordion-item heading="Numbering" meta="INV-1044 next">Invoices continue from INV-1043. Credit notes use the CN prefix.</sui-accordion-item>
</sui-accordion>
<script type="module">
import { defineCustomElements } from "@shineui/core/loader";
import "@shineui/core/shineui.css";
defineCustomElements();
const el = document.querySelector("sui-accordion");
el.expanded = []; /* number[] */
el.addEventListener("suiExpandedChange", (e) => console.log(e.detail));
</script>
import { SuiAccordion } from "@shineui/react";
import "@shineui/core/shineui.css";
export function Example() {
const expanded = []; /* number[] */
return (
<SuiAccordion aria-label="Basic" expanded={expanded} onSuiExpandedChange={(e) => console.log(e.detail)}>
<sui-accordion-item expanded heading="Company details" subtitle="Name, EIN and addresses">Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.</sui-accordion-item>
<sui-accordion-item heading="Tax settings" meta="2 to review">Indiana sales tax registered. Kentucky registration is pending.</sui-accordion-item>
<sui-accordion-item heading="Numbering" meta="INV-1044 next">Invoices continue from INV-1043. Credit notes use the CN prefix.</sui-accordion-item>
</SuiAccordion>
);
}
<script setup>
import { SuiAccordion } from "@shineui/vue";
import "@shineui/core/shineui.css";
const expanded = []; // number[]
const onChange = (e) => console.log(e.detail);
</script>
<template>
<SuiAccordion aria-label="Basic" :expanded="expanded" @sui-expanded-change="onChange"><sui-accordion-item expanded heading="Company details" subtitle="Name, EIN and addresses">Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.</sui-accordion-item>
<sui-accordion-item heading="Tax settings" meta="2 to review">Indiana sales tax registered. Kentucky registration is pending.</sui-accordion-item>
<sui-accordion-item heading="Numbering" meta="INV-1044 next">Invoices continue from INV-1043. Credit notes use the CN prefix.</sui-accordion-item></SuiAccordion>
</template>
import { Component } from "@angular/core";
import { SuiAccordion } from "@shineui/angular";
@Component({
standalone: true,
imports: [SuiAccordion],
template: `<sui-accordion aria-label="Basic" [(expanded)]="expanded"><sui-accordion-item expanded heading="Company details" subtitle="Name, EIN and addresses">Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.</sui-accordion-item>
<sui-accordion-item heading="Tax settings" meta="2 to review">Indiana sales tax registered. Kentucky registration is pending.</sui-accordion-item>
<sui-accordion-item heading="Numbering" meta="INV-1044 next">Invoices continue from INV-1043. Credit notes use the CN prefix.</sui-accordion-item></sui-accordion>`,
})
export class Example {
expanded: number[] = [];
}
Basic
Every section starts closed; expanded on an item opens it from plain HTML, and the accordion keeps its own expanded list in step. Sections take turns, so opening one closes the rest.
Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.Indiana sales tax registered. Kentucky registration is pending.Invoices continue from INV-1043. Credit notes use the CN prefix.
<sui-accordion aria-label="Basic">
<sui-accordion-item expanded heading="Company details" subtitle="Name, EIN and addresses">Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.</sui-accordion-item>
<sui-accordion-item heading="Tax settings" meta="2 to review">Indiana sales tax registered. Kentucky registration is pending.</sui-accordion-item>
<sui-accordion-item heading="Numbering" meta="INV-1044 next">Invoices continue from INV-1043. Credit notes use the CN prefix.</sui-accordion-item>
</sui-accordion>
Several open
multiple lets sections stand alone. expanded is the open index list and a property, not an attribute.
Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.Indiana sales tax registered. Kentucky registration is pending.Invoices continue from INV-1043. Credit notes use the CN prefix.
<sui-accordion id="acc-multi" aria-label="Several open" multiple>
<sui-accordion-item heading="Company details" subtitle="Name, EIN and addresses">Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.</sui-accordion-item>
<sui-accordion-item heading="Tax settings" meta="2 to review">Indiana sales tax registered. Kentucky registration is pending.</sui-accordion-item>
<sui-accordion-item heading="Numbering" meta="INV-1044 next">Invoices continue from INV-1043. Credit notes use the CN prefix.</sui-accordion-item>
</sui-accordion>
A disabled header grays out, refuses clicks, and the arrow keys step over it.
Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.Indiana sales tax registered. Kentucky registration is pending.Invoices continue from INV-1043. Credit notes use the CN prefix.
<sui-accordion id="acc-off" aria-label="Disabled section">
<sui-accordion-item expanded heading="Company details" subtitle="Name, EIN and addresses">Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.</sui-accordion-item>
<sui-accordion-item heading="Tax settings" meta="2 to review">Indiana sales tax registered. Kentucky registration is pending.</sui-accordion-item>
<sui-accordion-item heading="Numbering" meta="INV-1044 next" disabled>Invoices continue from INV-1043. Credit notes use the CN prefix.</sui-accordion-item>
</sui-accordion>
Events
suiExpandedChange carries the whole open index list and does not bubble, so an inner accordion never reports as the outer one; a field's suiChange inside a section does bubble. Each header is a button with aria-expanded and aria-controls, each body a region named by its header. A closed body is hidden.
Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.Indiana sales tax registered. Kentucky registration is pending.Invoices continue from INV-1043. Credit notes use the CN prefix.Open: Company details.
<div style="display:flex;flex-direction:column;gap:10px">
<sui-accordion id="acc-events" aria-label="Events" multiple>
<sui-accordion-item expanded heading="Company details" subtitle="Name, EIN and addresses">Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.</sui-accordion-item>
<sui-accordion-item heading="Tax settings" meta="2 to review">Indiana sales tax registered. Kentucky registration is pending.</sui-accordion-item>
<sui-accordion-item heading="Numbering" meta="INV-1044 next">Invoices continue from INV-1043. Credit notes use the CN prefix.</sui-accordion-item>
</sui-accordion>
<span id="acc-log" style="font:460 13px/1.6 var(--font-sans);color:var(--ink-muted)">Open: Company details.</span>
</div>
Writing expanded opens the sections and emits nothing, so a host that already knows the state never hears its own write echoed back. Writing an item's expanded does the same through the item, and the list follows.
Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.Indiana sales tax registered. Kentucky registration is pending.Invoices continue from INV-1043. Credit notes use the CN prefix.
<div style="display:flex;flex-direction:column;gap:10px">
<div style="display:flex;flex-wrap:wrap;gap:8px">
<sui-button id="acc-jump-tax" variant="outline" size="sm" label="Open tax settings"></sui-button>
<sui-button id="acc-jump-all" variant="outline" size="sm" label="Open every section"></sui-button>
<sui-button id="acc-jump-none" variant="ghost" size="sm" label="Close all"></sui-button>
</div>
<sui-accordion id="acc-driven" aria-label="Driven from script" multiple>
<sui-accordion-item heading="Company details" subtitle="Name, EIN and addresses">Falls City Supply Co. EIN 35-1882210. 410 Pearl Street, New Albany, IN 47150.</sui-accordion-item>
<sui-accordion-item heading="Tax settings" meta="2 to review">Indiana sales tax registered. Kentucky registration is pending.</sui-accordion-item>
<sui-accordion-item heading="Numbering" meta="INV-1044 next">Invoices continue from INV-1043. Credit notes use the CN prefix.</sui-accordion-item>
</sui-accordion>
</div>
Each header is drawn from its item's heading, subtitle, meta and disabled, and it redraws when one changes from script: a count can fall as work clears and a locked section can open once an earlier step is done, with no call on the parent. expanded opens a section from markup.
Indiana sales tax registered. Kentucky registration is pending.
Close September and roll balances into October.
<div style="display:flex;flex-direction:column;gap:12px">
<sui-accordion id="ai-live">
<sui-accordion-item id="ai-live-tax" heading="Tax settings" meta="2 to review" expanded><div style="font-size:13px;color:var(--ink-muted);line-height:1.7">Indiana sales tax registered. Kentucky registration is pending.</div></sui-accordion-item>
<sui-accordion-item id="ai-live-close" heading="Period close" subtitle="Opens once tax settings are reviewed" disabled><div style="font-size:13px;color:var(--ink-muted);line-height:1.7">Close September and roll balances into October.</div></sui-accordion-item>
</sui-accordion>
<div style="display:flex;gap:8px;flex-wrap:wrap">
<sui-button id="ai-live-review" variant="outline" size="sm" label="Review one"></sui-button>
</div>
</div>
// setup(root): properties and events
setup(root) {
const tax = root.querySelector('#ai-live-tax');
const close = root.querySelector('#ai-live-close');
let left = 2;
root.querySelector('#ai-live-review').addEventListener('click', () => {
if (left === 0) return;
left -= 1;
tax.meta = left ? `${left} to review` : 'Reviewed';
if (left === 0) {
close.disabled = false;
close.subtitle = 'Ready to run';
}
});
}
Keyboard
Key
Action
Tab sui-accordion
Moves to the next header, or out of the accordion. Every enabled header is a tab stop.
EnterSpace sui-accordion
Toggles the focused section.
ArrowDown sui-accordion
Moves focus to the next enabled header, wrapping to the first.
ArrowUp sui-accordion
Moves focus to the previous enabled header, wrapping to the last.
Home sui-accordion
Moves focus to the first enabled header.
End sui-accordion
Moves focus to the last enabled header.
API
<sui-accordion>
Properties
Property
Attribute
Type
Default
Description
expanded
property only
number[]
[]
Indexes of the open sections, in ascending order. Property, not attribute. Every section starts closed; a section whose item carries expanded joins the list when the accordion loads, so plain HTML opens one with the attribute. The list and the items' expanded stay in step both ways: writing the list opens and closes items, and writing an item's expanded updates the list. A write from script, to either, emits nothing.
multiple
multiple
boolean
false
Lets several sections stay open; otherwise opening one closes the rest.
Events
Event
Detail
React
Vue
Description
suiExpandedChange
number[]
onSuiExpandedChange
@sui-expanded-change
Fires after a header toggles, or when sections come or go and the open indexes move or drop; detail is the new expanded index list. Does not bubble, so an accordion inside a section never reports as the outer one.
Methods
Method
Signature
Description
setFocus()
setFocus() => Promise<void>
Moves keyboard focus to the first enabled header.
Slots
Slot
Description
(default)
sui-accordion-item children, in order.
<sui-accordion-item>
Properties
Property
Attribute
Type
Default
Description
disabled
disabled
boolean
false
Greys the header and blocks toggling.
expanded
expanded
boolean
false
Whether the content is shown. Put the attribute on an item to open it from plain HTML. Inside a sui-accordion the two stay in step: the accordion writes it from its expanded list, and a write here from script updates that list, closing the other sections unless the accordion is multiple; neither write emits anything. The panel's height opens and closes over the base duration, with the chevron; the content stays in the DOM through the collapse and is hidden once it has closed.
heading
heading
string
''
Section title (the reference title; renamed for the native attribute). It names the panel's region; when the parent sui-accordion carries an aria-label, the region is named "heading, accordion name", so two accordions with the same sections read apart in a landmark list.
meta
meta
stringstring | undefined
Muted tabular text at the right of the header (counts, statuses).
subtitle
subtitle
stringstring | undefined
Faint line under the title.
Methods
Method
Signature
Description
setFocus()
setFocus() => Promise<void>
Moves keyboard focus to the header button. Does nothing while the item is disabled.
Slots
Slot
Description
(default)
Section content (13px muted body copy, indented under the title).
Theming
Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.