Skip to content
Destyler UI Destyler UI Destyler UI

Collapsible

A collapsible is a component which expands and collapses a panel.

@elonehoo starred 3 repositories

@destyler/collapsible

@elonehoo starred 3 repositories

@destyler/collapsible

@elonehoo starred 3 repositories

@destyler/collapsible

@elonehoo starred 3 repositories

@destyler/collapsible

Features

Install

Install the component from your command line.

Terminal window
      
        
npm install @destyler/{collapsible,vue}
Terminal window
      
        
npm install @destyler/{collapsible,react}
Terminal window
      
        
npm install @destyler/{collapsible,svelte}
Terminal window
      
        
npm install @destyler/{collapsible,solid}

Anatomy

Import all parts and piece them together.

<script setup lang="ts">
import * as collapsible from '@destyler/collapsible'
import { normalizeProps, useMachine } from '@destyler/vue'
import { computed, useId } from 'vue'
const [state, send] = useMachine(collapsible.machine({ id: useId() }))
const api = computed(() =>
collapsible.connect(state.value, send, normalizeProps),
)
</script>
<template>
<div v-bind="api.getRootProps()">
<button v-bind="api.getTriggerProps()"></button>
<div v-bind="api.getContentProps()"></div>
</div>
</template>
import * as collapsible from '@destyler/collapsible'
import { normalizeProps, useMachine } from '@destyler/react'
import { useId } from 'react'
export default function Collapsible() {
const [state, send] = useMachine(collapsible.machine({ id: useId() }))
const api = collapsible.connect(state, send, normalizeProps)
return (
<div {...api.getRootProps()}>
<button {...api.getTriggerProps()}></button>
<div {...api.getContentProps()}></div>
</div>
)
}
<script lang="ts">
import * as collapsible from '@destyler/collapsible'
import { normalizeProps, useMachine } from '@destyler/svelte'
const id = $props.id()
const [state, send] = useMachine(collapsible.machine({ id }))
const api = $derived(collapsible.connect(state, send, normalizeProps))
</script>
<div {...api.getRootProps()}>
<button {...api.getTriggerProps()}></button>
<div {...api.getContentProps()}>
</div>
import * as collapsible from '@destyler/collapsible'
import { normalizeProps, useMachine } from '@destyler/solid'
import { createMemo, createUniqueId } from 'solid-js'
export default function Collapsible() {
const [state, send] = useMachine(collapsible.machine({ id: createUniqueId() }))
const api = createMemo(() => collapsible.connect(state, send, normalizeProps))
return (
<div {...api().getRootProps()} >
<button {...api().getTriggerProps()} ></button>
<div {...api().getContentProps()} ></div>
</div>
)
}

Listening for changes

When the collapsible state changes, the onOpenChange callback is invoked.

const [state, send] = useMachine(
collapsible.machine({
onOpenChange(details) {
// details => { open: boolean }
console.log("collapsible open:", details.open)
},
}),
)

Disabling the collapsible

Set the disabled machine context property to true to disable the collapsible.

const [state, send] = useMachine(
collapsible.machine({
disabled: true,
}),
)

Animating the collapsible

Use CSS animations to animate the collapsible when it expands and collapses. The --destyler-height and --destyler-width custom properties are attached to the content part.

@keyframes expand {
from {
height: 0;
}
to {
height: var(--destyler-height);
}
}
@keyframes collapse {
from {
height: var(--destyler-height);
}
to {
height: 0;
}
}
[data-scope="collapsible"][data-part="content"] {
overflow: hidden;
max-width: 400px;
}
[data-scope="collapsible"][data-part="content"][data-state="open"] {
animation: expand 450ms cubic-bezier(0.16, 1, 0.3, 1);
}
[data-scope="collapsible"][data-part="content"][data-state="closed"] {
animation: collapse 250ms cubic-bezier(0.16, 1, 0.3, 1);
}

Styling Guide

Earlier, we mentioned that each collapse part has a data-part attribute added to them to select and style them in the DOM.

Open and closed state

When a collapsible is expanded or collapsed, a data-state attribute is set on the root, trigger and content elements. This attribute is removed when it is closed.

[data-part="root"][data-state="open"] {
/* styles for the collapsible is open or closed state */
}
[data-part="trigger"][data-state="open"] {
/* styles for the collapsible is open or closed state */
}
[data-part="content"][data-state="open"] {
/* styles for the collapsible is open or closed state */
}

Focused state

When a collapsible’s trigger is focused, a data-focus attribute is set on the root, trigger and content.

[data-part="root"][data-focus] {
/* styles for the item's focus state */
}
[data-part="trigger"][data-focus] {
/* styles for the content's focus state */
}
[data-part="content"][data-focus] {
/* styles for the content's focus state */
}

Methods and Properties

Machine Context

The collapsible machine exposes the following context properties:

ids
Partial<{ root: string; content: string; trigger: string; }>
The ids of the elements in the collapsible. Useful for composition.
onExitComplete
() => void
Function called when the animation ends in the closed state.
onOpenChange
(details: OpenChangeDetails) => void
Function called when the popup is opened
open
boolean
Whether the collapsible is open
disabled
boolean
Whether the collapsible is disabled
open.controlled
boolean
Whether the collapsible open state is controlled by the user
dir
"ltr" | "rtl"
The document's text/writing direction.
id
string
The unique identifier of the machine.
getRootNode
() => ShadowRoot | Node | Document
A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.

Machine API

The collapsible api exposes the following methods:

open
boolean
Whether the collapsible is open.
visible
boolean
Whether the collapsible is visible (open or closing)
disabled
boolean
Whether the collapsible is disabled
setOpen
(open: boolean) => void
Function to open or close the collapsible.
measureSize
() => void
Function to measure the size of the content.

Data Attributes

Root

name
desc
data-scope
collapsible
data-part
root
data-state
"open" | "closed"

Content

name
desc
data-scope
collapsible
data-part
content
data-state
"open" | "closed"
data-disabled
Present when disabled

Trigger

name
desc
data-scope
collapsible
data-part
trigger
data-state
"open" | "closed"
data-disabled
Present when disabled

Accessibility

Keyboard Interaction

name
desc
Space
Opens/closes the collapsible.
Enter
Opens/closes the collapsible.