Collapsible

A collapsible element to toggle visibility of its content.

Usage

Use a Button or any other component in the default slot of the Collapsible.

Then, use the #content slot to add the content displayed when the Collapsible is open.

<template>
  <PCollapsible class="flex flex-col gap-2 w-48">
    <PButton
      label="Open"
      color="neutral"
      variant="subtle"
      trailing-icon="i-lucide-chevron-down"
      block
    />

    <template #content>
      <Placeholder class="h-48" />
    </template>
  </PCollapsible>
</template>

Unmount

Use the unmount-on-hide prop to prevent the content from being unmounted when the Collapsible is collapsed. Defaults to true.

<template>
  <PCollapsible class="flex flex-col gap-2 w-48">
    <PButton
      label="Open"
      color="neutral"
      variant="subtle"
      trailing-icon="i-lucide-chevron-down"
      block
    />

    <template #content>
      <Placeholder class="h-48" />
    </template>
  </PCollapsible>
</template>
You can inspect the DOM to see the content being rendered.

Disabled

Use the disabled prop to disable the Collapsible.

<template>
  <PCollapsible class="flex flex-col gap-2 w-48" disabled>
    <PButton
      label="Open"
      color="neutral"
      variant="subtle"
      trailing-icon="i-lucide-chevron-down"
      block
    />

    <template #content>
      <Placeholder class="h-48" />
    </template>
  </PCollapsible>
</template>

Examples

Control open state

You can control the open state by using the default-open prop or the v-model:open directive.

<script setup lang="ts">
const open = ref(true);

defineShortcuts({
  o: () => open.value = !open.value,
});
</script>

<template>
  <PCollapsible
    v-model:open="open"
    class="flex flex-col gap-2 w-48"
  >
    <PButton
      label="Open"
      color="neutral"
      variant="subtle"
      trailing-icon="i-lucide-chevron-down"
      block
    />

    <template #content>
      <Placeholder class="h-48" />
    </template>
  </PCollapsible>
</template>
<script setup lang="ts">
import { ref } from 'vue'

const open = ref(true);

defineShortcuts({
  o: () => open.value = !open.value,
});
</script>

<template>
  <PCollapsible
    v-model:open="open"
    class="flex flex-col gap-2 w-48"
  >
    <PButton
      label="Open"
      color="neutral"
      variant="subtle"
      trailing-icon="i-lucide-chevron-down"
      block
    />

    <template #content>
      <Placeholder class="h-48" />
    </template>
  </PCollapsible>
</template>
In this example, leveraging defineShortcuts, you can toggle the Collapsible by pressing O.
This lets you move the trigger outside of the Collapsible or remove it entirely.

With rotating icon

Here is an example with a rotating icon in the Button that indicates the open state of the Collapsible.

<template>
  <PCollapsible class="flex flex-col gap-2 w-48">
    <PButton
      class="group"
      label="Open"
      color="neutral"
      variant="subtle"
      trailing-icon="i-lucide-chevron-down"
      :ui="{
        trailingIcon: 'group-data-[state=open]:rotate-180 transition-transform duration-200',
      }"
      block
    />

    <template #content>
      <Placeholder class="h-48" />
    </template>
  </PCollapsible>
</template>

API

Props

Prop Default Type
as
'div'
any

The element or component this component should render as.

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 binded 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.

ui
{ root?: SlotClass; content?: SlotClass; }

Slots

Slot Type
default
{ open: boolean; }
content
{}

Emits

Event Type
update:open
[value: boolean]

Theme

app.config.ts
export default defineAppConfig({
  ui: {
    collapsible: {
      slots: {
        root: '',
        content: 'data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down data-[state=closed]:overflow-hidden'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from 'pohon-ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        collapsible: {
          slots: {
            root: '',
            content: 'data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down data-[state=closed]:overflow-hidden'
          }
        }
      }
    })
  ]
})

Changelog

No recent changes