Accordion
Grouped-inset disclosure list with rotating chevrons.
SwiftUI: DisclosureGroup in a List
Your battery's maximum capacity is 91%. Peak performance capability is normal.
Installation
npx shadcn@latest add https://cupertino-ui.baltoon.jp/r/accordion.jsonRequires the theme tokens — see Installation if this is your first component.
Source
"use client";
import * as React from "react";
import { Accordion as AccordionPrimitive } from "radix-ui";
import { ChevronDownIcon } from "lucide-react";
import { cn } from "@/lib/utils";
/**
* Accordion rendered as an iOS grouped-inset list: rounded section,
* hairline separators, and a chevron that rotates open.
*/
function Accordion({
className,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
return (
<AccordionPrimitive.Root
data-slot="accordion"
className={cn(
"w-full overflow-hidden rounded-[var(--radius-card)] bg-grouped-secondary",
className
)}
{...props}
/>
);
}
function AccordionItem({
className,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
return (
<AccordionPrimitive.Item
data-slot="accordion-item"
className={cn(
"not-first:shadow-[0_-0.5px_0_0_var(--separator)]",
className
)}
{...props}
/>
);
}
function AccordionTrigger({
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
return (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
data-slot="accordion-trigger"
className={cn(
"flex min-h-11 flex-1 cursor-default select-none items-center justify-between gap-3 px-4 py-2.5 text-left text-body text-label outline-none transition-colors focus-visible:bg-fill-quaternary active:bg-fill-tertiary [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}
>
{children}
<ChevronDownIcon
className="size-[17px] shrink-0 text-tertiary-label transition-transform duration-200"
strokeWidth={2.5}
/>
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
);
}
function AccordionContent({
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Content>) {
return (
<AccordionPrimitive.Content
data-slot="accordion-content"
className="overflow-hidden text-subheadline text-secondary-label data-[state=open]:animate-accordion-down data-[state=closed]:animate-accordion-up"
{...props}
>
<div className={cn("px-4 pb-3 pt-0.5", className)}>{children}</div>
</AccordionPrimitive.Content>
);
}
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };