Meet Frontfriend.Your brand. Your rules. Your agents, connected.Explore what’s new
DocumentationAccordion

Accordion

A vertically stacked set of interactive headings that each reveal a section of content.

Interactive preview

Rendered from the shared Frontfriend stories with React Base, the same preview Studio shows. Styling comes from your Design System; the code below is native to Reka UI.

Installation

Complete project setup first. Your configuration must select vue/reka and include your Design System ID.

pnpm exec frontfriend download accordion -f vue --primitive reka

Review dependencies reported by the downloader and keep your source changes in version control.

Usage

<script setup lang="ts">
import { Accordion } from "@/components/ui/accordion";
import { AccordionItem } from "@/components/ui/accordion";
import { AccordionTrigger } from "@/components/ui/accordion";
import { AccordionContent } from "@/components/ui/accordion";
import * as UI from "@/components/ui/accordion";

const Component = UI.Accordion;

const args = {
  "naked": false,
} satisfies Partial<
  InstanceType<typeof Component> extends { $props: infer Props } ? Props : {}
> &
  Record<string, unknown>;
</script>

<template>
  <div class="w-[400px]">
    <Accordion type="single" collapsible class="w-full" v-bind="args"
      ><AccordionItem value="item-1"
        ><AccordionTrigger>Is it accessible?</AccordionTrigger
        ><AccordionContent
          >Yes. It adheres to the WAI-ARIA design pattern.</AccordionContent
        ></AccordionItem
      ><AccordionItem value="item-2"
        ><AccordionTrigger>Is it styled?</AccordionTrigger
        ><AccordionContent
          >Yes. It comes with default styles that matches the other components'
          aesthetic.</AccordionContent
        ></AccordionItem
      ><AccordionItem value="item-3"
        ><AccordionTrigger>Is it animated?</AccordionTrigger
        ><AccordionContent
          >Yes. It's animated by default, but you can disable it if you
          prefer.</AccordionContent
        ></AccordionItem
      ></Accordion
    >
  </div>
</template>

One item, or several

Use type="multiple" when people need to compare content across sections. For a single-item accordion, keep the expanded state in the native shape of the selected target: React Aria uses expanded keys, Base UI uses a value array, Radix and Reka distinguish single and multiple values.

Keep item identities stable across renders. Put a short, descriptive label in each trigger and the actual content in its panel.

Accessibility

  • Keep the trigger a native primitive button and retain its expanded state.
  • Use headings that fit the surrounding page hierarchy.
  • Test keyboard navigation, activation and the relationship between trigger and panel.
  • Keep all content available when reduced motion is enabled.

Examples

Default

<script setup lang="ts">
import { Accordion } from "@/components/ui/accordion";
import { AccordionItem } from "@/components/ui/accordion";
import { AccordionTrigger } from "@/components/ui/accordion";
import { AccordionContent } from "@/components/ui/accordion";
import * as UI from "@/components/ui/accordion";

const Component = UI.Accordion;

const args = {

} satisfies Partial<
  InstanceType<typeof Component> extends { $props: infer Props } ? Props : {}
> &
  Record<string, unknown>;
</script>

<template>
  <div class="w-[400px]">
    <Accordion type="single" collapsible class="w-full" v-bind="args"
      ><AccordionItem value="item-1"
        ><AccordionTrigger>Is it accessible?</AccordionTrigger
        ><AccordionContent
          >Yes. It adheres to the WAI-ARIA design pattern.</AccordionContent
        ></AccordionItem
      ><AccordionItem value="item-2"
        ><AccordionTrigger>Is it styled?</AccordionTrigger
        ><AccordionContent
          >Yes. It comes with default styles that matches the other components'
          aesthetic.</AccordionContent
        ></AccordionItem
      ><AccordionItem value="item-3"
        ><AccordionTrigger>Is it animated?</AccordionTrigger
        ><AccordionContent
          >Yes. It's animated by default, but you can disable it if you
          prefer.</AccordionContent
        ></AccordionItem
      ></Accordion
    >
  </div>
</template>

Multiple

<script setup lang="ts">
import { Accordion } from "@/components/ui/accordion";
import { AccordionItem } from "@/components/ui/accordion";
import { AccordionTrigger } from "@/components/ui/accordion";
import { AccordionContent } from "@/components/ui/accordion";
import * as UI from "@/components/ui/accordion";

const Component = UI.Accordion;

const args = {

} satisfies Partial<
  InstanceType<typeof Component> extends { $props: infer Props } ? Props : {}
> &
  Record<string, unknown>;
</script>

<template>
  <div class="w-[400px]">
    <Accordion type="multiple" class="w-full"
      ><AccordionItem value="item-1"
        ><AccordionTrigger>Is it accessible?</AccordionTrigger
        ><AccordionContent
          >Yes. It adheres to the WAI-ARIA design pattern.</AccordionContent
        ></AccordionItem
      ><AccordionItem value="item-2"
        ><AccordionTrigger>Is it styled?</AccordionTrigger
        ><AccordionContent
          >Yes. It comes with default styles that matches the other components'
          aesthetic.</AccordionContent
        ></AccordionItem
      ><AccordionItem value="item-3"
        ><AccordionTrigger>Is it animated?</AccordionTrigger
        ><AccordionContent
          >Yes. It's animated by default, but you can disable it if you
          prefer.</AccordionContent
        ></AccordionItem
      ></Accordion
    >
  </div>
</template>

API reference

Frontfriend-owned props. Native HTML and inherited primitive props remain documented by Reka UI.

Accordion

Prop Type Default Description
class string —
last boolean —
naked boolean —

AccordionContent

Prop Type Default Description
class HTMLAttributes["class"] —

AccordionItem

Prop Type Default Description
class HTMLAttributes["class"] —

AccordionTrigger

Prop Type Default Description
class HTMLAttributes["class"] —

Configuration determines the actual classes and available styling hooks. See Theming & component configuration before introducing a repeated local override.