Accordion
Sections that expand and collapse, animated from a measured height.
Installation
Accordion ships with the library — install it once, then import:
import { Accordion } from "@delacour/react-native-ui/accordion";Or copy the source into your project, to own and edit it:
bunx delacour@latest add accordionUsage
import { Accordion } from "@/components/ui/accordion";
import { Text } from "@/components/ui/text";
import { View } from "react-native";
export default function Example() {
return (
<View className="flex-1 justify-center p-4">
<Accordion>
<Accordion.Item value="shipping">
<Accordion.Trigger>
<Accordion.Title>Shipping</Accordion.Title>
<Accordion.Description>Rates and delivery times</Accordion.Description>
</Accordion.Trigger>
<Accordion.Content>
<Text.Paragraph>Free over $50. Two to four working days.</Text.Paragraph>
</Accordion.Content>
</Accordion.Item>
<Accordion.Item value="returns">
<Accordion.Trigger>
<Accordion.Title>Returns</Accordion.Title>
<Accordion.Description>Thirty days, no questions</Accordion.Description>
</Accordion.Trigger>
<Accordion.Content>
<Text.Paragraph>Post it back in its original packaging for a full refund.</Text.Paragraph>
</Accordion.Content>
</Accordion.Item>
</Accordion>
</View>
);
}Variants
ListGroup's set, because an accordion is the same kind of thing.
<Accordion variant="secondary">…</Accordion>
<Accordion variant="tertiary">…</Accordion>
<Accordion variant="transparent">…</Accordion>Sizes
<Accordion size="sm">…</Accordion>
<Accordion size="md">…</Accordion>
<Accordion size="lg">…</Accordion>Selection
The root is a discriminated union on selectionMode: single carries string | null, where
null is a controlled empty; multiple carries string[].
<Accordion value={open} onValueChange={setOpen}>…</Accordion>
<Accordion selectionMode="multiple" value={open} onValueChange={setOpen}>…</Accordion>Indicators
<Accordion.Trigger>
<Icon icon={IconTruck} />
<Accordion.Title>Delivery</Accordion.Title>
<Accordion.Indicator />
</Accordion.Trigger>An indicator has to be a direct Accordion.Indicator child of the trigger — the trigger finds
it by element type, so a wrapped one is invisible and a second default gets composed in beside it.
Custom indicators
Use the render function to swap the glyph on state, and isAnimated={false} to opt out of the
rotation when the glyph itself carries the change.
<Accordion.Trigger>
<Accordion.Title>Details</Accordion.Title>
<Accordion.Indicator isAnimated={false}>
{({ isExpanded }) => <Icon icon={isExpanded ? IconMinus : IconPlus} />}
</Accordion.Indicator>
</Accordion.Trigger>The disabled fade lands on the item, never on the trigger. The trigger is a Pressable whose
Animated.View writes opacity every frame, so a class there is silently overwritten.
API Reference
Anatomy
| Part | What it is |
|---|---|
Accordion | The surface. Owns the selection mode and the shared axes |
Accordion.Item | One section: a trigger, and the panel it discloses |
Accordion.Trigger | The row that opens the item. A Pressable, so it inherits the whole vocabulary |
Accordion.Title | The trigger's primary line. Bare string children become one automatically |
Accordion.Description | The trigger's secondary line, stacked under the title |
Accordion.Indicator | The glyph that turns as the panel opens. Composed in when a trigger holds none |
Accordion.Content | The measured, clipped panel. Mounts on first expand and stays mounted |
Dividers between adjacent items are inserted for you, the way ListGroup does it. A Separator
placed by hand is never doubled; isDivided={false} turns the feature off.
AccordionProps
Prop
Type