{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "accordion", "title": "Accordion", "description": "Vertically stacked expandable and collapsible content sections for organizing dense information.", "dependencies": [ "@base-ui/react", "lucide-react" ], "files": [ { "path": "packages/ui/src/accordion.tsx", "content": "\"use client\";\n\nimport { Accordion as AccordionPrimitive } from \"@base-ui/react/accordion\";\nimport { ChevronDown } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype AccordionRootBaseProps = Omit<\n React.ComponentPropsWithoutRef,\n | \"className\"\n | \"render\"\n | \"variant\"\n | \"defaultValue\"\n | \"value\"\n | \"onValueChange\"\n | \"hiddenUntilFound\"\n | \"multiple\"\n | \"disabled\"\n | \"orientation\"\n | \"keepMounted\"\n>;\ntype AccordionItemBaseProps = Omit<\n React.ComponentPropsWithoutRef,\n \"className\" | \"render\" | \"variant\" | \"onOpenChange\" | \"disabled\"\n>;\ntype AccordionHeaderBaseProps = Omit<\n React.ComponentPropsWithoutRef,\n \"className\" | \"render\"\n>;\ntype AccordionTriggerBaseProps = Omit<\n React.ComponentPropsWithoutRef,\n \"className\" | \"render\" | \"chevronIcon\" | \"variant\"\n>;\ntype AccordionPanelBaseProps = Omit<\n React.ComponentPropsWithoutRef,\n \"className\" | \"render\" | \"variant\" | \"hiddenUntilFound\" | \"keepMounted\"\n>;\n\nexport type AccordionVariant = \"box\" | \"underline\" | \"ghost\" | \"table\";\ntype RenderProp =\n | React.ReactElement\n | ((props: any, state: any) => React.ReactElement);\ntype ClassNameProp = string | ((state: any) => string);\n\nexport type AccordionProps = AccordionRootBaseProps & {\n /** The visual style variant of the accordion @default \"underline\" */\n variant?: AccordionVariant;\n /** The default value of the accordion */\n defaultValue?: string[];\n /** The controlled value of the accordion */\n value?: string[];\n /** Callback when value changes */\n onValueChange?: (value: string[]) => void;\n /** Whether the accordion items should be hidden until found @default false */\n hiddenUntilFound?: boolean;\n /** Whether multiple items can be opened at once @default true */\n multiple?: boolean;\n /** Whether the accordion is disabled @default false */\n disabled?: boolean;\n /** The orientation of the accordion @default 'vertical' */\n orientation?: \"horizontal\" | \"vertical\";\n /** Whether to keep the content mounted when closed @default false */\n keepMounted?: boolean;\n /** Optional class name or function that returns a class name */\n className?: ClassNameProp;\n /** Optional render function */\n render?: RenderProp;\n};\n\nexport type AccordionItemProps = AccordionItemBaseProps & {\n /** The visual style variant of the accordion item. Inherited from parent Accordion if not specified */\n variant?: AccordionVariant;\n /** Callback when item open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Whether the item is disabled @default false */\n disabled?: boolean;\n className?: ClassNameProp;\n render?: RenderProp;\n};\n\nexport type AccordionHeaderProps = AccordionHeaderBaseProps & {\n className?: ClassNameProp;\n render?: RenderProp;\n};\n\nexport type AccordionTriggerProps = AccordionTriggerBaseProps & {\n /** Icon to replace the default chevron icon on the right side. */\n chevronIcon?: React.ReactNode;\n /** The visual style variant of the trigger. Inherited from parent AccordionItem if not specified */\n variant?: AccordionVariant;\n className?: ClassNameProp;\n render?: RenderProp;\n};\n\nexport type AccordionPanelProps = AccordionPanelBaseProps & {\n /** The visual style variant of the panel. Inherited from parent AccordionItem if not specified */\n variant?: AccordionVariant;\n /** Whether the panel should be hidden until found @default false */\n hiddenUntilFound?: boolean;\n /** Whether to keep the panel mounted when closed @default false */\n keepMounted?: boolean;\n className?: ClassNameProp;\n render?: RenderProp;\n};\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nconst AccordionVariantContext =\n React.createContext(\"underline\");\nconst AccordionLeadingIconContext = React.createContext(false);\n\n// ---------------------------------------------------------------------------\n// Accordion (root)\n// ---------------------------------------------------------------------------\n\nconst Accordion = ({\n className: classNameProp,\n variant = \"underline\",\n defaultValue,\n value,\n onValueChange,\n hiddenUntilFound,\n multiple,\n disabled,\n orientation,\n ref,\n ...props\n}: AccordionProps &\n React.RefAttributes>) => {\n const baseClasses = cn(\"flex w-full flex-col justify-center\");\n\n return (\n \n \n \n \n \n );\n};\n\nAccordion.displayName = \"Accordion\";\n\n// ---------------------------------------------------------------------------\n// AccordionItem\n// ---------------------------------------------------------------------------\n\nconst AccordionItem = ({\n className: classNameProp,\n variant: variantProp,\n ref,\n ...props\n}: AccordionItemProps &\n React.RefAttributes>) => {\n const contextVariant = React.useContext(AccordionVariantContext);\n const variant = variantProp ?? contextVariant;\n\n const baseClasses = cn(\n \"group\",\n variant === \"box\" && [\"mb-2 rounded-lg border border-border\"],\n variant === \"table\" && [\n \"border border-border\",\n \"[&:not(:first-child)]:-mt-[1px]\",\n \"first:rounded-t-lg last:rounded-b-lg\",\n ],\n variant === \"underline\" && [\"border-border border-b\", \"last:border-b-0\"],\n variant === \"ghost\" && \"border-none\"\n );\n\n return (\n \n );\n};\n\nAccordionItem.displayName = \"AccordionItem\";\n\n// ---------------------------------------------------------------------------\n// AccordionHeader\n// ---------------------------------------------------------------------------\n\nconst AccordionHeader = ({\n className,\n ref,\n ...props\n}: AccordionHeaderProps &\n React.RefAttributes<\n React.ComponentRef\n >) => (\n \n);\n\nAccordionHeader.displayName = \"AccordionHeader\";\n\n// ---------------------------------------------------------------------------\n// AccordionTrigger\n// ---------------------------------------------------------------------------\n\nconst AccordionTrigger = ({\n className: classNameProp,\n children,\n variant: variantProp,\n chevronIcon,\n ref,\n ...props\n}: AccordionTriggerProps &\n React.RefAttributes<\n React.ComponentRef\n >) => {\n const contextVariant = React.useContext(AccordionVariantContext);\n const variant = variantProp ?? contextVariant;\n\n const baseClasses = cn(\n \"group flex w-full cursor-pointer items-center justify-between gap-4 py-2.5 text-left font-semibold text-sm\",\n \"focus:ring-0 focus:ring-offset-0\",\n \"focus-visible:outline-2 focus-visible:outline-ring/50 focus-visible:outline-offset-2\",\n variant === \"box\" && [\"px-3\", \"rounded-lg\"],\n variant === \"table\" && \"px-3\"\n );\n\n return (\n \n {children}\n {chevronIcon ? (\n \n {chevronIcon}\n \n ) : (\n \n )}\n \n );\n};\n\nAccordionTrigger.displayName = \"AccordionTrigger\";\n\n// ---------------------------------------------------------------------------\n// AccordionPanel\n// ---------------------------------------------------------------------------\n\nconst AccordionPanel = ({\n className: classNameProp,\n children,\n variant: variantProp,\n ref,\n ...props\n}: AccordionPanelProps &\n React.RefAttributes>) => {\n const contextVariant = React.useContext(AccordionVariantContext);\n const variant = variantProp ?? contextVariant;\n\n const baseClasses = cn(\n \"overflow-hidden text-muted-foreground text-sm\",\n // CSS transition on height — smoothly cancellable mid-animation.\n // Reduced motion is handled globally by base.css.\n \"h-[var(--accordion-panel-height)] transition-[height] duration-200 ease-out\",\n // Enter: start from 0 height\n \"data-[starting-style]:h-0\",\n // Exit: collapse to 0 height\n \"data-[ending-style]:h-0\"\n );\n\n const innerClasses = cn(\n \"pb-3\",\n (variant === \"box\" || variant === \"table\") && \"px-3\"\n );\n\n return (\n \n
{children}
\n \n );\n};\n\nAccordionPanel.displayName = \"AccordionPanel\";\n\n// ---------------------------------------------------------------------------\n// Exports\n// ---------------------------------------------------------------------------\n\nexport {\n Accordion,\n AccordionHeader,\n AccordionItem,\n AccordionLeadingIconContext,\n AccordionPanel,\n AccordionTrigger,\n AccordionVariantContext,\n};\n", "type": "registry:ui" } ], "type": "registry:ui" }