Skip to content

Accordion

import { Accordion, AccordionItem } from '@delightstack/components';
Getting Started

Getting started is easy! Create an account and follow the onboarding steps.

We accept all major credit cards, PayPal, and bank transfers.

Reach our support team via email or through the in-app chat.

View code
<script>
import { Accordion, AccordionItem } from '@delightstack/components';
let openSection = $state('faq-1');
</script>
<Accordion bind:value={openSection}>
<AccordionItem value="faq-1" title="Getting Started">
<p>Getting started is easy! Create an account and follow the onboarding steps.</p>
</AccordionItem>
<AccordionItem value="faq-2" title="Payment Methods">
<p>We accept all major credit cards, PayPal, and bank transfers.</p>
</AccordionItem>
<AccordionItem value="faq-3" title="Contact Support">
<p>Reach our support team via email or through the in-app chat.</p>
</AccordionItem>
</Accordion>

By default an accordion is borderless — just a subtle hairline between items (and none after the last one), with items sitting flush against each other. Add filled to join the items into one tinted surface, or outline to wrap the whole set in a single bordered, rounded frame. Corners follow the library’s squircle treatment.

filled and outline are independent, so you can combine them for a framed set of filled items.

Default

Hairline separators

The default keeps a subtle line between each item and nothing else.

Items touch by default — opening one doesn't push the others away.

The last item never draws a bottom separator.

Filled

Tinted block

Items join into one tinted surface with squircle-rounded ends.

Every item shares the same subtle tint, open or closed.

Corners use the same squircle treatment as the rest of the library.

Outline

One framed group

A single bordered, rounded frame wraps the whole set.

Items are divided by hairlines inside the frame.

Only the group's outer corners round; the radius stays subtle.

View code
<!-- Default: hairline separators only -->
<Accordion value="a"></Accordion>
<!-- Filled: items join into one tinted surface -->
<Accordion filled value="a"></Accordion>
<!-- Outline: a single bordered, rounded frame -->
<Accordion outline value="a"></Accordion>

By default items stay connected. Add separated and the open item animates apart from the list, gaining a gap above and below so the active section reads as emphasised. With filled or outline this is especially nice: the single surface starts connected and splits into rounded pieces as an item opens — the item above rounds its bottom corners, the active item rounds all four, and the item below rounds its top corners. Closing the item glides everything back into one piece.

Outline + separated

While every item is closed the frame reads as one continuous outline.

Splits to its own piece

Open an item and it animates apart into its own rounded box — the item above rounds its bottom, this one rounds top and bottom, and the item below rounds its top.

Close it again and the pieces glide back into a single frame.

Filled + separated

Closed items sit flush as a single tinted surface.

Lifts out when open

The active item pulls away as its own fully rounded piece.

Filled and outline share the splitting behaviour; only the surface differs.

View code
<!-- Outline frame that splits apart on open -->
<Accordion outline separated value="b"></Accordion>
<!-- Filled surface that splits apart on open -->
<Accordion filled separated value="b"></Accordion>

Allow multiple sections to be expanded simultaneously. When multiple is true, value is an array of strings.

First Section

Content for the first section.

Content for the second section.

Content for the third section.

View code
<script>
let openSections = $state(['section-1']);
</script>
<Accordion multiple bind:value={openSections}>
<AccordionItem value="section-1" title="First Section">
<p>Content for the first section.</p>
</AccordionItem>
<AccordionItem value="section-2" title="Second Section">
<p>Content for the second section.</p>
</AccordionItem>
<AccordionItem value="section-3" title="Third Section">
<p>Content for the third section.</p>
</AccordionItem>
</Accordion>

Prevent all sections from being collapsed by setting collapsible to false.

Always Visible

At least one section is always open.

Click to switch which section is open.

View code
<Accordion collapsible={false} value="first">
<AccordionItem value="first" title="Always Visible">
<p>At least one section is always open.</p>
</AccordionItem>
<AccordionItem value="second" title="Another Section">
<p>Click to switch which section is open.</p>
</AccordionItem>
</Accordion>

Use the trigger snippet to replace the default title rendering with custom content.

Manage your name, avatar, and public profile information.

Advanced Settings

Configure advanced options like API keys, webhooks, and integrations.

Choose which notifications you receive and how they are delivered.

View code
<script>
import { Accordion, AccordionItem } from '@delightstack/components';
let value = $state('settings');
</script>
<Accordion bind:value>
<AccordionItem value="profile">
{#snippet trigger()}
<div style="display: flex; align-items: center; gap: 0.5rem;">
<UserIcon />
<span>Profile Settings</span>
</div>
{/snippet}
<p>Manage your name, avatar, and public profile information.</p>
</AccordionItem>
<AccordionItem value="settings">
{#snippet trigger()}
<div style="display: flex; align-items: center; gap: 0.5rem;">
<SettingsIcon />
<span>Advanced Settings</span>
</div>
{/snippet}
<p>Configure advanced options like API keys, webhooks, and integrations.</p>
</AccordionItem>
</Accordion>

Dense

Compact Item A

Less padding for dense layouts.

Tighter spacing between items.

Comfortable

Spacious Item A

More padding for a relaxed feel.

Extra breathing room between items.

View code
<!-- Compact spacing -->
<Accordion dense>
<AccordionItem value="a" title="Compact Item A">
<p>Less padding for dense layouts.</p>
</AccordionItem>
<AccordionItem value="b" title="Compact Item B">
<p>Tighter spacing between items.</p>
</AccordionItem>
</Accordion>
<!-- Relaxed spacing -->
<Accordion comfortable>
<AccordionItem value="a" title="Spacious Item A">
<p>More padding for a relaxed feel.</p>
</AccordionItem>
<AccordionItem value="b" title="Spacious Item B">
<p>Extra breathing room between items.</p>
</AccordionItem>
</Accordion>
View code
<Accordion skeleton={loading} skeleton_count={3}></Accordion>
Frontend Frameworks

A compiler-based framework that shifts work to build time for smaller, faster apps.

A library for building user interfaces with a virtual DOM and component model.

Popular choices include Node.js, Python, Go, and Rust.

View code
<script>
import { Accordion, AccordionItem } from '@delightstack/components';
let outerValue = $state('parent-1');
let innerValue = $state('');
</script>
<Accordion bind:value={outerValue}>
<AccordionItem value="parent-1" title="Frontend Frameworks">
<Accordion bind:value={innerValue}>
<AccordionItem value="child-1" title="Svelte">
<p>A compiler-based framework that shifts work to build time.</p>
</AccordionItem>
<AccordionItem value="child-2" title="React">
<p>A library for building user interfaces with a virtual DOM.</p>
</AccordionItem>
</Accordion>
</AccordionItem>
<AccordionItem value="parent-2" title="Backend Languages">
<p>Popular choices include Node.js, Python, Go, and Rust.</p>
</AccordionItem>
</Accordion>
PropTypeDefaultDescription
valuestring | string[]''Currently open item(s), bindable
multiplebooleanfalseAllow multiple panels open simultaneously
collapsiblebooleantrueAllow closing all items
disabledbooleanfalseDisable all items
densebooleanfalseCompact header/content padding
comfortablebooleanfalseRelaxed header/content padding
filledbooleanfalseJoin items into one subtly tinted, rounded surface
outlinebooleanfalseWrap the whole set in a single bordered, rounded (squircle) frame
separatedbooleanfalseAnimate the open item apart from the list; with filled/outline the surface splits into rounded pieces
skeletonbooleanfalseShow loading skeleton
skeleton_countnumber3Number of skeleton items to render
idstringautoElement ID
classstring''Additional CSS classes
childrenSnippet-AccordionItem children
PropTypeDefaultDescription
valuestringrequiredUnique identifier for this item
titlestring''Header text shown in the summary
disabledbooleanfalseDisable this individual item
triggerSnippet-Custom header content replacing title text
childrenSnippet-Panel content
  • Uses semantic <details>/<summary> elements for native accessibility
  • aria-expanded on each <summary> reflects its open/closed state
  • aria-controls links each <summary> to its content panel
  • role="region" on each content panel with aria-labelledby
  • Tab moves focus between summary elements
  • Arrow Down / Arrow Up moves focus to next/previous summary
  • Enter / Space toggles the focused item
  • Home moves focus to the first summary
  • End moves focus to the last summary
  • Disabled items are excluded from arrow key navigation
  • Respects prefers-reduced-motion for chevron transitions