collapsible
A collapsed height clips the panel instead of hiding it.
The first lines stay on the page, and the rest slides in behind them when the trigger is pressed.
A Collapsible is Accordion’s row without the accordion around it. It wears the same
three variants, the same three sizes and the same slot names on purpose, so the two look
like siblings on a page and a ui override written for one reads on the other.
<Collapsible label="What is 75NeoUI?">One set of styles, shipped for React and Vue.</Collapsible>
<Collapsible label="What is 75NeoUI?">
One set of styles, shipped for React and Vue.
</Collapsible>
What is different is that nothing coordinates it. There is no set of rows taking turns,
so there is no value to identify a row by and no multiple to allow a second one open.
Reach for Accordion when the rows belong together; reach for this when one panel stands
on its own.
The content
The panel holds whatever the framework calls children, rather than a string prop. A
collapsible usually holds markup, and a prop would only get in the way. The trigger is
the other way round: label is a string, with a label slot in Vue and renderLabel in
React for anything richer.
Open and closed
Open is not a recipe variant. Ark writes data-state on the trigger and the panel, and
the recipe styles itself off that, so one resolved class string covers both states.
React takes open with onOpenChange, or defaultOpen to leave the state alone. Vue
takes v-model:open, with defaultOpen as the uncontrolled counterpart.
const [open, setOpen] = useState(false);
<Collapsible label="Controlled" open={open} onOpenChange={(details) => setOpen(details.open)}>
The button that opens this one lives somewhere else.
</Collapsible>;
<script setup lang="ts">
const open = ref(false);
</script>
<template>
<Collapsible v-model:open="open" label="Controlled">
The button that opens this one lives somewhere else.
</Collapsible>
</template>
A show more
collapsedHeight leaves the panel clipped rather than hidden, so the first lines stay on
the page and the rest slides in behind them. It takes a CSS length or a number of pixels.
<Collapsible label="Show more" collapsedHeight="3rem">
<p>The first lines are readable before anyone opens anything.</p>
<p>The rest arrives when they do.</p>
</Collapsible>
<Collapsible label="Show more" collapsed-height="3rem">
<p>The first lines are readable before anyone opens anything.</p>
<p>The rest arrives when they do.</p>
</Collapsible>
The animation
The panel measures itself, and the content slot hands both of Ark’s measurements to
keyframes shared with Accordion. --height is the panel’s natural size and
--collapsed-height is whatever collapsedHeight asked it to shrink to, defaulting to
nothing. That default is why the same keyframes serve Accordion, which always closes all
the way shut.
unmountOnExit takes the panel out of the DOM once it has finished closing, and
lazyMount keeps it out until it is opened the first time. Both are off by default,
because a panel that stays mounted is the one that keeps its scroll position and its
form state.
Slots
The same word names the recipe slot, the data-slot attribute and the key in ui.
- base
- trigger
- leadingIcon
- label
- trailingIcon
- content
- body
Variants
Read off the recipe, so these are the values that actually resolve. A Theme layer can change which one is the default; it cannot add a value.
- variant
- outlinesoftghost
- size
- smmdlg
Props
Taken by both adapters, read out of the component module. The same names and the same types work in React and Vue.
- ui
CollapsibleUI
Per-slot class overrides.
- variant
"outline" | "soft" | "ghost"
Defaults to
"outline"- size
"sm" | "md" | "lg"
Defaults to
"md"- label
string
Trigger text.
- icon
Component
Icon shown before the label.
- trailingIcon
Component
Replaces the chevron.
- disabled
boolean
- collapsedHeight
string | number
How much of the panel stays visible while closed, as a CSS length or a number of pixels. Turns the component into a "show more": the panel is clipped rather than hidden, and the content underneath keeps its place in the tab order.
- unmountOnExit
boolean
Remove the panel from the DOM once it has finished closing.
- lazyMount
boolean
Keep the panel out of the DOM until it is opened for the first time.
Vue only
Binds v-model:open.
- class
unknown
- defaultOpen
boolean
- ids
{ root?: string; content?: string; trigger?: string }
- #default
- The panel's content.
- #label
- Replaces the trigger's contents. Falls back to `label`.
- #trailingIcon
- Replaces the chevron. Falls back to `trailingIcon`.