Accordion
A vertically stacked set of interactive headings that each reveal a section of content.
tsx
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger,} from "@/components/ui/accordion"
export function AccordionDemo() { return ( <Accordion type="single" collapsible className="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> )}
Installation
CLI
bash
npx fivui add accordion
Manual
Copy and paste the following code into your project.
bash
npm install @radix-ui/react-accordion
components/ui/accordion.tsx
"use client"
import * as React from "react"import * as AccordionPrimitive from "@radix-ui/react-accordion"import { ChevronDown } from "lucide-react"
import { cn } from "@/lib/utils"
const Accordion = AccordionPrimitive.Root
const AccordionItem = React.forwardRef< React.ElementRef<typeof AccordionPrimitive.Item>, React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>>(({ className, ...props }, ref) => ( <AccordionPrimitive.Item ref={ref} className={cn("border-b", className)} {...props} />))AccordionItem.displayName = "AccordionItem"
const AccordionTrigger = React.forwardRef< React.ElementRef<typeof AccordionPrimitive.Trigger>, React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>>(({ className, children, ...props }, ref) => ( <AccordionPrimitive.Header className="flex"> <AccordionPrimitive.Trigger ref={ref} className={cn( "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180", className )} {...props} > {children} <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" /> </AccordionPrimitive.Trigger> </AccordionPrimitive.Header>))AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
const AccordionContent = React.forwardRef< React.ElementRef<typeof AccordionPrimitive.Content>, React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>>(({ className, children, ...props }, ref) => ( <AccordionPrimitive.Content ref={ref} className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down" {...props} > <div className={cn("pb-4 pt-0", className)}>{children}</div> </AccordionPrimitive.Content>))
AccordionContent.displayName = AccordionPrimitive.Content.displayName
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
Usage
tsx
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger,} from "@/components/ui/accordion"
tsx
<Accordion type="single" collapsible> <AccordionItem value="item-1"> <AccordionTrigger>Is it accessible?</AccordionTrigger> <AccordionContent> Yes. It adheres to the WAI-ARIA design pattern. </AccordionContent> </AccordionItem></Accordion>
Examples
Single
tsx
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger,} from "@/components/ui/accordion"
export function AccordionDemo() { return ( <Accordion type="single" collapsible className="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> )}
Multiple
tsx
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger,} from "@/components/ui/accordion"
export function AccordionMultiple() { return ( <Accordion type="multiple" className="w-full"> <AccordionItem value="item-1"> <AccordionTrigger>Can I open multiple items?</AccordionTrigger> <AccordionContent> Yes! When the accordion is set to type="multiple", you can open multiple items at once. </AccordionContent> </AccordionItem> <AccordionItem value="item-2"> <AccordionTrigger>Does it work with keyboard navigation?</AccordionTrigger> <AccordionContent> Yes. You can navigate through the accordion items using the Tab key and activate them with Enter or Space. </AccordionContent> </AccordionItem> <AccordionItem value="item-3"> <AccordionTrigger>Is it responsive?</AccordionTrigger> <AccordionContent> Yes. The accordion adapts to different screen sizes and works well on mobile devices. </AccordionContent> </AccordionItem> </Accordion> )}
With Default Value
This item is open by default because we set defaultValue="item-2" on the Accordion component. You can specify which item should be open initially.
tsx
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger,} from "@/components/ui/accordion"
export function AccordionWithDefault() { return ( <Accordion type="single" defaultValue="item-2" collapsible className="w-full"> <AccordionItem value="item-1"> <AccordionTrigger>What is FivUI?</AccordionTrigger> <AccordionContent> FivUI is a modern React component library built with Tailwind CSS, that allows copy-paste components. </AccordionContent> </AccordionItem> <AccordionItem value="item-2"> <AccordionTrigger>How does it work? (Default open)</AccordionTrigger> <AccordionContent> This item is open by default because we set defaultValue="item-2" on the Accordion component. </AccordionContent> </AccordionItem> <AccordionItem value="item-3"> <AccordionTrigger>Can I customize the styling?</AccordionTrigger> <AccordionContent> Absolutely! Since you own the code, you can customize every aspect of the components to match your design system. </AccordionContent> </AccordionItem> </Accordion> )}
API Reference
Accordion
Prop | Type | Default | Description |
---|---|---|---|
type | "single" | "multiple" | - | Determines whether one or multiple items can be opened at the same time |
collapsible | boolean | false | When type is "single", allows closing content when clicking trigger of an open item |
defaultValue | string | string[] | - | The value of the item to expand when initially rendered |
value | string | string[] | - | The controlled value of the item to expand |
onValueChange | function | - | Event handler called when the expanded state of an item changes |
AccordionItem
Prop | Type | Default | Description |
---|---|---|---|
value | string | - | A unique value for the item |
AccordionTrigger
and AccordionContent
inherit their props from their respective Radix UI primitives.