Accordion

Import
import { Accordion } from "reshaped";
import type { AccordionProps } from "reshaped";
Related components

Accordion is a compound component that includes Accordion.Trigger and Account.Content in it. When it comes to styles, Accordion provides a toggle icon and content transitions, while all other layout styles can be fully customised. For example, you can pick your own typography with the Text utility and decide which gap you want to use.

<Accordion gap={4} iconSize={6}>
  <Accordion.Trigger>
    <Text variant="featured-3" weight="medium">
      How to enable dark mode?
    </Text>
  </Accordion.Trigger>
  <Accordion.Content>
    <View backgroundColor="neutral-faded" height="80px" borderRadius="small" />
  </Accordion.Content>
</Accordion>

Accordion can be used as a controlled or uncontrolled component. By default, Accordion is uncontrolled and lets you define its default state using the defaultActive property. In this case, all change events are handled automatically.

<Accordion gap={4} defaultActive>
  <Accordion.Trigger>
    <View backgroundColor="neutral-faded" height="32px" borderRadius="small" />
  </Accordion.Trigger>
  <Accordion.Content>
    <View backgroundColor="neutral-faded" height="80px" borderRadius="small" />
  </Accordion.Content>
</Accordion>

If you need to control the state of the component manually, you can use the active property instead. That will give you complete control of the content visibility and will stop handling the state automatically. You will have to update the state using the onToggle handler and will be able to add custom logic before the state changes for the user.

<Accordion
  active
  gap={4}
  onToggle={() => {
    /* Change the state here */
  }}
>
  <Accordion.Trigger>
    <View backgroundColor="neutral-faded" height="32px" borderRadius="small" />
  </Accordion.Trigger>
  <Accordion.Content>
    <View backgroundColor="neutral-faded" height="80px" borderRadius="small" />
  </Accordion.Content>
</Accordion>

Accordion comes with almost zero styles, which means you can build your own custom layout composition with it. For example, you can combine multiple Accordions together and render the Accordion in a styled View when it's active. Same way, you can change the layout of the Accordion.Trigger content.

const Component = () => {
  const [activeValue, setActiveValue] = React.useState<number | null>(null);

  return (
    <View gap={2}>
      {[1, 2, 3].map((i) => (
        <View
          key={i}
          animated
          backgroundColor={activeValue === i ? "neutral-faded" : undefined}
          borderRadius="large"
          padding={2}
        >
          <Accordion
            active={activeValue === i}
            onToggle={(active) => setActiveValue(active ? i : null)}
            gap={3}
          >
            <Accordion.Trigger>
              <View direction="row" gap={2} align="center">
                <Avatar size={8} initials={i.toString()} color="neutral" />
                <View.Item grow>Accordion trigger</View.Item>
              </View>
            </Accordion.Trigger>
            <Accordion.Content>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris
              nisi ut aliquip ex ea commodo consequat.
            </Accordion.Content>
          </Accordion>
        </View>
      ))}
    </View>
  );
}

Accordion.Trigger can be used with render props, which means it won't render the default trigger and instead will give you access to all attributes required for it to work. You can pass those attributes to any other component to keep the behaviour accessible.

For example, you can open an Accordion with a Button component and sync its highlighted property with the state of the Accordion.

<Accordion gap={2}>
  <Accordion.Trigger>
    {(attributes, { active }) => (
      <Button attributes={attributes} highlighted={active}>
        Toggle
      </Button>
    )}
  </Accordion.Trigger>
  <Accordion.Content>
    <View backgroundColor="neutral-faded" height={10} />
  </Accordion.Content>
</Accordion>
  • Only content inside the active Accordion can be focused with keyboard
  • Accordion content area is labelled by the trigger content
Professionally crafted React & Figma components for building beautiful products or starting your own design system
Built with Reshaped in Amsterdam ❤️
Contact us·License agreement·FAQ·
© Reshaped 2025