Accordion
Collapsible content sections with an expand/collapse animation, one or several open at a time.
Playground
Design tokens are named values — colors, spacing, radii — that form the single source of truth for your design system.
Semantic tokens map to foundation tokens. Swap the foundation layer and the entire UI updates automatically.
Yes — semantic tokens handle dark mode via the CSS light-dark() function. No manual dark: classes needed.
<Accordion>
<AccordionItem value="item-1" title="Section One">
Content for the first section.
</AccordionItem>
<AccordionItem value="item-2" title="Section Two">
Content for the second section.
</AccordionItem>
<AccordionItem value="item-3" title="Section Three">
Content for the third section.
</AccordionItem>
</Accordion>01 Examples
Each AccordionItem takes a value that identifies it, a title for its header, and its
panel content as children.
FAQ Section
Frequently Asked Questions
Everything you need to know to get started.
Basic Svelte knowledge helps, but our components are designed with simple, declarative APIs. If you can write HTML and pass props, you're good to go. Check the Getting Started guide for a gentle introduction.
We use a 3-layer token system: foundation, semantic, and interaction tokens. Dark
mode is handled automatically via light-dark(). No manual dark: classes needed.
Absolutely. Every component is tree-shakeable. Import only what you need and your bundle stays lean.
Yes. All components follow WAI-ARIA patterns, support keyboard navigation, and
include proper focus management. We test with screen readers and respect prefers-reduced-motion.
<div
class="bg-surface-elevated border-border-subtle w-full overflow-hidden rounded-2xl border"
>
<div class="border-border-subtle border-b px-6 py-4">
<h3 class="text-text-primary font-semibold">Frequently Asked Questions</h3>
<p class="text-text-tertiary mt-0.5 text-sm">
Everything you need to know to get started.
</p>
</div>
<div class="px-6 py-2">
<Accordion defaultValue="faq-1">
<AccordionItem value="faq-1" title="Do I need to know Svelte to use this?">
<p class="text-text-secondary text-sm leading-relaxed">
Basic Svelte knowledge helps, but our components are designed with simple,
declarative APIs. If you can write HTML and pass props, you're good to go. Check the <a
href={resolve('/getting-started')}
class="text-primary underline">Getting Started guide</a
> for a gentle introduction.
</p>
</AccordionItem>
<AccordionItem value="faq-2" title="How does dark mode work?">
<p class="text-text-secondary text-sm leading-relaxed">
We use a 3-layer token system: foundation, semantic, and interaction tokens. Dark
mode is handled automatically via <code
class="bg-surface-base rounded px-1.5 py-0.5 text-xs">light-dark()</code
>. No manual
<code class="bg-surface-base rounded px-1.5 py-0.5 text-xs">dark:</code> classes needed.
</p>
</AccordionItem>
<AccordionItem value="faq-3" title="Can I use only some components?">
<p class="text-text-secondary text-sm leading-relaxed">
Absolutely. Every component is tree-shakeable. Import only what you need and your
bundle stays lean.
</p>
</AccordionItem>
<AccordionItem value="faq-4" title="Is it accessible?">
<p class="text-text-secondary text-sm leading-relaxed">
Yes. All components follow WAI-ARIA patterns, support keyboard navigation, and
include proper focus management. We test with screen readers and respect <code
class="bg-surface-base rounded px-1.5 py-0.5 text-xs">prefers-reduced-motion</code
>.
</p>
</AccordionItem>
</Accordion>
</div>
</div>Controlled State
<div class="flex w-full flex-col gap-4">
<div class="flex items-center gap-2">
<span class="text-text-tertiary text-xs font-medium">Open:</span>
<Badge size="xs" intent="primary" variant="soft">{faqValue || '(none)'}</Badge>
</div>
<Accordion variant="card" bind:value={faqValue}>
<AccordionItem value="what-is" title="What is Urbicon UI?">
A Svelte 5 component library with built-in i18n, semantic design tokens, and zero-config
dark mode.
</AccordionItem>
<AccordionItem value="pricing" title="Is it free?">
Yes. Urbicon UI is free and open-source under the MIT license.
</AccordionItem>
<AccordionItem value="support" title="Where do I get help?">
Check the documentation, open a GitHub issue, or join the community Discord.
</AccordionItem>
</Accordion>
</div>Several panels open
<Accordion type="multiple" variant="card" defaultValue={['shipping', 'items']}>
<AccordionItem value="items" title="Items (2)">
Two products, shipped together in one parcel.
</AccordionItem>
<AccordionItem value="shipping" title="Shipping address">
Ada Lovelace, 12 Analytical Ave, London.
</AccordionItem>
<AccordionItem value="payment" title="Payment">
Visa ending 4242, billed monthly.
</AccordionItem>
</Accordion>Custom Trigger
Includes community support, basic components, and public repos only.
Priority support, private repos, advanced theming, and early access to new components.
<Accordion variant="card" defaultValue="pro">
<AccordionItem value="free">
{#snippet trigger({ open: _open })}
<div class="flex w-full items-center gap-3">
<div
class="bg-surface-hover text-text-secondary rounded-modify flex size-8 items-center justify-center"
>
<GiftIcon size={16} />
</div>
<div class="flex-1 text-left">
<p class="text-text-primary text-sm font-semibold">Free Plan</p>
<p class="text-text-tertiary text-xs">Up to 3 projects</p>
</div>
<Badge size="xs" intent="neutral" variant="soft">$0/mo</Badge>
</div>
{/snippet}
<p class="text-text-secondary text-sm">
Includes community support, basic components, and public repos only.
</p>
</AccordionItem>
<AccordionItem value="pro">
{#snippet trigger({ open: _open })}
<div class="flex w-full items-center gap-3">
<div
class="bg-primary/10 text-primary rounded-modify flex size-8 items-center justify-center"
>
<ZapIcon size={16} />
</div>
<div class="flex-1 text-left">
<p class="text-text-primary text-sm font-semibold">Pro Plan</p>
<p class="text-text-tertiary text-xs">Unlimited projects</p>
</div>
<Badge size="xs" intent="primary" variant="filled">$29/mo</Badge>
</div>
{/snippet}
<p class="text-text-secondary text-sm">
Priority support, private repos, advanced theming, and early access to new components.
</p>
</AccordionItem>
</Accordion>02 Accordion or Collapsible
Accordion vs Collapsible
Single panel → Collapsible
Use Collapsible when you
need a single panel that manages its own state. No context, no coordination, just expand and
collapse.
Multi-panel → Accordion
<div class="flex w-full max-w-lg flex-col gap-2.5">
<p class="text-text-tertiary text-xs font-medium tracking-wider uppercase">
Single panel → Collapsible
</p>
<Collapsible variant="card" title="Standalone expand/collapse" defaultOpen>
<p class="text-text-secondary text-sm">
Use <code class="bg-surface-base rounded px-1.5 py-0.5 text-xs">Collapsible</code> when you
need a single panel that manages its own state. No context, no coordination, just expand and
collapse.
</p>
</Collapsible>
</div>
<div class="flex w-full max-w-lg flex-col gap-2.5">
<p class="text-text-tertiary text-xs font-medium tracking-wider uppercase">
Multi-panel → Accordion
</p>
<Accordion variant="card" defaultValue="a1">
<AccordionItem value="a1" title="Coordinated panel A">
Opening this closes panel B. Accordion coordinates multiple Collapsible panels via a
shared context.
</AccordionItem>
<AccordionItem value="a2" title="Coordinated panel B">
Single, multiple and non-collapsible modes, all managed by the Accordion wrapper.
</AccordionItem>
</Accordion>
</div>See the Collapsible page for that standalone case.
03 Customization
One provider default
<BlocksProvider
defaults={{
AccordionItem: {
slotClasses: {
item: 'border border-primary/40 bg-primary/10',
chevron: 'text-primary'
}
}
}}
>
<Accordion variant="card" defaultValue="brand-1">
<AccordionItem value="brand-1" title="How is this styled?">
A single provider default paints every item from one place.
</AccordionItem>
<AccordionItem value="brand-2" title="Does the behaviour survive?">
Yes. Only the surface tint, border and accent colour change.
</AccordionItem>
</Accordion>
</BlocksProvider>This is one of five ways to restyle a block. See Customization for class, slotClasses, unstyled, preset and provider-level overrides.
04 Accessibility
Built-in ARIA
Each trigger uses aria-expanded and aria-controls to link to its content panel. Content
panels have role="region" with aria-labelledby pointing back to the trigger. The data-state attribute exposes open / closed for CSS-only styling.
Keyboard Navigation
Tab moves focus between triggers. Enter / Space toggle the focused item. Focus rings use focus-visible: so they only appear on keyboard navigation,
never on mouse clicks.
Disabled State
Set disabled on an AccordionItem to give its trigger the native disabled attribute, which removes it from the tab order
and blocks activation.
Reduced Motion
When prefers-reduced-motion is set, panels open and close
without animating.
05 API Reference
18 propsProp | Type | Default | Description | |
|---|---|---|---|---|
children required | Snippet | — | Accordion items | |
class | string | — | Custom CSS class | |
collapsible | boolean | true | Whether items can be fully collapsed | |
defaultValue | string | string[] | — | Default open item(s) | |
disabled | boolean | false | Disable all items | |
expanded variant | falsetrue | — | Controls the expanded behavior and appearance of the Accordion component. Available options: false, true. | |
onValueChange | (value: string | string[]) => void | — | Callback when open items change | |
preset | string | — | Apply a named preset registered via <BlocksProvider presets={{ Accordion: {...} }}>.
Prefer this over class overrides when the requested look falls outside the
semantic intent palette — presets keep hover/active/dark-mode logic coherent
and make the custom look reusable across the project. | |
size | smmdlg | 'md' | Size | |
slotClasses | Partial<Record<AccordionSlots, string>> | — | Per-slot class overrides, accordion-wide: the item slots (item | trigger | chevron | content | contentInner) apply to every AccordionItem; an item's own slotClasses win their bucket. Slots: base | item | trigger | chevron | content | contentInner | |
transitionDuration | number | — | Override every item's expand/collapse animation duration in milliseconds. Defaults to the
--blocks-collapse-duration token (the normal 250ms). Respects prefers-reduced-motion. | |
transitionEasing | string | — | Override every item's expand/collapse easing as a CSS <easing-function> — e.g.
'ease-in-out', 'cubic-bezier(0.4,0,0.2,1)', or a token like 'var(--blocks-ease-springy)'.
Defaults to the --blocks-collapse-easing token. (A CSS string, not the (t) => number
easing function the overlay components take — Accordion animates via CSS.) | |
type | singlemultiple | 'single' | Allow single or multiple items open at once | |
unstyled | boolean | — | Remove default styles | |
value | string | string[] | — | Controlled open item(s) – string for single, string[] for multiple | |
variant | defaultcardghost | 'default' | Visual style | |
...AccordionVariants variant | VariantProps | — | Styling variants from AccordionVariants | |
...HTMLAttributes<HTMLDivElement> inherited | HTMLAttributes | — | HTML attributes (excluding: 'children') |
06 Types
Local type definitions used by this component.
Name | Kind | Category | Used by | Description | |
|---|---|---|---|---|---|
AccordionContext | interface | helper | 0 | Context for Accordion ↔ AccordionItem communication | |
AccordionProps | interface | props | 0 | Props interface for Accordion component | |
AccordionItemProps | interface | props | 0 | Props interface for AccordionItem component | |
AccordionVariants | type | variant | 1 | — | |
AccordionSlots | type | variant | 0 | Slot names derived from the tv() config — single source of truth for slotClasses. |
07 Installation
Import
import { Accordion, AccordionItem } from '@urbicon-ui/blocks';