Skip to content

Collapse

A content area that can be collapsed or expanded.

NameCategoryDescriptionTypeDefault
ghost? StyleGhost mode with no border or backgroundbooleanfalse
icon-placement? StylePosition of the indicator icon'start' | 'end''end'
CollapseItemshow-arrow? StyleWhether to show the arrow indicatorbooleantrue
CollapseItemicon? StyleCustom indicator icon name (supports all built-in icons). Set to "plus" for an automatic plus/minus toggle effectstring
color? ColorColor theme. Supports preset names (primary / success / warning / danger / info) or custom hex colorsstring
CollapseItemdisabled? StateWhether disabledbooleanfalse
accordion? BehaviorWhether to enable accordion modebooleanfalse
trigger? BehaviorTrigger mode. In 'focus' mode, items open on focus and close on blur'click' | 'focus''click'
CollapseItemforce-open? BehaviorForce item to stay open, ignoring modelValue and click interactionsbooleanfalse
CollapseItemforce-close? BehaviorForce item to stay closed, ignoring modelValue and click interactions. Takes precedence over force-openbooleanfalse
model-value / v-model? ContentCurrently active panelsstring | string[]
CollapseItemname? ContentUnique identifierstring
CollapseItemtitle? ContentTitlestring
change? EventTriggered when active panels change(activeNames: string | string[]) => void
CollapseItemdefault? SlotPanel content
CollapseItemtitle? SlotCustom title

Basic Usage

Multiple panels can be expanded at the same time without affecting each other.

<script setup lang="ts">
import { type CollapseItemName } from 'sakana-element';
import { ref } from 'vue';

const activeNames = ref(['1']);

function handleChange(_val: CollapseItemName[]) {}
</script>

<template>
  <px-collapse v-model="activeNames" @change="handleChange">
    <px-collapse-item title="Consistency" name="1">
      <div>
        Consistent with real life: in line with the process and logic of real
        life, and comply with languages and habits that the users are used to;
      </div>
      <div>
        Consistent within interface: all elements should be consistent, such as:
        design style, icons and texts, position of elements, etc.
      </div>
    </px-collapse-item>
    <px-collapse-item title="Feedback" name="2">
      <div>
        Operation feedback: enable the users to clearly perceive their
        operations by style updates and interactive effects;
      </div>
      <div>
        Visual feedback: reflect current state by updating or rearranging
        elements of the page.
      </div>
    </px-collapse-item>
    <px-collapse-item title="Efficiency" name="3">
      <div>
        Simplify the process: keep operating process simple and intuitive;
      </div>
      <div>
        Definite and clear: enunciate your intentions clearly so that the users
        can quickly understand and make decisions;
      </div>
      <div>
        Easy to identify: the interface should be straightforward, which helps
        the users to identify and frees them from memorizing and recalling.
      </div>
    </px-collapse-item>
    <px-collapse-item title="Controllability" name="4">
      <div>
        Decision making: giving advices about operations is acceptable, but do
        not make decisions for the users;
      </div>
      <div>
        Controlled consequences: users should be granted the freedom to operate,
        including canceling, aborting or terminating current operation.
      </div>
    </px-collapse-item>
  </px-collapse>
</template>

Accordion Mode

Use accordion property to enable accordion mode, where only one panel can be expanded at a time.

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

const activeNames = ref(['1']);
</script>

<template>
  <px-collapse v-model="activeNames" accordion>
    <px-collapse-item title="Consistency" name="1">
      <div>
        Consistent with real life: in line with the process and logic of real
        life, and comply with languages and habits that the users are used to;
      </div>
      <div>
        Consistent within interface: all elements should be consistent, such as:
        design style, icons and texts, position of elements, etc.
      </div>
    </px-collapse-item>
    <px-collapse-item title="Feedback" name="2">
      <div>
        Operation feedback: enable the users to clearly perceive their
        operations by style updates and interactive effects;
      </div>
      <div>
        Visual feedback: reflect current state by updating or rearranging
        elements of the page.
      </div>
    </px-collapse-item>
    <px-collapse-item title="Efficiency" name="3">
      <div>
        Simplify the process: keep operating process simple and intuitive;
      </div>
      <div>
        Definite and clear: enunciate your intentions clearly so that the users
        can quickly understand and make decisions;
      </div>
      <div>
        Easy to identify: the interface should be straightforward, which helps
        the users to identify and frees them from memorizing and recalling.
      </div>
    </px-collapse-item>
    <px-collapse-item title="Controllability" name="4">
      <div>
        Decision making: giving advices about operations is acceptable, but do
        not make decisions for the users;
      </div>
      <div>
        Controlled consequences: users should be granted the freedom to operate,
        including canceling, aborting or terminating current operation.
      </div>
    </px-collapse-item>
  </px-collapse>
</template>

Color Variants

Use the color prop with preset names to style the collapse with theme colors.

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

const active1 = ref(['1']);
const active2 = ref(['1']);
const active3 = ref(['1']);
const active4 = ref(['1']);
const active5 = ref(['1']);
</script>

<template>
  <div style="display: flex; flex-direction: column; gap: 16px;">
    <px-collapse v-model="active1" color="primary">
      <px-collapse-item title="Primary Color" name="1">
        This collapse uses the primary color theme.
      </px-collapse-item>
      <px-collapse-item title="Second Item" name="2">
        Content of the second item.
      </px-collapse-item>
    </px-collapse>

    <px-collapse v-model="active2" color="success">
      <px-collapse-item title="Success Color" name="1">
        This collapse uses the success color theme.
      </px-collapse-item>
      <px-collapse-item title="Second Item" name="2">
        Content of the second item.
      </px-collapse-item>
    </px-collapse>

    <px-collapse v-model="active3" color="warning">
      <px-collapse-item title="Warning Color" name="1">
        This collapse uses the warning color theme.
      </px-collapse-item>
      <px-collapse-item title="Second Item" name="2">
        Content of the second item.
      </px-collapse-item>
    </px-collapse>

    <px-collapse v-model="active4" color="danger">
      <px-collapse-item title="Danger Color" name="1">
        This collapse uses the danger color theme.
      </px-collapse-item>
      <px-collapse-item title="Second Item" name="2">
        Content of the second item.
      </px-collapse-item>
    </px-collapse>

    <px-collapse v-model="active5" color="info">
      <px-collapse-item title="Info Color" name="1">
        This collapse uses the info color theme.
      </px-collapse-item>
      <px-collapse-item title="Second Item" name="2">
        Content of the second item.
      </px-collapse-item>
    </px-collapse>
  </div>
</template>

Custom Color

Pass any hex color string to the color prop for a fully custom color theme.

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

const activeNames = ref(['1']);
</script>

<template>
  <px-collapse v-model="activeNames" color="#e91e63">
    <px-collapse-item title="Custom Hex Color" name="1">
      This collapse uses a custom hex color (#e91e63).
    </px-collapse-item>
    <px-collapse-item title="Second Item" name="2">
      Content of the second item.
    </px-collapse-item>
    <px-collapse-item title="Third Item" name="3">
      Content of the third item.
    </px-collapse-item>
  </px-collapse>
</template>

Ghost

Enable ghost mode for a borderless, backgroundless appearance — useful when embedding inside other containers.

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

const activeNames = ref(['1']);
</script>

<template>
  <px-collapse v-model="activeNames" ghost>
    <px-collapse-item title="Ghost Mode" name="1">
      This collapse uses ghost mode — no pixel border or shadow.
    </px-collapse-item>
    <px-collapse-item title="Clean Look" name="2">
      Perfect for embedding inside other containers.
    </px-collapse-item>
    <px-collapse-item title="Minimal Style" name="3">
      Keeps the interaction while removing visual weight.
    </px-collapse-item>
  </px-collapse>
</template>

Focus Trigger

Set trigger="focus" to open panels on focus and close them on blur. Navigate with the Tab key.

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

const activeNames = ref<string[]>([]);
</script>

<template>
  <px-collapse v-model="activeNames" trigger="focus">
    <px-collapse-item title="Focus to Open" name="1">
      This item opens when the header receives focus (Tab key or click).
    </px-collapse-item>
    <px-collapse-item title="Blur to Close" name="2">
      This item closes when focus moves away from the header.
    </px-collapse-item>
    <px-collapse-item title="Try Tab Key" name="3">
      Use Tab to navigate between items — they open and close automatically.
    </px-collapse-item>
  </px-collapse>
</template>

Icon Placement

Use icon-placement="start" to move the arrow indicator before the title.

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

const activeNames = ref(['1']);
</script>

<template>
  <px-collapse v-model="activeNames" icon-placement="start">
    <px-collapse-item title="Icon at Start" name="1">
      The arrow indicator is placed before the title text.
    </px-collapse-item>
    <px-collapse-item title="Left-side Arrow" name="2">
      This layout is common in file explorers and tree views.
    </px-collapse-item>
    <px-collapse-item title="Familiar Pattern" name="3">
      Users can quickly identify expandable sections.
    </px-collapse-item>
  </px-collapse>
</template>

Force Open / Close

Use force-open or force-close on individual items to lock their state. force-close takes precedence over force-open.

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

const activeNames = ref(['2']);
</script>

<template>
  <px-collapse v-model="activeNames">
    <px-collapse-item title="Always Open (force-open)" name="1" force-open>
      This item is always expanded, regardless of the v-model value. Clicking the header has no effect.
    </px-collapse-item>
    <px-collapse-item title="Normal Item" name="2">
      This item behaves normally — click to toggle.
    </px-collapse-item>
    <px-collapse-item title="Always Closed (force-close)" name="3" force-close>
      This item is always collapsed. Even if its name is in the v-model array, it stays closed.
    </px-collapse-item>
  </px-collapse>
</template>

No Arrow

Hide the arrow indicator with show-arrow="false" for a cleaner look.

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

const activeNames = ref(['1']);
</script>
<template>
  <px-collapse v-model="activeNames">
    <px-collapse-item title="How do I create an account?" name="1" :show-arrow="false">
      Click the "Sign Up" button in the top right corner and follow the registration process.
    </px-collapse-item>
    <px-collapse-item title="I forgot my password. What should I do?" name="2" :show-arrow="false">
      Click "Forgot Password" on the login page to reset your password via email.
    </px-collapse-item>
    <px-collapse-item title="How do I update my profile information?" name="3" :show-arrow="false">
      Go to Settings > Profile to update your personal information.
    </px-collapse-item>
  </px-collapse>
</template>

Plus/Minus Icon

Use icon="plus" for a plus/minus toggle indicator instead of the default arrow.

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

const activeNames = ref(['1']);
</script>
<template>
  <px-collapse v-model="activeNames">
    <px-collapse-item title="How do I create an account?" name="1" icon="plus">
      Click the "Sign Up" button in the top right corner and follow the registration process.
    </px-collapse-item>
    <px-collapse-item title="I forgot my password. What should I do?" name="2" icon="plus">
      Click "Forgot Password" on the login page to reset your password via email.
    </px-collapse-item>
    <px-collapse-item title="How do I update my profile information?" name="3" icon="plus">
      Go to Settings > Profile to update your personal information.
    </px-collapse-item>
  </px-collapse>
</template>

Custom Icon

Use the icon prop with any built-in icon name to replace the default arrow. The icon remains static (no rotation). Set icon="plus" for the special plus/minus toggle shown above.

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

const activeNames = ref(['1']);
</script>
<template>
  <px-collapse v-model="activeNames">
    <px-collapse-item title="Favorites" name="1" icon="heart">
      Manage your favorite items and saved collections here.
    </px-collapse-item>
    <px-collapse-item title="Bookmarks" name="2" icon="bookmark">
      Access your bookmarked pages and resources.
    </px-collapse-item>
    <px-collapse-item title="Quick Actions" name="3" icon="zap">
      Shortcuts for frequently used operations.
    </px-collapse-item>
  </px-collapse>
</template>

Custom Title

Use title slot to customize the title content.

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

const activeNames = ref(['1']);
</script>

<template>
  <px-collapse v-model="activeNames" accordion>
    <px-collapse-item name="1">
      <template #title>
        <span style="color: var(--px-color-danger)"> Consistency </span>
        <px-icon icon="info-box" />
      </template>
      <div>
        Consistent with real life: in line with the process and logic of real
        life, and comply with languages and habits that the users are used to;
      </div>
      <div>
        Consistent within interface: all elements should be consistent, such as:
        design style, icons and texts, position of elements, etc.
      </div>
    </px-collapse-item>
    <px-collapse-item title="Feedback" name="2">
      <div>
        Operation feedback: enable the users to clearly perceive their
        operations by style updates and interactive effects;
      </div>
      <div>
        Visual feedback: reflect current state by updating or rearranging
        elements of the page.
      </div>
    </px-collapse-item>
    <px-collapse-item title="Efficiency" name="3">
      <div>
        Simplify the process: keep operating process simple and intuitive;
      </div>
      <div>
        Definite and clear: enunciate your intentions clearly so that the users
        can quickly understand and make decisions;
      </div>
      <div>
        Easy to identify: the interface should be straightforward, which helps
        the users to identify and frees them from memorizing and recalling.
      </div>
    </px-collapse-item>
    <px-collapse-item title="Controllability" name="4">
      <div>
        Decision making: giving advices about operations is acceptable, but do
        not make decisions for the users;
      </div>
      <div>
        Controlled consequences: users should be granted the freedom to operate,
        including canceling, aborting or terminating current operation.
      </div>
    </px-collapse-item>
  </px-collapse>
</template>

Disabled State

Use disabled property to disable the panel.

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

const activeNames = ref(['1']);
</script>

<template>
  <px-collapse v-model="activeNames">
    <px-collapse-item title="Consistency" name="1">
      <div>
        Consistent with real life: in line with the process and logic of real
        life, and comply with languages and habits that the users are used to;
      </div>
      <div>
        Consistent within interface: all elements should be consistent, such as:
        design style, icons and texts, position of elements, etc.
      </div>
    </px-collapse-item>
    <px-collapse-item title="Feedback" name="2" disabled>
      <div>
        Operation feedback: enable the users to clearly perceive their
        operations by style updates and interactive effects;
      </div>
      <div>
        Visual feedback: reflect current state by updating or rearranging
        elements of the page.
      </div>
    </px-collapse-item>
    <px-collapse-item title="Efficiency" name="3" disabled>
      <div>
        Simplify the process: keep operating process simple and intuitive;
      </div>
      <div>
        Definite and clear: enunciate your intentions clearly so that the users
        can quickly understand and make decisions;
      </div>
      <div>
        Easy to identify: the interface should be straightforward, which helps
        the users to identify and frees them from memorizing and recalling.
      </div>
    </px-collapse-item>
    <px-collapse-item title="Controllability" name="4">
      <div>
        Decision making: giving advices about operations is acceptable, but do
        not make decisions for the users;
      </div>
      <div>
        Controlled consequences: users should be granted the freedom to operate,
        including canceling, aborting or terminating current operation.
      </div>
    </px-collapse-item>
  </px-collapse>
</template>