Accordion
Collapsible sections. Single-open by default (an FAQ), or type="multiple" to allow several at once. bordered (one panel) or separated (gapped cards). The panel animates open with a grid-template-rows transition — no fixed heights.
bash
jlds add accordionUsage
html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/accordion.css">
<!-- behavior layer: open/close on click -->
<script src="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/js/core.js" defer></script>
<script src="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/js/accordion.js" defer></script>
<div class="jl-accordion jl-accordion--bordered">
<div class="jl-acc-item" data-open="true">
<h3 style="margin:0">
<button type="button" class="jl-acc-trigger" aria-expanded="true" aria-controls="a1">
<span class="jl-acc-trigger__label">What is JLDS?</span>
<span class="jl-acc-trigger__chevron"><svg viewBox="0 0 24 24" fill="none"><path d="m6 9 6 6 6-6" stroke="currentColor" stroke-width="1.85" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</button>
</h3>
<div class="jl-acc-region" id="a1" role="region">
<div class="jl-acc-content"><div class="jl-acc-content__inner">A component CLI — you own the code.</div></div>
</div>
</div>
<!-- more .jl-acc-item blocks -->
</div>vue
<script setup lang="ts">
import { Accordion, AccordionItem } from "@/components/ui/accordion"
</script>
<template>
<Accordion type="single" default-value="what">
<AccordionItem value="what" title="What is JLDS?">
A component CLI — you own the code.
</AccordionItem>
<AccordionItem value="how" title="How does it work?">
Run <code>jlds add <name></code> and the files land in your project.
</AccordionItem>
</Accordion>
</template>tsx
import { Accordion } from "@/components/ui/accordion"
<Accordion type="single" defaultValue="what">
<Accordion.Item value="what" title="What is JLDS?">
A component CLI — you own the code.
</Accordion.Item>
<Accordion.Item value="how" title="How does it work?">
Run <code>jlds add <name></code> and the files land in your project.
</Accordion.Item>
</Accordion>Multiple open
Set type="multiple" (React/Vue) or data-type="multiple" on the container (HTML) to let several panels stay open.
html
<div class="jl-accordion jl-accordion--bordered" data-type="multiple">
<!-- items … -->
</div>vue
<template>
<Accordion type="multiple" :default-value="['a', 'b']">
<AccordionItem value="a" title="First">…</AccordionItem>
<AccordionItem value="b" title="Second">…</AccordionItem>
</Accordion>
</template>tsx
<Accordion type="multiple" defaultValue={["a", "b"]}>
<Accordion.Item value="a" title="First">…</Accordion.Item>
<Accordion.Item value="b" title="Second">…</Accordion.Item>
</Accordion>Separated
variant="separated" renders each item as its own gapped card.
html
<div class="jl-accordion jl-accordion--separated">
<!-- items … -->
</div>vue
<template>
<Accordion variant="separated">…</Accordion>
</template>tsx
<Accordion variant="separated">…</Accordion>Props
React
Accordion extends React.HTMLAttributes<HTMLDivElement>.
| Prop | Type | Default | Description |
|---|---|---|---|
type | "single" | "multiple" | "single" | One or several panels open |
variant | "bordered" | "separated" | "bordered" | Visual treatment |
defaultValue | string | string[] | — | Initially-open item value(s) |
Accordion.Item props: value (stable id), title (header), icon, disabled.
Vue
Same options. Accordion + AccordionItem (each item needs a value); pass the header via the title prop and an optional icon slot.
CSS classes (HTML)
| Class | Purpose |
|---|---|
.jl-accordion + --bordered / --separated | Container and variant |
[data-type="multiple"] | On the container: allow several open |
.jl-acc-item + [data-open="true"] | A section and its open state |
.jl-acc-trigger + __label / __icon / __chevron | The header button parts |
.jl-acc-region / .jl-acc-content / __inner | The animated collapsible panel |