Skip to content

Collapse

Toggleable disclosure pane wrapping Reka's Collapsible primitive. Three parts: outer root, trigger, content. Auto-animated height transition + aria-expanded / aria-controls wiring out of the box.

bash
npm install @vuecs/elements
vue
<script setup lang="ts">
import {
    VCCollapse,
    VCCollapseContent,
    VCCollapseTrigger,
} from '@vuecs/elements';
import { ref } from 'vue';

const open = ref(false);
</script>

<template>
    <VCCollapse v-model:open="open">
        <VCCollapseTrigger>
            {{ open ? 'Hide details' : 'Show details' }}
        </VCCollapseTrigger>
        <VCCollapseContent>
            <p>Reka handles the height transition + a11y wiring.</p>
        </VCCollapseContent>
    </VCCollapse>
</template>
css
@import "tailwindcss";
@import "@vuecs/design";
@import "@vuecs/elements";

@custom-variant dark (&:where(.dark, .dark *));

Compound API

ComponentReka primitiveDefault tagRole
VCCollapseCollapsibleRoot<div>Outer container; owns v-model:open state
VCCollapseTriggerCollapsibleTrigger<button>Toggle button — clicks + Enter / Space toggle open
VCCollapseContentCollapsibleContent<div>Collapsing pane; auto-animated via Reka's Presence

Chevron variant

<VCCollapseTrigger> auto-renders a rotating chevron icon when an active icon preset is installed (e.g. @vuecs/icons-lucide ships 'lucide:chevron-down'). The chevron rotates 180° on open via the [data-state="open"] .vc-collapse-chevron structural rule.

Hide the chevron via :theme-variant:

vue
<VCCollapseTrigger :theme-variant="{ chevron: 'none' }">
    Custom trigger content
</VCCollapseTrigger>

Composition patterns

Card with collapsible body (FAQ)

vue
<VCCollapse>
    <VCCard>
        <VCCardHeader>
            <VCCollapseTrigger as-child>
                <button class="w-full flex items-center justify-between">
                    <VCCardTitle>How do I install vuecs?</VCCardTitle>
                    <VCIcon name="lucide:chevron-down" class="vc-collapse-chevron" />
                </button>
            </VCCollapseTrigger>
        </VCCardHeader>
        <VCCollapseContent>
            <VCCardBody>Run <code>npm install @vuecs/core</code> ...</VCCardBody>
        </VCCollapseContent>
    </VCCard>
</VCCollapse>

as-child on <VCCollapseTrigger> passes the trigger behavior to your own child element — useful when the trigger needs custom layout (card header, table row, etc.). The component suppresses the auto-chevron in as-child mode because Reka's asChild merges trigger props onto the slot's first child only — an injected chevron would render as a sibling outside the interactive element. Render your own chevron inside the custom child (use the vc-collapse-chevron class to inherit the rotate-on-open behavior).

Alert dismiss-with-collapse animation

vue
<script setup lang="ts">
const visible = ref(true);
</script>

<template>
    <VCCollapse v-model:open="visible">
        <VCCollapseContent>
            <VCAlert color="error">
                <VCAlertTitle>Save failed</VCAlertTitle>
                <VCAlertClose @click="visible = false" />
            </VCAlert>
        </VCCollapseContent>
    </VCCollapse>
</template>

Reka's Presence waits for the accordion-up animation to finish before unmounting the alert. Without <VCCollapse>, the alert disappears instantly.

Theme keys

KeySlotsNotes
collapseroot
collapseTriggerroot, chevronchevron: 'auto' | 'none' variant
collapseContentrootTheme classes animate via --reka-collapsible-content-height

Animations

<VCCollapseContent> uses data-state="open|closed" driven by Reka. Both themes ship accordion-down / accordion-up keyframes via @vuecs/design's vanilla-CSS port of tw-animate-css, interpolating from 0 → --reka-collapsible-content-height (and reverse). Tailwind theme gates via data-[state=open]:animate-accordion-down; BS5 and Bulma themes use the dual-state helper class vc-collapse-anim. prefers-reduced-motion: reduce disables every animation.

API Reference

<VCCollapse>

PropTypeDefaultDescription
openboolean | undefinedundefinedControlled state; bind with v-model:open. Leave undefined for uncontrolled.
defaultOpenbooleanfalseInitial state when open is undefined.
disabledbooleanfalseDisable interaction (trigger ignores clicks).
unmountOnHidebooleantrueUnmount the content element when closed. Set to false to preserve state (form inputs, animations) across cycles.
asstring'div'HTML tag to render.
asChildbooleanfalsePass through to consumer's child element.
EmitPayloadDescription
update:openbooleanFired when the open state changes.

<VCCollapseTrigger>

PropTypeDefaultDescription
chevron'auto' | 'none''auto'Show / hide the auto-rendered chevron indicator.
asstring'button'HTML tag to render.
asChildbooleanfalsePass trigger behavior to a custom child element.

<VCCollapseContent>

PropTypeDefaultDescription
forceMountbooleanfalseKeep mounted while closed. Useful when you need Vue-level control of the unmount cascade.
asstring'div'HTML tag to render.
asChildbooleanfalsePass content behavior to a custom child element.

Released under the Apache 2.0 License.