Skip to content

Collapsible ​

A lightweight single-toggle component for showing and hiding content. Unlike Collapse (multi-panel accordion), Collapsible manages a single open/close state — perfect for toggleable sections, expandable details, or progressive disclosure patterns.

NameCategoryDescriptionTypeDefault
ghost? StyleGhost mode with no border or shadowbooleanfalse
color? ColorColor theme. Supports preset names (primary / success / warning / danger / info) or custom hex colorsstring—
disabled? StateWhether disabledbooleanfalse
default-open? BehaviorDefault expanded state (uncontrolled mode)booleanfalse
CollapsibleTriggeras-child? BehaviorWhether to use child element as trigger (reserved)booleanfalse
model-value / v-model? ContentWhether expanded (controlled mode)boolean—
change? EventTriggered when open state changes(open: boolean) => void—
default? SlotContent area, should contain CollapsibleTrigger and CollapsibleContent—
CollapsibleTriggerdefault? SlotTrigger content—
CollapsibleContentdefault? SlotCollapsible content—
open? ExposeCurrent open stateRef<boolean>—
toggle? ExposeToggle open/close state() => void—

Basic Usage ​

Click the trigger to toggle the content area.

<template>
  <div class="demo-collapsible">
    <px-collapsible>
      <px-collapsible-trigger>
        <span class="trigger-label">Click to toggle</span>
      </px-collapsible-trigger>
      <px-collapsible-content>
        <p>This is the collapsible content. It can contain any elements.</p>
      </px-collapsible-content>
    </px-collapsible>
  </div>
</template>

<style scoped>
.demo-collapsible {
  max-width: 400px;
}
.trigger-label {
  font-weight: 500;
}
</style>

Default Open ​

Use the default-open prop to start with the content expanded.

<template>
  <div class="demo-collapsible">
    <px-collapsible default-open>
      <px-collapsible-trigger>
        <span class="trigger-label">Starts expanded</span>
      </px-collapsible-trigger>
      <px-collapsible-content>
        <p>This content is visible by default when the component mounts.</p>
      </px-collapsible-content>
    </px-collapsible>
  </div>
</template>

<style scoped>
.demo-collapsible {
  max-width: 400px;
}
.trigger-label {
  font-weight: 500;
}
</style>

Disabled ​

Set disabled to prevent the collapsible from being toggled.

<template>
  <div class="demo-collapsible">
    <px-collapsible disabled>
      <px-collapsible-trigger>
        <span class="trigger-label">Disabled (cannot toggle)</span>
      </px-collapsible-trigger>
      <px-collapsible-content>
        <p>This content is hidden and cannot be toggled.</p>
      </px-collapsible-content>
    </px-collapsible>
  </div>
</template>

<style scoped>
.demo-collapsible {
  max-width: 400px;
}
.trigger-label {
  font-weight: 500;
}
</style>

Color Variants ​

Use the color prop with preset names or custom hex values.

<template>
  <div class="demo-collapsible">
    <px-collapsible v-for="c in colors" :key="c" :color="c" default-open>
      <px-collapsible-trigger>
        <span class="trigger-label">{{ c }}</span>
      </px-collapsible-trigger>
      <px-collapsible-content>
        <p>Content styled with {{ c }} color theme.</p>
      </px-collapsible-content>
    </px-collapsible>

    <px-collapsible color="#e64553" default-open>
      <px-collapsible-trigger>
        <span class="trigger-label">Custom hex #e64553</span>
      </px-collapsible-trigger>
      <px-collapsible-content>
        <p>Content styled with a custom hex color.</p>
      </px-collapsible-content>
    </px-collapsible>
  </div>
</template>

<script setup lang="ts">
const colors = ['primary', 'success', 'warning', 'danger', 'info'];
</script>

<style scoped>
.demo-collapsible {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 400px;
}
.trigger-label {
  font-weight: 500;
  text-transform: capitalize;
}
</style>

Ghost ​

Enable ghost mode for a borderless, shadowless appearance.

<template>
  <div class="demo-collapsible">
    <px-collapsible ghost>
      <px-collapsible-trigger>
        <span class="trigger-label">Ghost mode (no border)</span>
      </px-collapsible-trigger>
      <px-collapsible-content>
        <p>Content area without pixel border or shadow — useful when embedding inside other containers.</p>
      </px-collapsible-content>
    </px-collapsible>

    <px-collapsible ghost color="primary">
      <px-collapsible-trigger>
        <span class="trigger-label">Ghost + color</span>
      </px-collapsible-trigger>
      <px-collapsible-content>
        <p>Ghost mode combined with a preset color.</p>
      </px-collapsible-content>
    </px-collapsible>
  </div>
</template>

<style scoped>
.demo-collapsible {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 400px;
}
.trigger-label {
  font-weight: 500;
}
</style>

Controlled State ​

Use v-model to control the open state from outside the component.

<template>
  <div class="demo-collapsible">
    <px-button @click="isOpen = !isOpen">
      {{ isOpen ? 'Close' : 'Open' }} from outside
    </px-button>

    <px-collapsible v-model="isOpen" color="primary">
      <px-collapsible-trigger>
        <span class="trigger-label">Controlled state: {{ isOpen ? 'Open' : 'Closed' }}</span>
      </px-collapsible-trigger>
      <px-collapsible-content>
        <p>This collapsible is controlled via <code>v-model</code>. You can toggle it from the button above or by clicking the trigger.</p>
      </px-collapsible-content>
    </px-collapsible>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

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

<style scoped>
.demo-collapsible {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 400px;
}
.trigger-label {
  font-weight: 500;
}
</style>