Accordion
A stack of headings that open to show more.
Preview
tsx
import { Accordion } from '@kerf-js/veneer'export function Boxed() { return ( <Accordion defaultOpen={['rollback']} items={QUESTIONS} /> )}const QUESTIONS = [ { value: 'rollback', title: 'How do I roll back a deploy?', content: 'Open the deploy you want and press ' + 'Promote. Traffic moves over in about ten seconds.', }, { value: 'domains', title: 'Can I bring my own domain?', content: 'Yes. Add it under Settings, then ' + 'point a CNAME at kerf.app.', }, { value: 'bill', title: 'What counts towards my bill?', content: 'Requests and build minutes. Preview ' + 'deploys are free.', },]Installation
npm install @kerf-js/veneerTry it
Change the controls: the preview and its code update together. The address keeps what you set, so you can link to it.
Live preview
Controls
Variant
Codeupdates as you change the controls
import { Accordion } from '@kerf-js/veneer'<Accordion defaultOpen={['rollback']} items={QUESTIONS} />Usage
tsx
import { Accordion } from '@kerf-js/veneer'<Accordion defaultOpen={['rollback']} items={QUESTIONS}/>Line
Hairlines only, for inside a card.
tsx
import { Accordion } from '@kerf-js/veneer'export function Line() { return ( <Accordion variant="line" defaultOpen={['rollback']} items={QUESTIONS} /> )}const QUESTIONS = [ { value: 'rollback', title: 'How do I roll back a deploy?', content: 'Open the deploy you want and press ' + 'Promote. Traffic moves over in about ten seconds.', }, { value: 'domains', title: 'Can I bring my own domain?', content: 'Yes. Add it under Settings, then ' + 'point a CNAME at kerf.app.', }, { value: 'bill', title: 'What counts towards my bill?', content: 'Requests and build minutes. Preview ' + 'deploys are free.', },]Several open
multiple leaves the others alone.
tsx
import { Accordion } from '@kerf-js/veneer'export function Multiple() { return ( <Accordion multiple defaultOpen={['rollback', 'bill']} items={QUESTIONS} /> )}const QUESTIONS = [ { value: 'rollback', title: 'How do I roll back a deploy?', content: 'Open the deploy you want and press ' + 'Promote. Traffic moves over in about ten seconds.', }, { value: 'domains', title: 'Can I bring my own domain?', content: 'Yes. Add it under Settings, then ' + 'point a CNAME at kerf.app.', }, { value: 'bill', title: 'What counts towards my bill?', content: 'Requests and build minutes. Preview ' + 'deploys are free.', },]A disabled item
Set disabled on the item, and say why in its title.
tsx
import { Accordion } from '@kerf-js/veneer'export function Disabled() { return ( <Accordion items={[ { value: 'plan', title: 'Plan', content: 'Team, billed monthly.', }, { value: 'seats', title: 'Seats', content: 'Eight of ten in use.', }, { value: 'sso', title: 'Single sign-on (Enterprise)', content: '', disabled: true, }, ]} /> )}Hearing what is open
onChange gets the open values each time.
tsx
import { state } from '@kerf-js/core'import { Accordion, Stack, Text } from '@kerf-js/veneer'export function HeardChange() { const open = state(['rollback']) return ( <Stack gap="group"> <Accordion multiple defaultOpen={['rollback']} onChange={(list) => (open.value = list)} items={QUESTIONS} /> <Text subtle> {open.value.length} of {QUESTIONS.length} open </Text> </Stack> )}const QUESTIONS = [ { value: 'rollback', title: 'How do I roll back a deploy?', content: 'Open the deploy you want and press ' + 'Promote. Traffic moves over in about ten seconds.', }, { value: 'domains', title: 'Can I bring my own domain?', content: 'Yes. Add it under Settings, then ' + 'point a CNAME at kerf.app.', }, { value: 'bill', title: 'What counts towards my bill?', content: 'Requests and build minutes. Preview ' + 'deploys are free.', },]Project settings
An item's content can be any JSX.
tsx
import { Accordion, Input, Stack, Switch} from '@kerf-js/veneer'export function Settings() { return ( <Accordion variant="line" defaultOpen={['general']} items={[ { value: 'general', title: 'General', content: ( <Input label="Project name" defaultValue="storefront" /> ), }, { value: 'build', title: 'Build', content: ( <Stack gap="related"> <Input label="Build command" defaultValue="npm run build" /> <Switch defaultChecked> Cache dependencies </Switch> </Stack> ), }, { value: 'alerts', title: 'Alerts', content: ( <Switch>Tell me when a deploy fails</Switch> ), }, ]} /> )}When to use
Accessibility
- Enter
- Opens or closes the focused item
- Space
- Opens or closes the focused item
- ↑↓
- Moves between headings
- HomeEnd
- Jumps to the first or last heading
- Each title is a real button inside a heading. Set
levelso the heading fits the page outline.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
items | AccordionItem[] | — | The entries: value, title, content and optionally disabled. |
variant | "line" | "boxed" | 'boxed' | Which form it takes. |
multiple | boolean | false | More than one open at once. |
defaultOpen | string[] | [] | What starts open. |
level | 2 | 3 | 4 | 6 | 5 | 3 | The heading level of each title: one below the heading the accordion sits under. Default 3, in a page section. |
| Event | Type | Default | Description |
|---|---|---|---|
onChange | ((open: string[]) => void) | — | Called with the new value. |
Parts
Every element carries a stable name, so you can style it from your own CSS: [data-scope="accordion"] [data-part="trigger"]
triggerrootitemheadingchevroncontentsweep