Back to catalog
Component detail entry
Data Display
@vean/ui
SCollapsible

Collapsible

Collapsible belongs to the Data Display category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Collapsible

Overview

An interactive component that expands/collapses a panel. SCollapsible wraps the Aria CollapsibleRoot with the collapsibleVariants style recipe (3 slots: root/trigger/content; 6 sizes), and the Aria CollapsibleTrigger/CollapsibleContent primitives provide the toggle button and the animated panel.

Use it for a single “expand to reveal” section, FAQ items, or inline collapsible filters. Prefer accordion when you need multiple coordinated sections (single/multiple open), and dialog/popover for floating surfaces.

Usage

Features

  • 🧩 Aria/styled split — SCollapsible injects collapsibleVariants; the Aria primitives own state, a11y and animation
  • 🎛️ Controlled / uncontrolled — v-model:open or defaultOpen
  • 📜 Animated panel — CollapsibleContent measures real dimensions and animates open/closed via data-state
  • 🗑️ unmountOnHide — removes closed content from the DOM, or keeps it mounted (hidden)
  • 🧲 forceMount — keep content present even when closed (for measurement/custom animation)
  • 🔗 Accessible wiring — the trigger exposes aria-expanded/aria-controls; root/content reflect data-state/data-disabled
  • 🔧 Polymorphic — as/asChild on root, trigger and content

Component family

  • SCollapsible (styled) — the root wrapper; collapsibleVariants recipe and provideCollapsibleUi
  • CollapsibleRoot (Aria) — the state owner; useControllableState + provideCollapsibleRootContext
  • CollapsibleTrigger (Aria) — the Button-based trigger; aria-expanded/aria-controls/data-state
  • CollapsibleContent (Aria) — the animated panel; presence-based dimension measurement and data-state

Demos

Basic

@soybeanjs starred 3 repositories
vean-aria

API

Aria Layer

4

Collapsible

8 Props1 Emits
Props
PropTypeDefaultDescription
size
ThemeSize
—
Visual size of the component.
ui
Partial<CollapsibleUi>
—
Per-slot class overrides for the component.
defaultOpen
boolean
—
The open state of the collapsible when it is initially rendered. Use when you do not need to control its open state.
open
boolean
—
The controlled open state of the collapsible. Can be bound with `v-model`.
disabled
boolean
—
When `true`, prevents the user from interacting with the collapsible.
unmountOnHide
boolean
—
When `true`, the element will be unmounted on closed state.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
update:open
boolean
Event handler called when the open state of the collapsible changes.

CollapsibleContent

3 Props
Props
PropTypeDefaultDescription
forceMount
boolean
—
Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

CollapsibleRoot

6 Props1 Emits
Props
PropTypeDefaultDescription
defaultOpen
boolean
—
The open state of the collapsible when it is initially rendered. Use when you do not need to control its open state.
open
boolean
—
The controlled open state of the collapsible. Can be bound with `v-model`.
disabled
boolean
—
When `true`, prevents the user from interacting with the collapsible.
unmountOnHide
boolean
—
When `true`, the element will be unmounted on closed state.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
update:open
boolean
Event handler called when the open state of the collapsible changes.

CollapsibleTrigger

5 Props
Props
PropTypeDefaultDescription
disabledCollapsible
boolean
—
When `true`, prevents the user from toggling the collapsible.
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

Notes

Architecture and benchmark differences

SCollapsible is a thin styled wrapper; the Aria primitives own the open state (useControllableState), the presence/animation cycle (usePresence + getBoundingClientRect dimension measurement) and the accessibility wiring (aria-expanded/aria-controls/data-state). This mirrors shadcn/ui and Radix’s headless Collapsible, unlike Ant Design, Element Plus and Mantine which ship a config-driven collapsible or fold. VeanUI routes the trigger through its Button primitive so the styled Button variants are reused instead of a bespoke toggle.

CapabilityVeanUIshadcn/uiRadix CollapsibleAnt DesignElement PlusMantine
Aria/styled split✅✅✅———
Controlled/uncontrolled✅✅✅✅✅✅
Height animation✅✅✅✅✅✅
unmountOnHide✅✅✅———
forceMount✅✅✅———
as/asChild✅✅✅———
Trigger reuses Button✅—————

— = unsupported or a different interaction model.

Cautions

  • The collapse animation measures real dimensions with getBoundingClientRect, so it only runs on the client; under SSR the first paint renders the open/closed state without animating.
  • With unmountOnHide: true (default) closed content is removed from the DOM; with false it stays mounted but is hidden (hidden="until-found").
  • forceMount keeps the content element present even when closed — combine it with your own animation/transition to control reveal.
  • Wire the trigger via the Aria CollapsibleTrigger (a Button) so aria-expanded/aria-controls stay correct; a custom button must set these manually.
  • The content element carries data-state/data-disabled and the recipe’s data-[state=open]:animate-* classes drive the transition.

Roadmap

No blocking gaps identified for the core collapsible API.

FAQ

How do I build a collapsible with a toggle?

Use SCollapsible with the Aria CollapsibleTrigger for a styled button trigger:

<SCollapsible v-model:open="open">
  <template #default="{ open }">
    <SCollapsibleTrigger>Toggle ({{ open ? 'on' : 'off' }})</SCollapsibleTrigger>
    <SCollapsibleContent>Hidden panel content</SCollapsibleContent>
  </template>
</SCollapsible>

How do I control the open state?

Bind open with v-model (or use default-open):

<SCollapsible v-model:open="open">…</SCollapsible>

How do I keep the content mounted when closed?

Set unmount-on-hide="false" so it stays in the DOM (hidden) instead of being removed:

<SCollapsible :unmount-on-hide="false">…</SCollapsible>

How do I animate with my own transition?

Use force-mount and drive the reveal with your own classes or a <Transition>:

<SCollapsible force-mount>…</SCollapsible>

Is the panel keyboard accessible?

Yes — the CollapsibleTrigger is a real <button> that sets aria-expanded and aria-controls to the content id, and the content reflects data-state; focus stays on the trigger after toggling.

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.50.0

2026-10-02

Compare release

Fix

stop freezing transition-duration while measuring content

Scope: collapsibleAuthors: soybeanjsView commit5def1

Fix

release the mount-time animation freeze on the first toggle

Scope: collapsibleAuthors: soybeanjsView commitbf333

Fix

stop freezing transition-duration while measuring content

Scope: collapsibleAuthors: soybeanjsView commit5def1

Fix

release the mount-time animation freeze on the first toggle

Scope: collapsibleAuthors: soybeanjsView commitbf333

v0.0.2

2025-11-18

Compare release

Refactor

rename context functions and update data handling for collapsible components

Scope: collapsibleAuthors: soybeanjsView commitef610

Refactor

update element reference handling and enhance content ID uniqueness

Scope: collapsibleAuthors: soybeanjsView commite2673

Refactor

replace old collapsible component with new structure, update imports, and enhance theming support

Scope: collapsibleAuthors: soybeanjsView commite4b97

Refactor

rename context functions and update data handling for collapsible components

Scope: collapsibleAuthors: soybeanjsView commitef610

Refactor

update element reference handling and enhance content ID uniqueness

Scope: collapsibleAuthors: soybeanjsView commite2673

Refactor

replace old collapsible component with new structure, update imports, and enhance theming support

Scope: collapsibleAuthors: soybeanjsView commite4b97