Accordion
Collapsible panel with an animated header and content area. Expand/collapse state is controlled by the parent.
Basic Usage
import { Accordion, Typography } from '@multinaire/expo-ui';
import { useState } from 'react';
function Example() {
const [active, setActive] = useState(false);
return (
<Accordion
active={active}
title="Section title"
onPress={() => setActive(!active)}
>
<Typography>Panel content</Typography>
</Accordion>
);
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
active | boolean | false | When true, the panel content is expanded |
leading | IconProps['icon'] | — | Icon name rendered before the title |
title | TranslationKey | — | Header title |
badge | ReactElement | — | Badge element rendered after the title, before the trailing icon |
trailing | IconProps['icon'] | dropdown chevron | Icon name for the trailing indicator. Defaults to a chevron (ArrowUp2/ArrowDown2) reflecting active |
onPress | () => void | — | Press handler for the header. When omitted, the header renders at reduced opacity to indicate it is non-interactive |
Examples
With Leading Icon
<Accordion
active={active}
leading="InfoCircle"
title="More information"
onPress={() => setActive(!active)}
>
<Typography color="neutral">Additional details go here.</Typography>
</Accordion>
With Badge
<Accordion
active={active}
title="Notifications"
badge={<Badge type="primary" title="3" />}
onPress={() => setActive(!active)}
>
<Typography>You have 3 unread notifications.</Typography>
</Accordion>
Custom Trailing Icon
<Accordion
active={active}
title="Settings"
trailing="ArrowRight2"
onPress={() => setActive(!active)}
>
<Typography>Panel content</Typography>
</Accordion>
Non-Interactive Header
<Accordion active title="Read-only section">
<Typography>This panel has no press handler, so the header renders dimmed.</Typography>
</Accordion>
Accordion Group
function AccordionGroup() {
const [openIndex, setOpenIndex] = useState<number | null>(0);
return (
<Container gap={variables.gap.medium}>
{sections.map((section, index) => (
<Accordion
key={section.title}
active={openIndex === index}
title={section.title}
onPress={() =>
setOpenIndex(openIndex === index ? null : index)
}
>
<Typography>{section.content}</Typography>
</Accordion>
))}
</Container>
);
}
Notes
Accordionis a controlled component — the parent ownsactivestate and toggles it viaonPress.- The panel is built on
Card, so it inherits the theme's border, radius, and background. - Expand/collapse is animated with
react-native-reanimatedby measuring the content's height and animating to it, so surrounding layout doesn't jump. - The content is re-measured whenever it changes size, so children that load or grow after mount are handled automatically — an open panel animates to its new height, and a closed one opens to the correct height next time. A panel rendered with
activealreadytruestarts open rather than animating open on mount.