Search

Accordion

This page is currently under construction
Lism UI (@lism-css/ui) is still in preparation.

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.

Preview
<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 on Stack)
  • <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 (uses hidden="until-found")

Props

PropDescription
<Accordion.Root>
allowMultiple
Allows multiple accordions to be expanded simultaneously. By default, only one can be open at a time.
<Accordion.Item>
isOpen
Expands the item by default (adds data-opened). Use together with isOpen on <Accordion.Button> / <Accordion.Panel>.
<Accordion.Heading>
as
Specifies the HTML tag for the heading. Defaults to div (with role="heading" added automatically). If h2h6 is specified, role is not added.
<Accordion.Button>
isOpen
Sets aria-expanded to match the initial expanded state.
<Accordion.Panel>
flow
Flow layout setting passed to the content area (__content) inside the panel.
<Accordion.Panel>
isOpen
Shows the panel by default (removes hidden).

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.

Example

<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>

Changing the animation duration

The speed of the open/close animation is controlled by the --duration variable, which defaults to 0.25s. You can change it by setting the CSS variable on <Accordion.Root> (for all items) or on an individual <Accordion.Item>.

Preview
<Accordion.Root style={{ '--duration': '.15s' }}>
<Accordion.Item>
<Accordion.Heading>
<Accordion.Button p="20">Accordion Example 1</Accordion.Button>
</Accordion.Heading>
<Accordion.Panel p="20" pt="5">
...
</Accordion.Panel>
</Accordion.Item>
...
</Accordion.Root>

Opening the first item by default

To have an item expanded from the start, specify isOpen on each of <Accordion.Item>, <Accordion.Button>, and <Accordion.Panel>.

Because isOpen plays a different role on each component, specify it on all three. On <Accordion.Item> it adds data-opened to set the panel height and icon to the open state, on <Accordion.Button> it controls aria-expanded, and on <Accordion.Panel> it toggles hidden.

Preview

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 isOpen>
<Accordion.Heading>
<Accordion.Button p="20" isOpen>Accordion Label 1</Accordion.Button>
</Accordion.Heading>
<Accordion.Panel p="20" pt="5" isOpen>
...
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item bd-t>
<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>

Allowing multiple panels to be open

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.

Preview
<Accordion.Root allowMultiple bd>
<Accordion.Item>
<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 bd-t>
<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>

© Lism CSS. All rights reserved.