A vertically stacked set of interactive headings that each reveal a section of content with a neobrutalism design style.
1"use client";
2
3import * as AccordionPrimitive from "@radix-ui/react-accordion";
4import { ChevronDown } from "lucide-react";
5import * as React from "react";
6
7// Import utility function for className merging
8const cn = (...classes: any[]) => classes.filter(Boolean).join(" ");
9
10const Accordion = AccordionPrimitive.Root;
11
12const AccordionItem = React.forwardRef<
13 React.ElementRef<typeof AccordionPrimitive.Item>,
14 React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
15>(({ className, ...props }, ref) => (
16 <AccordionPrimitive.Item
17 ref={ref}
18 className={cn(
19 "rounded-base overflow-x-hidden border-2 border-b border-border shadow-shadow",
20 className
21 )}
22 {...props}
23 />
24));
25AccordionItem.displayName = "AccordionItem";
26
27const AccordionTrigger = React.forwardRef<
28 React.ElementRef<typeof AccordionPrimitive.Trigger>,
29 React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
30>(({ className, children, ...props }, ref) => (
31 <AccordionPrimitive.Header className="flex">
32 <AccordionPrimitive.Trigger
33 ref={ref}
34 className={cn(
35 "flex flex-1 items-center justify-between text-mtext border-border bg-main p-4 font-heading transition-all [&[data-state=open]>svg]:rotate-180 [&[data-state=open]]:rounded-b-none [&[data-state=open]]:border-b-2",
36 className
37 )}
38 {...props}
39 >
40 {children}
41 <ChevronDown className="h-5 w-5 shrink-0 transition-transform duration-200" />
42 </AccordionPrimitive.Trigger>
43 </AccordionPrimitive.Header>
44));
45AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
46
47const AccordionContent = React.forwardRef<
48 React.ElementRef<typeof AccordionPrimitive.Content>,
49 React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
50>(({ className, children, ...props }, ref) => (
51 <AccordionPrimitive.Content
52 ref={ref}
53 className="overflow-hidden rounded-b-base bg-bw text-sm font-base transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
54 {...props}
55 >
56 <div className={cn("p-4", className)}>{children}</div>
57 </AccordionPrimitive.Content>
58));
59AccordionContent.displayName = AccordionPrimitive.Content.displayName;
60
61export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };
62