Docs
Accordion
Accordion
A vertically stacked set of interactive headings that each reveal a section of content.
Loading...
Installation
Install the following dependencies:
pnpm add @radix-ui/react-accordion
Copy and paste the following code into your project.
"use client";
import * as React from "react";
import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { cva } from "cva";
import { ChevronDown } from "lucide-react";
import { autoRef, cn } from "@/lib/utils";
/* -------------------------------------------------------------------------- */
/* Variants */
/* -------------------------------------------------------------------------- */
export const accordionVariants = {
item: cva({
base: "border-b",
}),
trigger: cva({
base: "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
}),
content: cva({
base: "overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
}),
};
/* -------------------------------------------------------------------------- */
/* Components */
/* -------------------------------------------------------------------------- */
/* ---------------------------------- Root ---------------------------------- */
export const Accordion = AccordionPrimitive.Root;
/* ---------------------------------- Item ---------------------------------- */
export type AccordionItemProps = React.ComponentPropsWithRef<
typeof AccordionPrimitive.Item
>;
export const AccordionItem = autoRef(
({ className, ...props }: AccordionItemProps) => {
return (
<AccordionPrimitive.Item
className={cn(accordionVariants.item(), className)}
{...props}
/>
);
},
);
/* --------------------------------- Trigger -------------------------------- */
export type AccordionTriggerProps = React.ComponentPropsWithoutRef<
typeof AccordionPrimitive.Trigger
>;
export const AccordionTrigger = autoRef(
({ className, children, ...props }: AccordionTriggerProps) => {
return (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
className={cn(accordionVariants.trigger(), className)}
{...props}
>
{children}
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
);
},
);
/* --------------------------------- Content -------------------------------- */
export type AccordionContentProps = React.ComponentPropsWithoutRef<
typeof AccordionPrimitive.Content
>;
export const AccordionContent = autoRef(
({ className, children, ...props }: AccordionContentProps) => {
return (
<AccordionPrimitive.Content
className={cn(accordionVariants.content())}
{...props}
>
<div className={cn("pb-4 pt-0", className)}>{children}</div>
</AccordionPrimitive.Content>
);
},
);
Update the import paths to match your project setup.
Update tailwind.config.js
Add the following animations to your tailwind.config.js
file:
tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
theme: {
extend: {
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
},
},
};