shadcn.io is not affiliated with official shadcn/ui
Shadcn Accordion for React and Tailwind
Open one panel or many. For FAQs, settings, and other disclosure UI.
Our flagship product combines cutting-edge technology with sleek design. Built with premium materials, it offers unparalleled performance and reliability.
Key features include advanced processing capabilities, and an intuitive user interface designed for both beginners and experts.
We offer worldwide shipping through trusted courier partners. Standard delivery takes 3-5 business days, while express shipping ensures delivery within 1-2 business days.
All orders are carefully packaged and fully insured. Track your shipment in real-time through our dedicated tracking portal.
We stand behind our products with a comprehensive 30-day return policy. If you're not completely satisfied, simply return the item in its original condition.
Our hassle-free return process includes free return shipping and full refunds processed within 48 hours of receiving the returned item.
Installation
bunx --bun shadcn@latest add https://kit.dev/r/accordion.jsonpnpm dlx shadcn@latest add https://kit.dev/r/accordion.jsonnpx shadcn@latest add https://kit.dev/r/accordion.jsonyarn shadcn@latest add https://kit.dev/r/accordion.jsonInstall the following dependencies:
bun add @ark-ui/react lucide-reactpnpm add @ark-ui/react lucide-reactnpm install @ark-ui/react lucide-reactyarn add @ark-ui/react lucide-reactAdd the following to your globals.css.
@theme inline {
--animate-slide-down: slideDown 0.2s ease-out;
--animate-slide-in: slideIn 0.2s ease-out;
--animate-slide-out: slideOut 0.2s ease-out;
--animate-slide-up: slideUp 0.2s ease-out;
}
[data-slot="accordion-content"][data-orientation="horizontal"] > * {
white-space: nowrap;
}
[data-slot="accordion-content"][data-state="closed"]:not([data-orientation="horizontal"]) {
animation-name: slideUp, accordion-fade-out;
}
[data-slot="accordion-content"][data-state="closed"][data-orientation="horizontal"] {
animation-name: slideOut, accordion-fade-out;
will-change: width;
}
[data-slot="accordion-content"][data-state="open"], [data-slot="accordion-content"][data-state="closed"] {
animation-duration: 200ms;
animation-timing-function: ease-out;
}
[data-slot="accordion"][data-motion] [data-slot="accordion-content"][data-state="open"]:not([data-orientation="horizontal"]) {
animation-name: slideDown, accordion-fade-in;
}
[data-slot="accordion"][data-motion] [data-slot="accordion-content"][data-state="open"][data-orientation="horizontal"] {
animation-name: slideIn, accordion-fade-in;
will-change: width;
}
@keyframes accordion-fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes accordion-fade-out {
from { opacity: 1; }
to { opacity: 0; }
}
@keyframes slideDown {
from { height: 0; }
to { height: var(--height); }
}
@keyframes slideIn {
from { width: 0; }
to { width: var(--width); }
}
@keyframes slideOut {
from { width: var(--width); }
to { width: 0; }
}
@keyframes slideUp {
from { height: var(--height); }
to { height: 0; }
}Copy and paste the following code into your project.
"use client";
import {
Accordion as ArkAccordion,
useAccordion as useArkAccordion,
useAccordionContext as useArkAccordionContext,
useAccordionItemContext as useArkAccordionItemContext,
} from "@ark-ui/react/accordion";
import { ChevronDownIcon } from "lucide-react";
import type React from "react";
import { useCallback, useState } from "react";
import { cn } from "@/lib/utils";
export const useAccordion = useArkAccordion;
export const useAccordionContext = useArkAccordionContext;
export const useAccordionItemContext = useArkAccordionItemContext;
export const AccordionContext = ArkAccordion.Context;
export const AccordionItemContext = ArkAccordion.ItemContext;
const accordionRootClassName = cn(
"group/accordion",
"data-[orientation=horizontal]:flex data-[orientation=horizontal]:h-80 data-[orientation=horizontal]:max-h-[calc(100vh-8rem)] data-[orientation=horizontal]:flex-row"
);
export const Accordion = (
props: React.ComponentProps<typeof ArkAccordion.Root>
) => {
const {
orientation,
collapsible = true,
lazyMount,
unmountOnExit,
className,
onValueChange,
...rest
} = props;
const isHorizontal = orientation === "horizontal";
const [motion, setMotion] = useState(false);
const handleValueChange = useCallback(
(details: Parameters<NonNullable<typeof onValueChange>>[0]) => {
setMotion(true);
onValueChange?.(details);
},
[onValueChange]
);
return (
<ArkAccordion.Root
{...rest}
className={cn(accordionRootClassName, className)}
collapsible={collapsible}
data-motion={motion ? "" : undefined}
data-slot="accordion"
lazyMount={lazyMount ?? !isHorizontal}
onValueChange={handleValueChange}
orientation={orientation}
unmountOnExit={unmountOnExit ?? !isHorizontal}
/>
);
};
export const AccordionRootProvider = (
props: React.ComponentProps<typeof ArkAccordion.RootProvider>
) => {
const { className, ...rest } = props;
return (
<ArkAccordion.RootProvider
className={cn(accordionRootClassName, className)}
data-slot="accordion"
{...rest}
/>
);
};
export const AccordionItem = (
props: React.ComponentProps<typeof ArkAccordion.Item>
) => {
const { className, ...rest } = props;
return (
<ArkAccordion.Item
className={cn(
"border-b last:border-b-0 [overflow-anchor:none]",
"data-[orientation=horizontal]:flex data-[orientation=horizontal]:border-b-0 data-[orientation=horizontal]:border-e",
className
)}
data-slot="accordion-item"
{...rest}
/>
);
};
export const AccordionTrigger = (
props: React.ComponentProps<typeof ArkAccordion.ItemTrigger>
) => {
const { className, children, ...rest } = props;
return (
<ArkAccordion.ItemTrigger
className={cn(
"flex items-center justify-between gap-3",
"px-2",
"text-start font-medium text-sm",
"rounded-md border border-transparent bg-transparent",
"outline-none",
"disabled:pointer-events-none disabled:opacity-64 disabled:grayscale",
"focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-ring/32",
"[&_[data-state=open]>svg]:rotate-180",
"data-[orientation=vertical]:w-full data-[orientation=vertical]:min-h-10 data-[orientation=vertical]:py-4",
"data-[orientation=horizontal]:h-full data-[orientation=horizontal]:min-w-10 data-[orientation=horizontal]:[writing-mode:sideways-lr]",
className
)}
data-slot="accordion-trigger"
{...rest}
>
{children}
<ArkAccordion.ItemIndicator
className="inline-flex items-center justify-center data-[orientation=horizontal]:hidden"
data-slot="accordion-indicator"
>
<ChevronDownIcon
className={cn(
"size-4",
"shrink-0",
"text-muted-foreground",
"pointer-events-none",
"transition-transform duration-200",
"motion-reduce:transition-none!"
)}
/>
</ArkAccordion.ItemIndicator>
</ArkAccordion.ItemTrigger>
);
};
export const AccordionContent = (
props: React.ComponentProps<typeof ArkAccordion.ItemContent>
) => {
const { className, children, ...rest } = props;
return (
<ArkAccordion.ItemContent
className={cn("overflow-hidden rounded-lg text-sm", className)}
data-slot="accordion-content"
{...rest}
>
<div
className={cn(
"pt-0 pb-4",
"group-data-[orientation=horizontal]/accordion:flex",
"group-data-[orientation=horizontal]/accordion:size-full",
"group-data-[orientation=horizontal]/accordion:items-center",
"group-data-[orientation=horizontal]/accordion:justify-center",
"group-data-[orientation=horizontal]/accordion:bg-muted",
"group-data-[orientation=horizontal]/accordion:p-5",
"group-data-[orientation=horizontal]/accordion:text-center"
)}
>
{children}
</div>
</ArkAccordion.ItemContent>
);
};Update the import paths to match your project setup.
Anatomy

Usage
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";<Accordion
className="w-full max-w-lg"
defaultValue={["item-1"]}
lazyMount={false}
unmountOnExit={false}
>
<AccordionItem value="item-1">
<AccordionTrigger>Product Information</AccordionTrigger>
<AccordionContent className="flex flex-col gap-4 text-muted-foreground">
<p>
Our flagship product combines cutting-edge technology with sleek
design. Built with premium materials, it offers unparalleled
performance and reliability.
</p>
<p>
Key features include advanced processing capabilities, and an
intuitive user interface designed for both beginners and experts.
</p>
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-2">
<AccordionTrigger>Shipping Details</AccordionTrigger>
<AccordionContent className="flex flex-col gap-4 text-muted-foreground">
<p>
We offer worldwide shipping through trusted courier partners. Standard
delivery takes 3-5 business days, while express shipping ensures
delivery within 1-2 business days.
</p>
<p>
All orders are carefully packaged and fully insured. Track your
shipment in real-time through our dedicated tracking portal.
</p>
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-3">
<AccordionTrigger>Return Policy</AccordionTrigger>
<AccordionContent className="flex flex-col gap-4 text-muted-foreground">
<p>
We stand behind our products with a comprehensive 30-day return
policy. If you're not completely satisfied, simply return the
item in its original condition.
</p>
<p>
Our hassle-free return process includes free return shipping and full
refunds processed within 48 hours of receiving the returned item.
</p>
</AccordionContent>
</AccordionItem>
</Accordion>Accessibility
| Key | Description |
|---|---|
Enter | Activate the focused control. |
Space | Activate the focused control. |
ArrowDown | Move to the next item when orientation is "vertical". |
ArrowUp | Move to the previous item when orientation is "vertical". |
ArrowRight | Move to the next item. |
ArrowLeft | Move to the previous item. |
Home | Move to the first item. |
End | Move to the last item. |
Demos
Card
Context
Controlled
Disabled
Horizontal
Item Context
Lazy Mount
Multiple
Non Collapsible
Root Provider
With Slider
API Reference
Accordion
div
AccordionItem
div
AccordionTrigger
button
AccordionContent
div
AccordionItemIndicator
div
AccordionRootProvider
div