Accordion
Accordions enable multiple content sections to be displayed conditionally in a limited space.
import {QAccordion} from "@qui/react"
Accessibility
- This implementation is based on the ARIA Accordion pattern.
Examples
Expanded State
By default, only one panel can be expanded at a time. To change this behavior, set multiple
to true.
Default
Multiple
import {ReactNode} from "react"import {QAccordion,QAccordionButton,QAccordionItem,QAccordionPanel,} from "@qui/react"export default function Showcase(): ReactNode {return (<div className="grid grid-cols-1 justify-center gap-8 sm:grid-cols-2"><div className="flex max-w-[280px] flex-col gap-4"><span className="text-primary q-font-heading-xs">Default</span><QAccordion className="w-[280px]"><QAccordionItem><QAccordionButton>Panel 1</QAccordionButton><QAccordionPanel>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua.</QAccordionPanel></QAccordionItem><QAccordionItem><QAccordionButton>Panel 2</QAccordionButton><QAccordionPanel>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua.</QAccordionPanel></QAccordionItem><QAccordionItem><QAccordionButton>Panel 3</QAccordionButton><QAccordionPanel>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua.</QAccordionPanel></QAccordionItem></QAccordion></div><div className="flex max-w-[280px] flex-col gap-4"><span className="text-primary q-font-heading-xs">Multiple</span><QAccordion className="w-[280px]" multiple><QAccordionItem><QAccordionButton>Panel 1</QAccordionButton><QAccordionPanel>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua.</QAccordionPanel></QAccordionItem><QAccordionItem><QAccordionButton>Panel 2</QAccordionButton><QAccordionPanel>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua.</QAccordionPanel></QAccordionItem><QAccordionItem><QAccordionButton>Panel 3</QAccordionButton><QAccordionPanel>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua.</QAccordionPanel></QAccordionItem></QAccordion></div></div>)}
Sizes
Customize size using the size property.
import {ReactNode} from "react"import {Box} from "lucide-react"import {QAccordionItemSize} from "@qui/base"import {QAccordion,QAccordionButton,QAccordionItem,QAccordionPanel,} from "@qui/react"const sizes: QAccordionItemSize[] = ["s", "m", "l"]export default function Sizes(): ReactNode {return (<div className="flex flex-wrap justify-center gap-4">{sizes.map((size) => {return (<QAccordionkey={size}// define a max width so that the collapsed and expanded accordion are// always the same width.className="w-[280px]"size={size}><QAccordionItem><QAccordionButton startIcon={Box}>Size {size}</QAccordionButton><QAccordionPanel>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua.</QAccordionPanel></QAccordionItem></QAccordion>)})}</div>)}
Customization
Each item's button and content are customizable.
import {ReactNode} from "react"import {AlertTriangle} from "lucide-react"import {QAccordion,QAccordionButton,QAccordionItem,QAccordionPanel,QNotification,} from "@qui/react"export default function ContentCustomization(): ReactNode {return (<div className="flex flex-wrap justify-center gap-4"><QAccordion className="w-[350px]"><QAccordionItem><QAccordionButton>Default Button</QAccordionButton><QAccordionPanel>Default content style</QAccordionPanel></QAccordionItem><QAccordionItem><QAccordionButton startIcon={AlertTriangle}>Customized Button</QAccordionButton><QAccordionPanel><QNotification label="Custom Content" /></QAccordionPanel></QAccordionItem></QAccordion></div>)}
Controlled Accordion
The component can be controlled or uncontrolled.
When you supply the onExpandedChange and expanded props, the component is controlled
. Otherwise, the component is uncontrolled
and the value is tracked internally.
Learn more about controlled and uncontrolled components in the related React Documentation.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Default Active State
Use the defaultExpanded input to configure the accordion to open a specific index (or indices) on initialization.
Note: this will only impact the accordion when it's first initialized. For fully controlled behavior, refer to the controlled example.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
import {ReactNode} from "react"import {QAccordion,QAccordionButton,QAccordionItem,QAccordionPanel,} from "@qui/react"export default function DefaultActiveState(): ReactNode {return (<div className="flex flex-wrap justify-center gap-4"><QAccordion className="w-[280px]" defaultExpanded={0}><QAccordionItem><QAccordionButton>Panel 1</QAccordionButton><QAccordionPanel>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua.</QAccordionPanel></QAccordionItem><QAccordionItem><QAccordionButton>Panel 2</QAccordionButton><QAccordionPanel>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua.</QAccordionPanel></QAccordionItem><QAccordionItem><QAccordionButton>Panel 3</QAccordionButton><QAccordionPanel>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed doeiusmod tempor incididunt ut labore et dolore magna aliqua.</QAccordionPanel></QAccordionItem></QAccordion></div>)}
Multiple Type Parameter
The value type of the expanded and defaultExpanded props are inferred from the value of the multiple prop. This is accomplished using TypeScript generics. Here's what you need to know: when multiple is true
, these props are assumed to be of type number[]
. Otherwise, these values default to the non-array number
type. This also applies to the value parameter of the onExpandedChange callback.
Consider the following example:
export function Example(): ReactNode {const [index, setIndex] = useState<number>(0)return (<>{/** since `multiple` is not true, TypeScript knows that the expanded* value is of type number.*/}<QAccordion expanded={index} onExpandedChange={setIndex}></QAccordion>{/** This will emit an error because index is of type `number`, but the* accordion is expecting `number[]` since `multiple` is true.*/}<QAccordionexpanded={index}multipleonExpandedChange={setIndex}></QAccordion></>)}
API
QAccordionProps
Note that the QAccordionProps
are generic and include the following type parameters:
- C: inferred from the
as
prop. This is the React ElementType or ComponentType of the component's root element. - Multiple: inferred from the
multiple
prop.
Name & Description | Option(s) | Default |
---|---|---|
If true, an animation will play when an item is expanded or collapsed. |
| true |
The component used for the root node. It can be a React component or
element. |
| 'div' |
The className property of the Element
interface gets and sets the value of the
class attribute
of the specified element. |
| |
Default visible indices. |
| |
Used to manually control accordion item visibility. |
| |
Modify the placement of the expand icon |
| 'end' |
| ||
Callback fired whenever an item is expanded or collapsed.
|
| |
Size of the accordion item and its contents. |
| |
The style global attribute
contains CSS styling
declarations to be applied to the element. | CSSProperties |
Type
boolean
Default
true
Description
If true, an animation will play when an item is expanded or collapsed.
Type
| ElementType| ComponentType
Default
'div'
Description
The component used for the root node. It can be a React component or
element.
Type
string
Description
The className property of the Element
interface gets and sets the value of the
class attribute
of the specified element.
Type
| number| Array<number>
Description
Default visible indices.
Type
| number| Array<number>
Description
Used to manually control accordion item visibility.
Type
| 'start'| 'end'
Default
'end'
Description
Modify the placement of the expand icon
Type
boolean
Description
Allow more than one panel to be open at a time. Note that the value of this
prop determines the value of the Multiple
type parameter.
Type
(expandedItems: Multiple extends true? number[]: number,event: SyntheticEvent,itemIndex: number,expanded: boolean,) => void
Description
Callback fired whenever an item is expanded or collapsed.
- expandedItemsThe updated state. Will be an array if multiple is
true
, otherwise this will be a single value. - eventThe DOM event that triggered this change, typically a click or keypress.
- itemIndexThe index of the selected item.
- expandedWhether the item is expanded as a result of this change.
Type
| 's'| 'm'| 'l'
Description
Size of the accordion item and its contents.
Type
CSSProperties
Description
The style global attribute
contains CSS styling
declarations to be applied to the element.
QAccordionItemProps
Name & Description | Option(s) | Default |
---|---|---|
The component used for the root node. It can be a React component or
element. |
| 'div' |
The className property of the Element
interface gets and sets the value of the
class attribute
of the specified element. |
| |
If true, the accordion item will be disabled. |
| false |
If true, the divider after the accordion item will be hidden. |
| false |
The style global attribute
contains CSS styling
declarations to be applied to the element. | CSSProperties |
Type
| ElementType| ComponentType
Default
'div'
Description
The component used for the root node. It can be a React component or
element.
Type
string
Description
The className property of the Element
interface gets and sets the value of the
class attribute
of the specified element.
Type
boolean
Default
false
Description
If true, the accordion item will be disabled.
Type
boolean
Default
false
Description
If true, the divider after the accordion item will be hidden.
Type
CSSProperties
Description
The style global attribute
contains CSS styling
declarations to be applied to the element.
Keyboard Events
If an accordion item's button is focused:
Moves focus to the next item's button. If focus is on the last accordion item's button, moves focus to the first accordion item's button.
Moves focus to the previous item's button. If focus is on the first accordion item's button, moves focus to the last accordion item's button.
Toggles the visibility of the panel: if the item's panel is closed, it is opened. If the item's panel is open, it is closed.