<script setup>
import { ref } from "vue";
import { Collapsible } from "@dicehub/phi/components/collapsible";
const open = ref(true);
</script>
<template>
<Collapsible v-model:open="open">
<Collapsible.DefaultTrigger>What is Phi?</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
Phi is a Vue component library.
</Collapsible.DefaultPanel>
</Collapsible>
</template>Installation
Barrel
import { Collapsible } from "@dicehub/phi";Granular
import { Collapsible } from "@dicehub/phi/components/collapsible";Usage
Collapsible uses a compound component pattern for full composition control.
With Default Styling
Use DefaultTrigger and DefaultPanel for Phi styling and smooth height animation. DefaultPanel applies its border and spacing through an inner content wrapper; use Panel when custom layout classes must control the panel element directly.
<script setup>
import { ref } from "vue";
import { Collapsible } from "@dicehub/phi/components/collapsible";
const open = ref(false);
</script>
<template>
<Collapsible v-model:open="open">
<Collapsible.DefaultTrigger>Show details</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
Content with border-left accent styling.
</Collapsible.DefaultPanel>
</Collapsible>
</template>Custom Trigger
Use as-child on Trigger for full control over the trigger element.
<script setup>
import { ref } from "vue";
import { Button } from "@dicehub/phi/components/button";
import { Collapsible } from "@dicehub/phi/components/collapsible";
const open = ref(false);
</script>
<template>
<Collapsible v-model:open="open">
<Collapsible.Trigger as-child>
<Button variant="secondary" size="sm">
{{ open ? "Hide details" : "Show details" }}
</Button>
</Collapsible.Trigger>
<Collapsible.Panel class="custom-panel">
Custom styled panel content.
</Collapsible.Panel>
</Collapsible>
</template>Examples
Basic
<script setup>
import { ref } from "vue";
import { Collapsible } from "@dicehub/phi/components/collapsible";
const open = ref(false);
</script>
<template>
<Collapsible v-model:open="open">
<Collapsible.DefaultTrigger>What is Phi?</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
Phi is a Vue component library.
</Collapsible.DefaultPanel>
</Collapsible>
</template>Multiple Items
<script setup>
import { ref } from "vue";
import { Collapsible } from "@dicehub/phi/components/collapsible";
const firstOpen = ref(false);
const secondOpen = ref(false);
const thirdOpen = ref(false);
</script>
<template>
<div class="space-y-2">
<Collapsible v-model:open="firstOpen">
<Collapsible.DefaultTrigger>What is Phi?</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
Phi is a Vue component library.
</Collapsible.DefaultPanel>
</Collapsible>
<Collapsible v-model:open="secondOpen">
<Collapsible.DefaultTrigger>How do I use it?</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
Install the components and import them into your project.
</Collapsible.DefaultPanel>
</Collapsible>
<Collapsible v-model:open="thirdOpen">
<Collapsible.DefaultTrigger>Is it open source?</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
Check the repository for license information.
</Collapsible.DefaultPanel>
</Collapsible>
</div>
</template>Custom Trigger
Use Collapsible.Trigger with as-child for full control.
<script setup>
import { ref } from "vue";
import { Button } from "@dicehub/phi/components/button";
import { Collapsible } from "@dicehub/phi/components/collapsible";
const open = ref(false);
</script>
<template>
<Collapsible v-model:open="open">
<Collapsible.Trigger as-child>
<Button variant="secondary" size="sm">
{{ open ? "Hide details" : "Show details" }}
</Button>
</Collapsible.Trigger>
<Collapsible.Panel class="custom-panel">
This panel uses custom styling instead of the default border-left accent.
</Collapsible.Panel>
</Collapsible>
</template>Keep Mounted
Phi panels stay mounted by default. Avoid unmountOnExit when internal state, such as form input, should be preserved while collapsed.
<script setup>
import { ref } from "vue";
import { Collapsible } from "@dicehub/phi/components/collapsible";
const open = ref(true);
const name = ref("");
</script>
<template>
<Collapsible v-model:open="open">
<Collapsible.DefaultTrigger>Edit details</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
<p>
Type something below, then collapse and re-open. Your input is preserved
because panels stay mounted by default.
</p>
<label>
<span>Name</span>
<input v-model="name" placeholder="Type here..." />
</label>
</Collapsible.DefaultPanel>
</Collapsible>
</template>Accordion Pattern
Control which item is open to create an accordion where only one item can be expanded at a time.
<script setup>
import { ref } from "vue";
import { Collapsible } from "@dicehub/phi/components/collapsible";
const activeIndex = ref(0);
const items = [
{
title: "What is Phi?",
content: "Phi is a Vue component library built on accessible primitives.",
},
{
title: "How do I install it?",
content: "Install the package and import the components you need.",
},
{
title: "Is it accessible?",
content: "Yes. Phi components keep keyboard and screen reader behavior in the primitive layer.",
},
];
const setAccordionItem = (index, open) => {
activeIndex.value = open ? index : -1;
};
</script>
<template>
<div class="space-y-2">
<Collapsible
v-for="(item, index) in items"
:key="item.title"
:open="activeIndex === index"
@open-change="(details) => setAccordionItem(index, details.open)"
>
<Collapsible.DefaultTrigger>{{ item.title }}</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
{{ item.content }}
</Collapsible.DefaultPanel>
</Collapsible>
</div>
</template>Sub-components
| Component | Description |
|---|---|
Collapsible.Root | Manages open state. Use open and update:open for controlled mode. |
Collapsible.Trigger | Button that toggles visibility. Use as-child to render a custom trigger component. |
Collapsible.Panel | Container for collapsible content. |
Collapsible.DefaultTrigger | Pre-styled trigger with text label and animated caret icon. |
Collapsible.DefaultPanel | Pre-styled panel with border-left accent and standard spacing. |
API Reference
Collapsible.Root
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Controlled open state. Use v-model:open in Vue. |
defaultOpen | boolean | false | Initial open state for uncontrolled usage. |
disabled | boolean | false | Disables the trigger and prevents state changes. |
lazyMount | boolean | false | Mounts the panel only when it first opens. |
unmountOnExit | boolean | false | Unmounts the panel after it closes. |
collapsedHeight | number | string | - | Visible content height while collapsed. |
collapsedWidth | number | string | - | Visible content width while collapsed. |
Collapsible.Trigger
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Uses the provided child as the rendered trigger element. |
class | string | - | Additional CSS classes. |
Collapsible.Panel
| Prop | Type | Default | Description |
|---|---|---|---|
class | string | - | Additional CSS classes. |
Collapsible.DefaultTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
default slot | unknown | - | Label content displayed in the trigger. |
class | string | - | Additional CSS classes. |
Collapsible.DefaultPanel
| Prop | Type | Default | Description |
|---|---|---|---|
default slot | unknown | - | Panel content. |
class | string | - | Additional CSS classes. |