Accordion

Sections that expand and collapse, animated from a measured height.

Open Source

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 accordion

Usage

app/index.tsx
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.

Variants
<Accordion variant="secondary">…</Accordion>
<Accordion variant="tertiary">…</Accordion>
<Accordion variant="transparent">…</Accordion>

Sizes

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[].

One at a time
Any number at once
<Accordion value={open} onValueChange={setOpen}>…</Accordion>

<Accordion selectionMode="multiple" value={open} onValueChange={setOpen}>…</Accordion>

Indicators

A glyph beside the title
<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

PartWhat it is
AccordionThe surface. Owns the selection mode and the shared axes
Accordion.ItemOne section: a trigger, and the panel it discloses
Accordion.TriggerThe row that opens the item. A Pressable, so it inherits the whole vocabulary
Accordion.TitleThe trigger's primary line. Bare string children become one automatically
Accordion.DescriptionThe trigger's secondary line, stacked under the title
Accordion.IndicatorThe glyph that turns as the panel opens. Composed in when a trigger holds none
Accordion.ContentThe 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

On this page