uniquel
componentaccordion-chevronsource: ok · hit
Accordion Chevron
Minimal accordion with a subtly animated chevron for compact FAQs and supporting details.
npx shadcn add "https://uniquel.io/r/accordion-chevron.json"free
Visual style
minimal
Interaction
accordion
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Dependencies
Bundle weight · lighticonslucide-react
Files1 · source cached 10/15/2026, 4:15:14 AM
components/content/AccordionChevron.tsx
'use client';
import { ChevronDown } from 'lucide-react';
import { useId, useState } from 'react';
type AccordionChevronItem = {
title: string;
content: string;
};
type AccordionChevronProps = {
items?: AccordionChevronItem[];
defaultOpenIndex?: number | null;
className?: string;
};
const DEFAULT_ITEMS: AccordionChevronItem[] = [
{
title: 'How does it work?',
content: 'Use the accordion to keep related details close without making the page feel crowded.',
},
{
title: 'Can I change the content?',
content: 'Pass your own titles and descriptions through the items prop.',
},
{
title: 'Does it work on mobile?',
content: 'Yes. Each trigger has a comfortable touch target and supports keyboard navigation.',
},
];
export default function AccordionChevron({
items = DEFAULT_ITEMS,
defaultOpenIndex = 0,
className = '',
}: AccordionChevronProps) {
const id = useId();
const [openIndex, setOpenIndex] = useState(defaultOpenIndex);
return (
<div className={['w-full max-w-xl divide-y divide-[color:var(--color-border,#e5e7eb)] border-y border-[color:var(--color-border,#e5e7eb)]', className].filter(Boolean).join(' ')}>
{items.map((item, index) => {
const open = openIndex === index;
const triggerId = `${id}-trigger-${index}`;
const panelId = `${id}-panel-${index}`;
return (
<div key={item.title}>
<button
id={triggerId}
type='button'
aria-expanded={open}
aria-controls={panelId}
onClick={() => setOpenIndex(open ? null : index)}
className='group flex w-full items-center justify-between gap-6 py-4 text-left text-sm font-medium text-[color:var(--color-foreground,#111827)]'
>
{item.title}
<ChevronDown
aria-hidden='true'
className={['h-4 w-4 shrink-0 text-[color:var(--color-muted-foreground,#9ca3af)] transition-transform duration-400 ease-out', open ? 'rotate-180' : 'group-hover:translate-y-0.5'].join(' ')}
/>
</button>
<div
id={panelId}
role='region'
aria-labelledby={triggerId}
className={['grid transition-[grid-template-rows,opacity] duration-200 ease-out', open ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'].join(' ')}
>
<div className='overflow-hidden'>
<p className='pb-4 text-sm leading-6 text-[color:var(--color-muted-foreground,#6b7280)]'>{item.content}</p>
</div>
</div>
</div>
);
})}
</div>
);
}