kanpeki
uiaccordionsource: ok · refreshed
Accordion
npx shadcn add "https://kanpeki.vercel.app/r/accordion.json"free
Interaction
accordion
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Dependencies
Bundle weight · lighticonslucide-react
Registry dependencies
@kanpeki/collapsible
Files4 · source cached 10/8/2026, 4:09:06 AM
src/registry/ui/accordion/index.ts
export * from "./accordion";
export * as Accordion from "./namespace";
src/registry/ui/accordion/accordion.tsx
"use client";
import { ChevronDownIcon } from "lucide-react";
import {
Button,
composeRenderProps,
Disclosure,
DisclosureGroup,
DisclosurePanel,
} from "react-aria-components";
import { AccordionStyles } from "./styles";
export interface AccordionRootProps
extends React.ComponentProps<typeof DisclosureGroup> {}
export function AccordionRoot(props: AccordionRootProps) {
return <DisclosureGroup data-slot="accordion-root" {...props} />;
}
export interface AccordionItemProps
extends React.ComponentProps<typeof Disclosure> {}
export function AccordionItem({ className, ...props }: AccordionItemProps) {
return (
<Disclosure
className={composeRenderProps(className, (className) =>
AccordionStyles.Item({ className })
)}
data-slot="accordion-item"
{...props}
/>
);
}
export interface AccordionTriggerProps
extends Omit<React.ComponentProps<typeof Button>, "slot"> {}
export function AccordionTrigger({
className,
children,
...props
}: AccordionTriggerProps) {
return (
<Button
className={composeRenderProps(className, (className) =>
AccordionStyles.Trigger({ className })
)}
data-slot="accordion-trigger"
slot="trigger"
{...props}
>
{composeRenderProps(children, (children) => (
<>
{children}
<ChevronDownIcon className={AccordionStyles.Icon()} />
</>
))}
</Button>
);
}
export interface AccordionContentProps
extends React.ComponentProps<typeof DisclosurePanel> {}
export function AccordionContent({
className,
children,
...props
}: AccordionContentProps) {
return (
<DisclosurePanel
className={composeRenderProps(className, (className) =>
AccordionStyles.Content({ className })
)}
data-slot="accordion-content"
{...props}
>
<div>{children}</div>
</DisclosurePanel>
);
}
src/registry/ui/accordion/styles.ts
import { compose, cva } from "~/registry/lib/cva";
import { CollapsibleStyles } from "~/registry/ui/collapsible";
export const AccordionStyles = {
Content: compose(
CollapsibleStyles.Content,
cva({
base: ["*:pb-4"],
})
),
Icon: cva({
base: [
"pointer-events-none size-4 shrink-0 translate-y-0.5 text-muted-foreground transition-transform duration-200 group-expanded:rotate-180",
],
}),
Item: cva({
base: ["group border-b last:border-b-0"],
}),
Trigger: cva({
base: [
"flex w-full flex-1 items-start justify-between gap-4 rounded-md py-4 text-left font-medium text-sm outline-none transition-all",
"hover:underline",
"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
"disabled:pointer-events-none disabled:opacity-50",
],
}),
};
src/registry/ui/accordion/namespace.ts
export {
AccordionContent as Content,
AccordionItem as Item,
AccordionRoot as Root,
AccordionTrigger as Trigger,
} from "./accordion";