Getting Started
Components
- Accordion
- Alert
- Alert Dialog
- Avatar
- Badge
- Button
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Circular Progress
- Collapsible
- Compare Slider
- Dialog
- Dropdown Menu
- Gauge
- Input
- Label
- Marquee
- Navigation Menu
- Number Field
- Pagination
- Popover
- Progress
- Radio Group
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Tooltip
Demos
The first marker is always visible. The trigger shows the rest.
3 markers out of range
LDL-C · 142 mg/dL
"use client"
import { ChevronsUpDownIcon } from "lucide-react"
import { Button } from "@workspace/ui/components/button"
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@workspace/ui/components/collapsible"
export function CollapsibleDemo() {
return (
<Collapsible className="flex w-full max-w-xs flex-col gap-2">
<div className="flex items-center justify-between gap-4 px-3">
<p className="text-sm font-medium">3 markers out of range</p>
<CollapsibleTrigger
render={<Button variant="ghost" size="icon-sm" aria-label="Toggle markers" />}
>
<ChevronsUpDownIcon />
</CollapsibleTrigger>
</div>
<div className="rounded-md border px-3 py-2 text-xs">LDL-C · 142 mg/dL</div>
<CollapsibleContent className="flex flex-col gap-2">
<div className="rounded-md border px-3 py-2 text-xs">HbA1c · 5.9 %</div>
<div className="rounded-md border px-3 py-2 text-xs">Vitamin D · 22 ng/mL</div>
</CollapsibleContent>
</Collapsible>
)
}
Usage
Use a collapsible for one block of secondary content, like extra rows in a list. For several sections in a stack, use an Accordion.
Import it from @workspace/ui/components/collapsible.
Anatomy
- Collapsible — Holds the open state.
- CollapsibleTrigger — The control that toggles the content.
- CollapsibleContent — The content that shows and hides.
Notes
- The component has no styles of its own. Style the trigger and content for the context.
- Pass a button through
renderon the trigger to reuse the Button styles. - An icon-only trigger needs an
aria-label.
Examples
Controlled
Hold the state with open and onOpenChange to change the trigger label.
Your ApoB is in the optimal range. LDL-C is slightly high.
"use client"
import * as React from "react"
import { Button } from "@workspace/ui/components/button"
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@workspace/ui/components/collapsible"
export function CollapsibleControlled() {
const [open, setOpen] = React.useState(false)
return (
<Collapsible
open={open}
onOpenChange={setOpen}
className="flex w-full max-w-xs flex-col gap-2"
>
<p className="text-xs text-muted-foreground">
Your ApoB is in the optimal range. LDL-C is slightly high.
</p>
<CollapsibleContent className="text-xs text-muted-foreground">
LDL-C measures the cholesterol carried by LDL particles. ApoB counts the
particles themselves, so the two can disagree.
</CollapsibleContent>
<CollapsibleTrigger render={<Button variant="link" size="sm" className="w-fit px-0" />}>
{open ? "Show less" : "Read more"}
</CollapsibleTrigger>
</Collapsible>
)
}
Props
These are the props you set most often. Unlisted props pass through to the underlying element.
Collapsible
| Prop | Type | Default | Description |
|---|---|---|---|
defaultOpen | boolean | false | Open on first render. |
open | boolean | — | Open state when controlled. |
onOpenChange | (open) => void | — | Called when the state changes. |
disabled | boolean | false | Stops the trigger from toggling. |
CollapsibleTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
render | ReactElement | — | Element to render instead of a button. |