Accordion
SvAccordion: collapsible sections with single- or multiple-expand, roving header focus (Up/Down/Home/End) and full WAI-ARIA (region + aria-controls). The panel body is a snippet; RTL mirrors the chevron and layout.
A live, editable Svelte 5 component example from the SvGrid gallery (Layout). Read the SvGrid UI component docs for the full API.
What this example shows
SvAccordion - collapsible sections with single- or multiple-expand, roving header focus (Up/Down/Home/End) and full WAI-ARIA. The panel body is a snippet that receives the item. RTL mirrors the chevron + layout.
Imports, features and API used
Imports: @svgrid/grid
Source code (285-accordion.svelte)
<script lang="ts">
/**
* SvAccordion - collapsible sections with single- or multiple-expand, roving
* header focus (Up/Down/Home/End) and full WAI-ARIA. The panel body is a
* snippet that receives the item. RTL mirrors the chevron + layout.
*/
import { SvAccordion } from '@svgrid/grid'
import type { AccordionItem } from '@svgrid/grid'
const faq: AccordionItem[] = [
{ id: 'ship', label: 'How does shipping work?' },
{ id: 'returns', label: 'What is your return policy?' },
{ id: 'warranty', label: 'Is there a warranty?' },
]
const bodies: Record<string, string> = {
ship: 'Orders ship within 2 business days. Tracking is emailed the moment your parcel leaves the warehouse.',
returns: 'Return anything within 30 days for a full refund - no questions asked. We even cover the return label.',
warranty: 'Every product carries a 2-year limited warranty against manufacturing defects.',
}
let single = $state<string[]>(['ship'])
let multi = $state<string[]>(['ship', 'warranty'])
let rtl = $state(false)
</script>
<div class="wrap">
<header>
<h2>Accordion</h2>
<p>Collapsible sections. <code>expandMode="single"</code> keeps one panel open (FAQ style); <code>"multiple"</code> lets several stay open. Arrow keys move between headers.</p>
<label class="rtl-toggle"><input type="checkbox" bind:checked={rtl} /> Right-to-left</label>
</header>
<div class="cols">
<section>
<h3>Single (FAQ)</h3>
<SvAccordion items={faq} expanded={single} expandMode="single" dir={rtl ? 'rtl' : undefined} onChange={(ids) => (single = ids)}>
{#snippet panel(item)}
<p>{bodies[item.id]}</p>
{/snippet}
</SvAccordion>
</section>
<section>
<h3>Multiple</h3>
<SvAccordion items={faq} expanded={multi} expandMode="multiple" dir={rtl ? 'rtl' : undefined} onChange={(ids) => (multi = ids)}>
{#snippet panel(item)}
<p>{bodies[item.id]}</p>
{/snippet}
</SvAccordion>
<p class="out">Open: <strong>{multi.length ? multi.join(', ') : 'none'}</strong></p>
</section>
</div>
</div>
<style>
.wrap { padding: 20px; max-width: 860px; display: flex; flex-direction: column; gap: 18px; }
header h2 { margin: 0 0 4px; font-size: 20px; font-weight: 700; }
header p { margin: 0; color: var(--sg-muted, #64748b); font-size: 13.5px; line-height: 1.5; max-width: 640px; }
code { background: var(--sg-row-hover-bg, #eef2ff); padding: 1px 5px; border-radius: 5px; font-size: 12px; }
.rtl-toggle { display: inline-flex; align-items: center; gap: 6px; margin-top: 12px; font-size: 13px; font-weight: 600; color: var(--sg-muted, #64748b); }
.cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; align-items: start; }
section h3 { margin: 0 0 10px; font-size: 13px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--sg-muted, #64748b); }
section :global(.sv-acc__body p) { margin: 0; }
.out { margin: 12px 0 0; font-size: 13px; color: var(--sg-muted, #64748b); }
</style>Related documentation
Related articles
- Avoiding Layout Thrash in Custom Grid Cells - Layout thrash from interleaved DOM reads and writes is the most common cause of scroll jank in grids with custom cells - here is how to find it and design your way out of it.
- Column Resizing and Reordering - Let Users Shape the Grid - How to wire drag-to-resize and drag-to-reorder in SvGrid, then persist the layout to localStorage so it survives page reloads.
More Layout examples
- Account & security settings console - A real SaaS settings surface composed from the UI kit: SvMenubar app bar, promise + Undo-action toasts on save, SvPopconfirm on destructive rows, SvHoverCard teammate previews, and frame input adornments (leading icons, prefix affixes, masked API key). Profile / Team / Security tabs over SvCard + SvStat.
- Invoice builder - An adornment-heavy money form: currency prefixes, % suffixes, masked tax IDs (frame adornments), line items with SvPopconfirm delete + Undo action toasts, live SvStat totals, an SvHoverCard tax hint, and a promise toast on Send. Pure UI-kit composition.
- Operations KPI dashboard - A KPI console: SvStat + SvSparkline tiles, an SvGauge SLA dial, SvHoverCard drill-down previews per service, an SvMenubar toolbar (View / Range / Actions) and a promise toast on Refresh. Pure UI-kit composition, no grid dependency.
- Form: rich field types - SvForm reaching the whole input suite from one schema - phone, country, mask, combobox, radio, slider, tags, datetime and file - plus per-field help text, a readonly field, column span, and a promise toast on submit.
- Form: cascading fields - SvForm dependent selects - a child list derives from the parent value via a function `options`, and `dependsOn` clears the child when the parent changes so a stale selection never lingers. Country -> State -> City.