Display
Accordion.
Stacked questions that open one panel at a time, with a rotating chevron and orange open state.
A small web for Minecraft servers. In-game computers serve pages, and the hub lists every site on the network.
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
const faqs = [
{
q: "What is Lantern?",
a: "A small web for Minecraft servers. In-game computers serve pages, and the hub lists every site on the network.",
},
{
q: "Do I need to open a port?",
a: "No. Your computer connects out to the hub, so it works on any server that allows HTTP.",
},
{
q: "Can turtles post to my site?",
a: "Yes. Any program can write to the guestbook or update a status page through the same API.",
},
];
export default function AccordionDemo() {
return (
<Accordion type="single" collapsible defaultValue="item-0" className="w-full max-w-lg">
{faqs.map((faq, i) => (
<AccordionItem key={faq.q} value={`item-${i}`}>
<AccordionTrigger>{faq.q}</AccordionTrigger>
<AccordionContent>{faq.a}</AccordionContent>
</AccordionItem>
))}
</Accordion>
);
}Installation#
With the CLI
$npx lanterncn add accordionThis also installs the Lantern theme and any Lantern UI components it depends on. The shadcn CLI works directly too: npx shadcn@latest add httptim/lantern-ui/accordion. See Installation if your project is not set up yet.
Manually
Install the dependencies
npm install radix-ui lucide-reactCopy the source into your project
components/ui/accordion.tsx"use client"; import * as React from "react"; import { ChevronDownIcon } from "lucide-react"; import { Accordion as AccordionPrimitive } from "radix-ui"; import { cn } from "@/lib/utils"; function Accordion({ ...props }: React.ComponentProps<typeof AccordionPrimitive.Root>) { return <AccordionPrimitive.Root data-slot="accordion" {...props} />; } function AccordionItem({ className, ...props }: React.ComponentProps<typeof AccordionPrimitive.Item>) { return <AccordionPrimitive.Item data-slot="accordion-item" className={cn("border-b last:border-b-0", 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 flex-1 cursor-pointer items-start justify-between gap-4 rounded-md py-4 text-left font-display text-base font-medium tracking-tight transition-colors outline-none hover:text-primary focus-visible:ring-2 focus-visible:ring-ring/25 disabled:pointer-events-none disabled:opacity-50 data-[state=open]:text-primary [&[data-state=open]>svg]:rotate-180", className, )} {...props} > {children} <ChevronDownIcon aria-hidden="true" className="pointer-events-none mt-0.5 size-4 shrink-0 text-muted-foreground transition-transform duration-200" /> </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-sm text-muted-foreground data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down" {...props} > <div className={cn("pt-0 pb-4 leading-relaxed", className)}>{children}</div> </AccordionPrimitive.Content> ); } export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };Update the import paths to match your project
The source imports
cnfrom@/lib/utils.
Usage#
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from "@/components/ui/accordion";<Accordion type="single" collapsible>
<AccordionItem value="a">
<AccordionTrigger>What is Lantern?</AccordionTrigger>
<AccordionContent>A small web for Minecraft servers.</AccordionContent>
</AccordionItem>
</Accordion>