Accordion
A UI component for creating accordion elements.
It is built with <div> / <button> elements rather than <details> / <summary>, and uses JavaScript to control the open/close animation.
The panel uses hidden="until-found", so its content can be discovered by the browser’s in-page search even when the accordion is closed, and the panel will automatically expand when a match is found.
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
<Accordion.Root> <Accordion.Item> <Accordion.Heading> <Accordion.Button p="20">Accordion Example</Accordion.Button> </Accordion.Heading> <Accordion.Panel p="20" pt="5"> <DummyText length="l" /> </Accordion.Panel> </Accordion.Item> <Accordion.Item bd-t> <Accordion.Heading> <Accordion.Button p="20">Accordion Example 2</Accordion.Button> </Accordion.Heading> <Accordion.Panel p="20" pt="5"> <DummyText length="l" /> </Accordion.Panel> </Accordion.Item></Accordion.Root>Usage
Provided as Accordion from the @lism-css/ui package.
Import
import { Accordion } from '@lism-css/ui/react'; The following components are available:
<Accordion.Root>: The root element wrapping multiple accordion items (based onStack)<Accordion.Item>: An individual accordion element<Accordion.Heading>: Wrapper for the heading area (defaults to<div role="heading">)<Accordion.Button>: The toggle button (automatically includes<Accordion.Icon>at the end)<Accordion.Icon>: The open/close state indicator icon (rendered via CSS pseudo-elements)<Accordion.Panel>: The content panel that opens and closes (useshidden="until-found")
Props
| Property | Description |
|---|---|
<Accordion.Root> allowMultiple | Allows multiple accordions to be expanded simultaneously. By default, only one can be open at a time. |
<Accordion.Heading> as | Specifies the HTML tag for the heading. Defaults to div (with role="heading" added automatically). If h2–h6 is specified, role is not added. |
<Accordion.Panel> flow | Flow layout setting passed to the content area (__content) inside the panel. |
Structure
<Accordion.Root> <Accordion.Item> <Accordion.Heading> <Accordion.Button>Accordion Label</Accordion.Button> </Accordion.Heading> <Accordion.Panel p="20" pt="5"> ...Contents... </Accordion.Panel> </Accordion.Item></Accordion.Root><Accordion.Button> automatically includes <Accordion.Icon> at the end.
The icon is rendered using CSS pseudo-elements (::before / ::after), so no SVG specification is needed.
Source Code
The source code is available on GitHub.
Examples
Changing the heading tag
<Accordion.Heading> outputs a <div role="heading"> by default, but you can specify a heading tag like h3 via the as prop to render it as an actual heading element.
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
<Accordion.Root bd> <Accordion.Item> <Accordion.Heading as="h3"> <Accordion.Button p="20">Accordion Label</Accordion.Button> </Accordion.Heading> <Accordion.Panel p="20" pt="5"> <DummyText length="l" /> </Accordion.Panel> </Accordion.Item> <Accordion.Item bd-t> <Accordion.Heading as="h3"> <Accordion.Button p="20">Accordion Label</Accordion.Button> </Accordion.Heading> <Accordion.Panel p="20" pt="5"> <DummyText length="l" /> </Accordion.Panel> </Accordion.Item></Accordion.Root>Animation duration and allowing multiple panels
The speed of the open/close animation is controlled by the --duration variable, which defaults to 0.25s.
By default, only one accordion within the same <Accordion.Root> can be expanded at a time.
Specifying allowMultiple allows multiple panels to be open simultaneously.
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint. Occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis undeomnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.
Lorem ipsum dolor sit amet. Consectetur adipiscing elit, sed do eiusmod tempor Incididunt ut. Labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut. Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint.
<Accordion.Root g="1px" allowMultiple> <Accordion.Item style={{ '--duration': '.15s' }}> <Accordion.Heading> <Accordion.Button p="20">Accordion Label 1</Accordion.Button> </Accordion.Heading> <Accordion.Panel p="20" pt="5"> ... </Accordion.Panel> </Accordion.Item> <Accordion.Item style={{ '--duration': '.15s' }}> <Accordion.Heading> <Accordion.Button p="20">Accordion Label 2</Accordion.Button> </Accordion.Heading> <Accordion.Panel p="20" pt="5"> ... </Accordion.Panel> </Accordion.Item> ...</Accordion.Root>