Accordion
The accordion component enables users to collapse and expand multiple content sections within a limited space. This helps group and hide content effectively, maintaining a clean interface and reducing clutter.
import {Accordion} from "@qualcomm-ui/react/accordion"Usage
- The accordion requires each of its items to have a unique
valueinput. - The accordion is keyboard-navigable once focused. Arrow keys can be used to move to the next or previous item. Home and End keys can be used to jump to the first or last item, respectively.
Examples
Simple
Here's a typical usage example that uses the shorthand syntax for the item.
Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas.
<Accordion.Root className="w-96" defaultValue={["a"]}>
<Accordion.Item
secondaryText="Secondary text"
text="Accordion Text 1"
value="a"
>
<LoremIpsum />
</Accordion.Item>
<Accordion.Item
secondaryText="Secondary text"
text="Accordion Text 2"
value="b"
>
<LoremIpsum />
</Accordion.Item>
</Accordion.Root>Composite
The following example is equivalent to the previous example, but uses the composite approach.
Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas.
<Accordion.ItemRoot value="a">
<Accordion.ItemTrigger>
<Accordion.ItemText>Accordion Text 1</Accordion.ItemText>
<Accordion.ItemSecondaryText>
Secondary text
</Accordion.ItemSecondaryText>
<Accordion.ItemIndicator />
</Accordion.ItemTrigger>
<Accordion.ItemContent>
<LoremIpsum />
</Accordion.ItemContent>
</Accordion.ItemRoot>Composite Layout
Use the composite form only when the simple approach can't achieve your desired layout or behavior. The following example demonstrates how to display the expand/collapse indicator at the start of the trigger by changing its DOM position.
<Accordion.Root className="w-96">
{items.map((item) => (
<Accordion.ItemRoot key={item.value} value={item.value}>
<Accordion.ItemTrigger>
<Accordion.ItemIndicator />
<Accordion.ItemText>{item.text}</Accordion.ItemText>
</Accordion.ItemTrigger>
<Accordion.ItemContent>{item.content}</Accordion.ItemContent>
</Accordion.ItemRoot>
))}
</Accordion.Root>Multiple
By default, only a single accordion section can be open at a time. Setting multiple allows multiple sections to be open or closed simultaneously.
<Accordion.Root className="w-96" multiple>
{items.map((item) => (
<Accordion.Item key={item.value} text={item.text} value={item.value}>
{item.content}
</Accordion.Item>
))}
</Accordion.Root>Collapsible
When multiple is not set, enabling collapsible lets the user close an open accordion item by clicking it again.
<Accordion.Root className="w-96" collapsible defaultValue={["a"]}>
{items.map((item) => (
<Accordion.Item key={item.value} text={item.text} value={item.value}>
{item.content}
</Accordion.Item>
))}
</Accordion.Root>Default Value
The defaultValue prop allows you to set the initial state for the accordion by specifying which accordion item or items (if multiple is set) should be open by default.
It expects an array of values that should match those passed to each Accordion.Item.
<Accordion.Root className="w-96" defaultValue={["a"]}>
{items.map((item) => (
<Accordion.Item key={item.value} text={item.text} value={item.value}>
{item.content}
</Accordion.Item>
))}
</Accordion.Root>Disabled
You can disable accordion items by setting their disabled prop. This prevents the item from being interacted with.
You can disable the entire accordion by setting the disabled prop on Accordion.Root.
<Accordion.Root className="w-full" disabled={disabled}>
{items.map((item) => (
<Accordion.Item
key={item.value}
disabled={item.disabled}
text={item.text}
value={item.value}
>
{item.content}
</Accordion.Item>
))}
</Accordion.Root>Uncontained
Set the uncontained prop when the accordion is not placed inside a container and needs to align flush with adjacent layout elements—such as when positioned directly below a paragraph of text. This prop removes the default horizontal padding from accordion items, allowing them to sit seamlessly within the surrounding content.
<Accordion.Root className="w-96" uncontained>
{items.map((item) => (
<Accordion.Item key={item.value} text={item.text} value={item.value}>
{item.content}
</Accordion.Item>
))}
</Accordion.Root>Size
Use the size prop to control the size of the accordion items. The available sizes are sm, md (default), and lg.
<Accordion.Root className="w-full" size={size}>
{items.map((item) => (
<Accordion.Item key={item.value} text={item.text} value={item.value}>
{item.content}
</Accordion.Item>
))}
</Accordion.Root>Secondary Text
Use the Accordion.ItemSecondaryText component to display additional text opposite the trigger title.
<Accordion.Root className="w-96">
{items.map((item) => (
<Accordion.Item
key={item.value}
secondaryText={item.secondaryText}
text={item.text}
value={item.value}
>
{item.content}
</Accordion.Item>
))}
</Accordion.Root>Icon
Pass an icon to the icon prop on the Accordion.ItemTrigger element to display it next to the trigger title.
<Accordion.Root className="w-96">
{items.map((item) => (
<Accordion.Item
key={item.value}
icon={FileChartColumn}
text={item.text}
value={item.value}
>
{item.content}
</Accordion.Item>
))}
</Accordion.Root>UX considerations
In order to prevent visual confusion, only one icon can appear next to the trigger title. If you place the indicator at the start, the icon prop will be ignored.
Controlled State
The Accordion follows our controlled state pattern with these three props:
- value - the controlled value that determines which accordion items are open.
- onValueChange - callback fired when the value changes:
(value: string[]) => void - defaultValue - initial state for uncontrolled mode
Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas.
<Accordion.Root
multiple
onValueChange={setCurrentValue}
value={currentValue}
>
<Accordion.Item text="Accordion Text 1" value="a">
<LoremIpsum />
</Accordion.Item>
<Accordion.Item text="Accordion Text 2" value="b">
<LoremIpsum />
</Accordion.Item>
<Accordion.Item text="Accordion Text 3" value="c">
<LoremIpsum />
</Accordion.Item>
</Accordion.Root>Focus Callback
The onFocusChange prop allows you to listen for focus events on the accordion's items.
<Accordion.Root
defaultValue={["a"]}
multiple
onFocusChange={(value) => setCurrentValue(value || "")}
>
{items.map((item) => (
<Accordion.Item key={item.value} text={item.text} value={item.value}>
{item.content}
</Accordion.Item>
))}
</Accordion.Root>Shortcuts
Item Content
The Accordion.ItemContent component is a shortcut for the following:
<AccordionItemContentAnimator>
<AccordionItemContentBody>{children}</AccordionItemContentBody>
</AccordionItemContentAnimator>Item Shorthand
The Accordion.Item component is a shortcut for the following:
<Accordion.ItemRoot>
<Accordion.ItemTrigger>
<Accordion.ItemText>{props.text}</Accordion.ItemText>
{props.secondaryText ? (
<Accordion.ItemSecondaryText>
{props.secondaryText}
</Accordion.ItemSecondaryText>
) : null}
<Accordion.ItemIndicator />
</Accordion.ItemTrigger>
<Accordion.ItemContent>{props.children}</Accordion.ItemContent>
</Accordion.ItemRoot>API
<Accordion.Root>
| Prop | Type | Default |
|---|---|---|
Whether sections can be collapsed (in non-multiple mode). | boolean | |
Initial value of the accordion. | string[] | |
The document's text/writing direction. | 'ltr' | 'rtl' | 'ltr' |
The disabled state of the accordion. | boolean | |
Whether multiple accordion items can be expanded at once. | boolean | |
Focus change callback. | ( | |
Value change callback. | ( | |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement | |
The size of the accordion. | | 'sm' | |
To display the accordion uncontained to the edges of its container. | boolean | |
Value(s) of the accordion's open item(s). | string[] |
booleanstring[]
'ltr' | 'rtl'
booleanboolean(
value: string,
) => void
(
value: string[],
) => void
| ReactElement
| ((
props: object,
) => ReactElement)
| 'sm'
| 'md'
| 'lg'
booleanstring[]
<Accordion.Item>
<div> element by default.| Prop | Type |
|---|---|
text * The primary text label for the item. | |
The value of the accordion item. | string |
Props applied to the content element. | |
The disabled state of the accordion item. | boolean |
An icon to display next to the trigger title. | LucideIcon |
id attribute. If
omitted, a unique identifier will be automatically generated for accessibility. | string |
Props applied to the indicator element. | |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
The secondary text label for the item. | |
Props applied to the secondary text element. | |
Props applied to the text element. | |
Props applied to the trigger element. |
stringbooleanLucideIconstring| ReactElement
| ((
props: object,
) => ReactElement)
<Accordion.ItemTrigger>
<button>
element by default.| Prop | Type |
|---|---|
An icon to display next to the trigger title. | LucideIcon |
id attribute. If
omitted, a unique identifier will be automatically generated for accessibility. | string |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
LucideIconstring| ReactElement
| ((
props: object,
) => ReactElement)
<Accordion.ItemText>
<Accordion.ItemSecondaryText>
<span> element by default.| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<Accordion.ItemIndicator>
<div> element by default.| Prop | Type | Default |
|---|---|---|
Indicator icon for the accordion item trigger. | | LucideIcon | ChevronDown |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| LucideIcon
| ReactNode
| ReactElement
| ((
props: object,
) => ReactElement)
<Accordion.ItemContent>
<div> element
by default.<CoreCollapsible.RootProvider open={open}>
<Accordion.ItemContentAnimator>
<Accordion.ItemContentBody>
{props.children}
</Accordion.ItemContentBody>
</Accordion.ItemContentAnimator>
</CoreCollapsible.RootProvider>
| Prop | Type |
|---|---|
Props applied to the content body element. | |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<Accordion.ItemContentAnimator>
<div> element by default.| Prop | Type |
|---|---|
id attribute. If
omitted, a unique identifier will be automatically generated for accessibility. | string |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
string| ReactElement
| ((
props: object,
) => ReactElement)
<Accordion.ItemContentBody>
<div> element by
default.| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<div>element by default.