Skip to content
CodeAtlas UI

Surfaces

Accordion

Vertically stacked collapsible sections backed by Bits UI, with one or many items open at once.

<script>
  import { Accordion, AccordionItem } from "@codeatlasdev/ui";
</script>

<Accordion type="single">
  <AccordionItem value="a" title="Question">Answer</AccordionItem>
</Accordion>

Triggers are buttons with aria-expanded, and Arrow, Home and End keys move between them. With type="single" the bound value is a string, with type="multiple" it is a string array.

Single

Only one item is open at a time. Clicking the open item collapses it.

Code
svelte
<script lang="ts">
  import { Accordion, AccordionItem } from '@codeatlasdev/ui';
</script>

<div class="wrap">
  <Accordion type="single">
    <AccordionItem value="a1" title="What is Liquid Glass?">
      Liquid Glass is a design language that applies real-time backdrop blur, refraction and
      tinting to UI surfaces, creating depth without heavy visual weight.
    </AccordionItem>
    <AccordionItem value="a2" title="Which browsers support backdrop-filter?">
      All modern evergreen browsers. Older environments receive a fallback without the blur effect.
    </AccordionItem>
    <AccordionItem value="a3" title="Can I nest GlassSurface inside GlassCard?">
      Yes. Both components use isolation: isolate to keep stacking contexts correct.
    </AccordionItem>
  </Accordion>
</div>

<style>
  .wrap { width: 100%; max-width: 560px; }
</style>

Multiple

Several items can be open at once.

Code
svelte
<script lang="ts">
  import { Accordion, AccordionItem } from '@codeatlasdev/ui';
</script>

<div class="wrap">
  <Accordion type="multiple">
    <AccordionItem value="b1" title="Svelte 5 runes">
      Runes replace reactive declarations with explicit $state(), $derived() and $effect().
    </AccordionItem>
    <AccordionItem value="b2" title="Bits UI">
      Bits UI provides unstyled, accessible headless primitives for Svelte, with WAI-ARIA
      patterns built in.
    </AccordionItem>
    <AccordionItem value="b3" title="CSS custom properties">
      All --ca-* tokens are set in global.css and cascade into every component without runtime
      overhead.
    </AccordionItem>
  </Accordion>
</div>

<style>
  .wrap { width: 100%; max-width: 560px; }
</style>

Controlled

Bind `value` to read or set the open item.

Opened from the bound value.

Open item: c1

Code
svelte
<script lang="ts">
  import { Accordion, AccordionItem } from '@codeatlasdev/ui';

  let value = $state<string | string[] | undefined>('c1');
</script>

<div class="wrap">
  <Accordion type="single" bind:value>
    <AccordionItem value="c1" title="First section">Opened from the bound value.</AccordionItem>
    <AccordionItem value="c2" title="Second section">Opening this one closes the first.</AccordionItem>
  </Accordion>
  <p>Open item: {Array.isArray(value) ? value.join(', ') : (value ?? 'none')}</p>
</div>

<style>
  .wrap { width: 100%; max-width: 560px; display: flex; flex-direction: column; gap: var(--ca-space-3); }
  p { margin: 0; font-size: var(--ca-font-size-body2); color: var(--ca-text-secondary); }
</style>

Accordion props

PropTypeDefaultDescription
type'single' | 'multiple''single'Whether one or many items can be open.
valuestring | string[]undefinedOpen item value(s). Bindable.
onValueChange(value: string | string[]) => voidundefinedCalled when the open items change.
classstring''Extra class names on the root.
childrenSnippetundefined`AccordionItem` children.

AccordionItem props

PropTypeDefaultDescription
valuestring–Unique key of the item. Required.
titlestring–Trigger label. Required.
classstring''Extra class names.
childrenSnippetundefinedBody shown when expanded.