Details
An accessible accordion or toggle component for details and summary elements.
Installation
Follow instructions for individual framework usage below
Styles
Variants
Scripts
The Details script keeps a checkbox inside summary in sync with the native details[open] state.
Examples
Default
<details class="x-details group bg-body-secondary rounded-md">
<summary class="flex items-center gap-2 text-primary p-4">
<span class="x-title">Show more</span>
<svg class="size-4 group-open:-scale-y-100 transition-transform" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</summary>
<div class="p-4">
Details content
</div>
</details><script setup lang="ts">
import { Details } from '@/components/details'
</script>
<template>
<Details class="group bg-body-secondary rounded-md">
<summary class="flex items-center gap-2 text-primary p-4">
<span class="x-title">Show more</span>
<svg class="size-4 group-open:-scale-y-100 transition-transform" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</summary>
<div class="p-4">
Details content
</div>
</Details>
</template>import { Details } from '@/components/details'
export function Example() {
return (
<Details className="group bg-body-secondary rounded-md">
<summary className="flex items-center gap-2 text-primary p-4">
<span className="x-title">Show more</span>
<svg className="size-4 group-open:-scale-y-100 transition-transform" fill="none" viewBox="0 0 24 24" strokeWidth="2.5" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</summary>
<div className="p-4">
Details content
</div>
</Details>
)
}Checkbox
You can also control details with a checkbox inside summary — only a tiny script is needed to sync the checkbox state. It's provided by the toggleDetails helper and wired up by the winduum-elements, winduum-stimulus, winduum-vue and winduum-react integrations below.
<details class="x-details group bg-body-secondary p-4 rounded-md" is="x-details">
<summary class="w-fit flex">
<label class="x-check">
<input type="checkbox" autocomplete="off">
Fill more
</label>
</summary>
<div class="x-control max-w-96 mt-4">
<input>
</div>
</details><details class="x-details group bg-body-secondary p-4 rounded-md" data-controller="x-details">
<summary class="w-fit flex">
<label class="x-check">
<input type="checkbox" autocomplete="off" data-action="change->x-details#toggleDetails">
Fill more
</label>
</summary>
<div class="x-control max-w-96 mt-4">
<input>
</div>
</details><script setup lang="ts">
import { Details } from '@/components/details'
</script>
<template>
<Details class="group bg-body-secondary p-4 rounded-md">
<summary class="w-fit flex">
<label class="x-check">
<input type="checkbox" autocomplete="off">
Fill more
</label>
</summary>
<div class="x-control max-w-96 mt-4">
<input>
</div>
</Details>
</template>import { Details } from '@/components/details'
export function Example() {
return (
<Details className="group bg-body-secondary p-4 rounded-md">
<summary className="w-fit flex">
<label className="x-check">
<input type="checkbox" autoComplete="off" />
Fill more
</label>
</summary>
<div className="x-control max-w-96 mt-4">
<input />
</div>
</Details>
)
}Accordion
Exclusive accordions use the native name attribute — details elements sharing the same name close each other automatically.
<details class="x-details group bg-body-secondary rounded-md" name="accordion" open>
<summary class="flex items-center gap-2 p-4 text-primary">
<span class="x-title">Accordion 1</span>
<svg class="size-4 group-open:-scale-y-100 transition-transform" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</summary>
<div class="p-4">
Details content
</div>
</details>
<details class="x-details group bg-body-secondary rounded" name="accordion">
<summary class="flex items-center gap-2 p-4 text-primary">
<span class="x-title">Accordion 2</span>
<svg class="size-4 group-open:-scale-y-100 transition-transform" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</summary>
<div>
<div class="p-4">
Details content
</div>
</div>
</details>
<details class="x-details group bg-body-secondary rounded" name="accordion">
<summary class="flex items-center gap-2 p-4 text-primary">
<span class="x-title">Accordion 3</span>
<svg class="size-4 group-open:-scale-y-100 transition-transform" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
</svg>
</summary>
<div>
<div class="p-4">
Details content
</div>
</div>
</details>JavaScript API
Low-level helper used by winduum-elements, winduum-stimulus, winduum-vue and winduum-react — you can use it to wire the checkbox sync manually or build your own integration.
import { toggleDetails } from 'winduum/src/components/details'
document.querySelectorAll('.x-details summary input[type="checkbox"]').forEach((inputElement) => {
inputElement.addEventListener('change', (event) => toggleDetails(event.target))
})toggleDetails
- Type:
(element: HTMLInputElement, options?: ToggleDetailsOptions) => void - Kind:
sync
Toggles the open attribute of the closest details element to match the checkbox checked state. Call it on the change event of a checkbox inside summary.
ToggleDetailsOptions
selector
- Type:
string - Default:
details