Skip to content
lab components / Structure

Accordion

Use this component to group content that can be hidden, as to reduce the need to scroll when presenting multiple sections of content on a single page.

This is a Lab component!

That means it doesn't satisfy our definition of done and may be changed or even deleted. For an exact status, please reach out to the Fancy team through the dev_fancy or ux_fancy channels.

import { Accordion } from "@siteimprove/fancylab";

Our structure components are strongly interconnected. Make sure to read the structure component guide, to find out which components you need and how to combine them correctly.

#Examples

The Accordion component is based on the Card component, where the Card.Header is converted into a button. The heading functions as a control that enable users to reveal or hide the associated section of content.

Terms for understanding accordions include:

  • Accordion Header: Label for or thumbnail representing a section of content that also serves as a control for showing and hiding the section of content.
  • Accordion Content: Section of content associated with an accordion header.

#Basic Usage

In its simplest form, the Accordion just needs the header content being set with the Accordion.Content subcomponent and the content being set with Accordion.Body subcomponent.

<Accordion> <Accordion.Header>Accordion header</Accordion.Header> <Accordion.Body> <Content>Accordion content goes here</Content> </Accordion.Body> </Accordion>

#Header Usage

The Accordion takes props for the heading but alignment, tooltipText, and tooltipPlacement has been omitted since they are conflicting with accordion styling.

<Accordion> <Accordion.Header level="h1" lookalike="h3" lineHeight="multi-line"> Accordion header content </Accordion.Header> <Accordion.Body> <Content>Accordion content goes here</Content> </Accordion.Body> </Accordion>

The Accordion needs the footer being set with the Accordion.Footer subcomponent.

<Accordion> <Accordion.Header>Accordion header</Accordion.Header> <Accordion.Body> <Content>Accordion content goes here</Content> </Accordion.Body> <Accordion.Footer> <Content>Accordion footer</Content> </Accordion.Footer> </Accordion>

#Expand Usage

The Accordion can be expanded/collapsed from outside the component. The component keeps the state itself whether it's expanded or not, but it will update it if the expanded prop changes. This can also be used to expand the Accordion by default by setting expanded={true}

Accordion content goes here
const [expanded, setExpanded] = useState(true); return ( <> <Button onClick={() => setExpanded(!expanded)}>Toggle accordion</Button> <Accordion expanded={expanded}> <Accordion.Header>Accordion header</Accordion.Header> <Accordion.Body> <Content>Accordion content goes here</Content> </Accordion.Body> </Accordion> </> );

#Illustration Usage

Both the header and content takes a ReactNode so they can both just be an illustration. But remember alt text!

<Accordion> <Accordion.Header> <Illustration src={IllustrationPromote} alt="Promote content" size={"small"} /> </Accordion.Header> <Accordion.Body> <Illustration src={IllustrationInitiate} alt="Initiate content" /> </Accordion.Body> </Accordion>

#Table Usage

const [items, setItems] = useState(someData); const [sort, setSort] = useState<SortField<typeof items[0]>>({ property: "title", direction: "asc", }); const [loading, setLoading] = useState(true); useEffect(() => { setItems(sortItems(items, sort)); setLoading(false); }, [sort]); return ( <Accordion> <Accordion.Header>Table</Accordion.Header> <Accordion.Body> <Table columns={[ { header: { property: "title", content: "Dish", defaultSortDirection: "asc", "data-observe-key": "table-header-dish", }, render: (dto) => dto.title, options: { isKeyColumn: true, }, }, { header: { content: "Cook Time", tooltip: "in minutes", "data-observe-key": "table-header-cook-time", }, render: (dto) => dto.cookTime, }, { header: { property: "servings", content: "Servings", tooltip: "in persons", notSortable: true, "data-observe-key": "table-header-servings", }, render: (dto) => dto.servings, }, ]} items={items} sort={sort} setSort={(property, direction) => { setLoading(true); setSort({ property: property, direction: property === sort.property ? invertDirection(sort.direction) : direction, }); }} loading={loading} caption="Basic usage table" /> </Accordion.Body> </Accordion> );

#Properties

PropertyDescriptionDefinedValue
childrenOptional
element
expandedOptional
boolean
data-componentOptional
stringName of the component. Should only be set by components since it needs to stable. Used to track component usage
classNameOptional
stringCustom className that's applied to the outermost element (only intended for special cases)
styleOptional
objectStyle object to apply custom inline styles (only intended for special cases)
data-observe-keyOptional
stringUnique string, used by external script e.g. for event tracking

#Guidelines

#Best practices

  • Be mindful if you change focusable properties of the accordion header. Right now they are centered around revealing/hiding the content.
  • To add padding to the accordion content, use a content component. It can also be used to control the position and alignment of the accordion’s contents.

#Do not use when

  • -

#Accessibility

This component comes with built-in accessibility, no extra work required. The accordion header has aria-expanded and aria-controls to indicate to screen-reader users whether the accordion expanded and which content it controls.

Explore detailed guidelines for this component: Accessibility Specifications

#Writing

  • -