Shipping address
100 Market St, San Francisco
Items
2x Studio Headphones
"use client";
import { ChevronsUpDown } from "lucide-react";import * as React from "react";import { Button } from "@/components/ui/button";import { Collapsible, CollapsibleContent, CollapsibleTrigger,} from "@/components/ui/collapsible";import { Surface } from "@/components/ui/surface";
export function CollapsibleDemo() { const [isOpen, setIsOpen] = React.useState(false);
return ( <Collapsible open={isOpen} onOpenChange={setIsOpen} className="flex w-[350px] flex-col gap-2" > <div className="flex items-center justify-between gap-4 px-4"> <h4 className="font-semibold text-sm">Order #4189</h4> <CollapsibleTrigger render={<Button variant="ghost" size="icon" className="size-8" />} > <ChevronsUpDown /> <span className="sr-only">Toggle details</span> </CollapsibleTrigger> </div> <Surface className="flex items-center justify-between rounded-2xl p-4 text-sm"> <span className="text-muted-foreground">Status</span> <span className="font-medium">Shipped</span> </Surface> <CollapsibleContent className="flex flex-col gap-2"> <Surface className="rounded-2xl p-4 text-sm"> <p className="font-medium">Shipping address</p> <p className="text-muted-foreground">100 Market St, San Francisco</p> </Surface> <Surface className="rounded-2xl p-4 text-sm"> <p className="font-medium">Items</p> <p className="text-muted-foreground">2x Studio Headphones</p> </Surface> </CollapsibleContent> </Collapsible> );}pnpm dlx shadcn@latest add @herocn/collapsibleimport { Collapsible, CollapsibleContent, CollapsibleTrigger,} from "@/components/ui/collapsible"<Collapsible> <CollapsibleTrigger>Can I use this in my project?</CollapsibleTrigger> <CollapsibleContent> Yes. Free to use for personal and commercial projects. No attribution required. </CollapsibleContent></Collapsible>Use the following composition to build a Collapsible:
Collapsible├── CollapsibleTrigger└── CollapsibleContentUse the open and onOpenChange props to control the state.
import * as React from "react"
export function Example() { const [open, setOpen] = React.useState(false)
return ( <Collapsible open={open} onOpenChange={setOpen}> <CollapsibleTrigger>Toggle</CollapsibleTrigger> <CollapsibleContent>Content</CollapsibleContent> </Collapsible> )}import { ChevronDownIcon } from "lucide-react";import { Button } from "@/components/ui/button";import { Card, CardContent } from "@/components/ui/card";import { Collapsible, CollapsibleContent, CollapsibleTrigger,} from "@/components/ui/collapsible";
export function CollapsibleBasic() { return ( <Card className="mx-auto w-full max-w-sm"> <CardContent> <Collapsible className="rounded-md data-open:bg-muted"> <CollapsibleTrigger render={<Button variant="ghost" className="w-full" />} > Product details <ChevronDownIcon className="ml-auto group-data-panel-open/button:rotate-180" /> </CollapsibleTrigger> <CollapsibleContent className="flex flex-col items-start gap-2 text-sm"> This panel can be expanded or collapsed to reveal additional content. <Button size="sm">Learn More</Button> </CollapsibleContent> </Collapsible> </CardContent> </Card> );}Use a trigger button to reveal additional settings.
"use client";
import { MaximizeIcon, MinimizeIcon } from "lucide-react";import * as React from "react";import { Button } from "@/components/ui/button";import { Card, CardContent, CardDescription, CardHeader, CardTitle,} from "@/components/ui/card";import { Collapsible, CollapsibleContent, CollapsibleTrigger,} from "@/components/ui/collapsible";import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";import { Input } from "@/components/ui/input";
export function CollapsibleSettings() { const [isOpen, setIsOpen] = React.useState(false);
return ( <Card className="mx-auto w-full max-w-xs" size="sm"> <CardHeader> <CardTitle>Radius</CardTitle> <CardDescription>Set the corner radius of the element.</CardDescription> </CardHeader> <CardContent> <Collapsible open={isOpen} onOpenChange={setIsOpen} className="flex items-start gap-2" > <FieldGroup className="grid w-full grid-cols-2 gap-2"> <Field> <FieldLabel htmlFor="radius-x" className="sr-only"> Radius X </FieldLabel> <Input variant="secondary" id="radius" placeholder="0" defaultValue={0} /> </Field> <Field> <FieldLabel htmlFor="radius-y" className="sr-only"> Radius Y </FieldLabel> <Input variant="secondary" id="radius" placeholder="0" defaultValue={0} /> </Field> <CollapsibleContent className="col-span-full grid grid-cols-subgrid gap-2"> <Field> <FieldLabel htmlFor="radius-x" className="sr-only"> Radius X </FieldLabel> <Input variant="secondary" id="radius" placeholder="0" defaultValue={0} /> </Field> <Field> <FieldLabel htmlFor="radius-y" className="sr-only"> Radius Y </FieldLabel> <Input variant="secondary" id="radius" placeholder="0" defaultValue={0} /> </Field> </CollapsibleContent> </FieldGroup> <CollapsibleTrigger render={<Button variant="outline" size="icon" />}> {isOpen ? <MinimizeIcon /> : <MaximizeIcon />} </CollapsibleTrigger> </Collapsible> </CardContent> </Card> );}Use nested collapsibles to build a file tree.
import { ChevronRightIcon, FileIcon, FolderIcon } from "lucide-react";import { Button } from "@/components/ui/button";import { Card, CardContent, CardHeader } from "@/components/ui/card";import { Collapsible, CollapsibleContent, CollapsibleTrigger,} from "@/components/ui/collapsible";import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
type FileTreeItem = { name: string } | { name: string; items: FileTreeItem[] };
export function CollapsibleFileTree() { const fileTree: FileTreeItem[] = [ { name: "components", items: [ { name: "ui", items: [ { name: "button.tsx" }, { name: "card.tsx" }, { name: "dialog.tsx" }, { name: "input.tsx" }, { name: "select.tsx" }, { name: "table.tsx" }, ], }, { name: "login-form.tsx" }, { name: "register-form.tsx" }, ], }, { name: "lib", items: [{ name: "utils.ts" }, { name: "cn.ts" }, { name: "api.ts" }], }, { name: "hooks", items: [ { name: "use-media-query.ts" }, { name: "use-debounce.ts" }, { name: "use-local-storage.ts" }, ], }, { name: "types", items: [{ name: "index.d.ts" }, { name: "api.d.ts" }], }, { name: "public", items: [ { name: "favicon.ico" }, { name: "logo.svg" }, { name: "images" }, ], }, { name: "app.tsx" }, { name: "layout.tsx" }, { name: "globals.css" }, { name: "package.json" }, { name: "tsconfig.json" }, { name: "README.md" }, { name: ".gitignore" }, ];
const renderItem = (fileItem: FileTreeItem): React.ReactNode => { if ("items" in fileItem) { return ( <Collapsible key={fileItem.name}> <CollapsibleTrigger render={ <Button variant="ghost" size="sm" className="group w-full justify-start transition-none hover:bg-accent hover:text-accent-foreground" /> } > <ChevronRightIcon className="group-data-panel-open:rotate-90" /> <FolderIcon /> {fileItem.name} </CollapsibleTrigger> <CollapsibleContent className="mt-1 ml-5 style-lyra:ml-4"> <div className="flex flex-col gap-1"> {fileItem.items.map((child) => renderItem(child))} </div> </CollapsibleContent> </Collapsible> ); }
return ( <Button key={fileItem.name} variant="ghost" size="sm" className="w-full justify-start gap-2 text-foreground" > <FileIcon /> <span>{fileItem.name}</span> </Button> ); };
return ( <Card className="mx-auto w-full max-w-[16rem] gap-2" size="sm"> <CardHeader> <Tabs defaultValue="explorer"> <TabsList className="w-full"> <TabsTrigger value="explorer">Explorer</TabsTrigger> <TabsTrigger value="settings">Outline</TabsTrigger> </TabsList> </Tabs> </CardHeader> <CardContent> <div className="flex max-h-107 flex-col gap-1 overflow-auto px-1"> {fileTree.map((item) => renderItem(item))} </div> </CardContent> </Card> );}"use client";
import { ChevronDownIcon } from "lucide-react";
import { type Translations, useTranslation,} from "@/components/language-selector";import { Button } from "@/components/ui/button";import { Card, CardContent } from "@/components/ui/card";import { Collapsible, CollapsibleContent, CollapsibleTrigger,} from "@/components/ui/collapsible";
const translations: Translations = { en: { dir: "ltr", values: { trigger: "Frequently asked questions", answer: "Yes. Free to use for personal and commercial projects. No attribution required.", learnMore: "Learn More", }, }, ar: { dir: "rtl", values: { trigger: "الأسئلة الشائعة", answer: "نعم. مجاني للاستخدام في المشاريع الشخصية والتجارية. لا يلزم ذكر المصدر.", learnMore: "اعرف المزيد", }, }, he: { dir: "rtl", values: { trigger: "שאלות נפוצות", answer: "כן. חינמי לשימוש בפרויקטים אישיים ומסחריים. אין צורך בייחוס.", learnMore: "למד עוד", }, },};
export function CollapsibleRtl() { const { dir, language, t } = useTranslation(translations, "ar");
return ( <Card className="mx-auto w-full max-w-sm" lang={language} dir={dir}> <CardContent> <Collapsible className="rounded-md data-open:bg-muted"> <CollapsibleTrigger render={<Button variant="ghost" className="w-full" />} > {t.trigger} <ChevronDownIcon className="ms-auto group-data-panel-open/button:rotate-180" /> </CollapsibleTrigger> <CollapsibleContent className="flex flex-col items-start gap-2 text-sm"> {t.answer} <Button size="sm">{t.learnMore}</Button> </CollapsibleContent> </Collapsible> </CardContent> </Card> );}See the Base UI documentation for more information.