On this page
Import
import { Accordion } from '@envsemble/envui';
Usage
Accordion.Root holds an Accordion.Item for each section, with its heading as title and its panel as children. One item is open at a time; multiple lets several stay open. disabled on the root or an item turns it off.
import { Accordion } from '@envsemble/envui';
const questions = [
{
value: 'sharing',
question: 'Who can see a shared plan?',
answer: 'Everyone in the workspace can read it; only its editors can change it.',
},
{
value: 'moving',
question: 'Can I move a plan to another workspace?',
answer: 'Yes. Open the plan’s menu, choose Move, and pick a workspace you belong to.',
},
{
value: 'archive',
question: 'What happens to archived plans?',
answer: 'They stay readable and searchable, and you can restore them at any time.',
},
{
value: 'export',
question: 'Can I export a plan?',
answer: 'Export it as Markdown or PDF from the plan’s menu.',
},
];
export default function FrequentQuestions() {
return (
// One answer open at a time; the first starts open.
<Accordion.Root defaultValue={['moving']} style={{ inlineSize: 'min(100%, 32rem)' }}>
{questions.map(({ value, question, answer }) => (
<Accordion.Item key={value} value={value} title={question}>
{answer}
</Accordion.Item>
))}
</Accordion.Root>
);
}Open items
defaultValue names the items open at first, by their value; or control them with value and onValueChange, which receives the values of the open items. An item's own onOpenChange reports whether it is open.
const [open, setOpen] = useState<string[]>([]);
<Button onClick={() => setOpen(['billing'])}>Show billing help</Button>
<Accordion.Root value={open} onValueChange={setOpen}>
<Accordion.Item value="billing" title="Billing">…</Accordion.Item>
</Accordion.Root>
Find in page
hiddenUntilFound keeps closed panels in the page, so the browser's find in page reaches their text and opens the item that holds it, where the browser supports it.
Composition
The headings are h3; set headingLevel to fit the page's outline, and they look the same at every level. Show the next level inside a panel as a List rather than another accordion.
Customize
The parts are the accordion, env-accordion; each item, env-accordion-item, which draws the line under it; its heading's button, env-accordion-trigger, with the indicator, env-accordion-indicator, and the title, env-accordion-label; and the panel, env-accordion-content.
Accessibility
You provide
- Titles that say what each section holds.
headingLevelthat fits the page's outline.
envUI provides
- Each title is a button inside a heading, which reports whether its section is expanded and controls its panel.
- Tab reaches every heading. The arrow keys, Home and End don't move between them, as the current ARIA accordion pattern advises, so they stay with the page and the panels' content.
- A focus outline, and headings at least 2.75 rem tall on touch screens.
Props
Accordion.Root
A list of sections, each a heading that shows and hides its panel, separated by full-width hairlines. A plus at the start of a heading becomes a minus while its section is open. One item is open at a time unless `multiple` is set. Built on Base UI's Accordion.
| Prop | Type | Description |
|---|---|---|
children | ReactNode | The items: Accordion.Item, one for each section. |
value | readonly string[ | The values of the open items, for a controlled accordion: update it from onValueChange. Use defaultValue instead to leave it to the accordion. |
defaultValueDefault [] | readonly string[ | The values of the items open at first, for an accordion that keeps its own state. |
onValueChange | ( | Receives the values of the open items, each time an item opens or closes. |
multipleDefault false | boolean | Lets several items be open at once; otherwise opening one closes the one that was open. |
headingLevelDefault 3 | Exclude< | The level of each item's heading, for the page's outline; they look the same at every level. |
disabledDefault false | boolean | Every item ignores presses and can't be focused. |
skeletonDefault false | boolean | Shows it and its content as a busy skeleton while that loads; turning it on or off renders the content anew. |
Also accepts the native props of <div>, such as ref, className and aria-* attributes.
Accordion.Item
One section of an accordion: its heading, a button with a plus or minus at its start, and the panel below it.
| Prop | Type | Description |
|---|---|---|
title | ReactNode | The heading that opens and closes the section, in medium weight: say what the panel holds, such as a question it answers. Given as undefined, such as over a placeholder item, a skeleton shows a bar in its place. |
children | ReactNode | The panel, in muted text lined up with the title, shown while the item is open. |
value | string | Names the item in the accordion's value, for an accordion that is controlled or opens items at first. Without it, the item takes a generated one. |
disabledDefault false | boolean | The item ignores presses and can't be focused; it stays dimmed. |
onOpenChange | ( | Receives whether this item is open, each time it opens or closes. |
Also accepts the native props of <div>, such as ref, className and aria-* attributes.
Part names
Each part's class and state attributes are public and versioned, for an application's CSS to style.
env-accordion- The accordion: sections separated by full-width hairlines.
env-accordion-content- The panel's content, in muted text lined up with the title.
env-accordion-header- An item's heading, which holds its button.
env-accordion-indicator- The plus that becomes a minus while the item is open.
env-accordion-item- One section, with the hairline under it.
env-accordion-label- An item's title.
env-accordion-panel- The panel that opens below the heading.
env-accordion-trigger- The button that opens and closes the item.
data-disabled- Any value, or present on env-accordion-trigger
data-ending-style- Any value, or present on env-accordion-panel
data-env-skeleton- Any value, or present
data-interactive- Present on env-accordion-trigger
data-panel-open- Any value, or present on env-accordion-trigger
data-starting-style- Any value, or present on env-accordion-panel
Changelog
- 1.0.0
Accordion.
- 1.0.0-prerelease.6
A closing panel's content fades over the panel's whole closing,
--env-motion-duration-medium, so it leaves no empty band.Colors under the pointer and while pressed change with
--env-motion-ease-enter, rather than easing in slowly, so hover and press show from the first frame.A panel's content fades in and out as it grows and shrinks, and the plus and minus fade into each other.
A heading lays the shared state layer on hover and press, inset from the hairlines, with its focus ring tracing it; the title and panel sit 8 px in from the hairlines to match.