Data Display

Accordion

Expandable content panels. Supports single or multiple expansion, icons, disabled items, and custom content via snippets.

Playground

Experiment with different props in real-time.

Basic Usage

Pass an array of items with label and content.

<script lang="ts">
  import { Accordion } from 'sv5ui';

  const items = [
    { label: 'What is sv5ui?', content: 'A modern Svelte 5 UI component library.' },
    { label: 'Is it free?', content: 'Yes, sv5ui is open source and free to use.' },
    { label: 'How do I install it?', content: 'Run npm install sv5ui in your project.' }
  ];
</script>

<Accordion {items} />

Multiple

Allow multiple items to be expanded simultaneously.

<Accordion type="multiple" {items} />

With Icons

Add leading icons to each item.

<Accordion items={[
  { label: 'Account', icon: 'lucide:user', content: 'Manage your account settings.' },
  { label: 'Notifications', icon: 'lucide:bell', content: 'Configure notification preferences.' },
  { label: 'Security', icon: 'lucide:shield', content: 'Update your security settings.' }
]} />

Disabled Items

Disable individual items to prevent expansion.

<Accordion items={[
  { label: 'Available', content: 'This item can be expanded.' },
  { label: 'Disabled', content: 'Cannot expand.', disabled: true },
  { label: 'Also Available', content: 'This item can be expanded too.' }
]} />

Disabled (Global)

Disable the entire accordion to prevent any item from being expanded.

<!-- Disable the entire accordion -->
<Accordion disabled items={[
  { label: 'Item 1', content: 'All items are disabled.' },
  { label: 'Item 2', content: 'None can be expanded.' },
  { label: 'Item 3', content: 'The entire accordion is disabled.' }
]} />

Default Open

Set an item to be expanded by default with the value prop.

Open by default.
<Accordion value="1" items={[
  { label: 'First', content: 'Closed by default.', value: '0' },
  { label: 'Second', content: 'Open by default.', value: '1' },
  { label: 'Third', content: 'Closed by default.', value: '2' }
]} />

Custom Trailing Icon

Replace the default chevron with a custom icon.

<Accordion trailingIcon="lucide:plus" items={[
  { label: 'Question 1', content: 'Answer to question 1.' },
  { label: 'Question 2', content: 'Answer to question 2.' }
]} />

Per-Item Trailing Icon

Override the trailing icon on individual items.

<Accordion items={[
  { label: 'Download', trailingIcon: 'lucide:download', content: 'Download the latest version.' },
  { label: 'Settings', trailingIcon: 'lucide:settings', content: 'Configure your preferences.' },
  { label: 'Default Icon', content: 'Uses the default chevron icon.' }
]} />

Keyboard Loop

Enable loop to cycle focus from the last item back to the first when navigating with keyboard arrows.

<!-- Focus cycles from last to first item with arrow keys -->
<Accordion loop {items} />

Custom Snippets

Use snippets to fully customize trigger and content rendering.

<Accordion {items}>
  {#snippet label({ item, open })}
    <div class="flex flex-col">
      <span class="font-semibold">{item.label}</span>
      <span class="text-on-surface/50 text-xs">
        {open ? 'Click to collapse' : 'Click to expand'}
      </span>
    </div>
  {/snippet}

  {#snippet trailing({ open })}
    <Icon name={open ? 'lucide:minus' : 'lucide:plus'} class="size-4 text-primary" />
  {/snippet}

  {#snippet body({ item })}
    <div class="flex items-start gap-3">
      <Icon name="lucide:check" class="mt-0.5 size-4 text-success" />
      <p class="text-sm">{item.content}</p>
    </div>
  {/snippet}
</Accordion>

UI Slots

Use the ui prop to override classes on internal elements.

SlotDescription
rootRoot accordion container
itemIndividual item container with border
headerHeader flex wrapper
triggerClickable trigger button
contentAnimated content wrapper
bodyBody text content
leadingIconLeading icon element
trailingIconTrailing icon element (chevron)
labelLabel text element

Snippets

NamePropsDescription
leading{ item, index, open }Custom leading section
label{ item, index, open }Custom label content
trailing{ item, index, open }Custom trailing section
content{ item, index, open }Custom entire content area
body{ item, index, open }Custom body inside default wrapper

Props

PropTypeDefault
itemsAccordionItem[]-
type'single' | 'multiple''single'
valuestring | string[]-
onValueChange(value: string | string[]) => void-
trailingIconstring'lucide:chevron-down'
loopbooleanfalse
disabledbooleanfalse
orientation'vertical' | 'horizontal''vertical'
forceMountbooleanfalse
classstring-
uiRecord<Slot, Class>-

Item Props

PropTypeDefault
labelstring-
iconstring-
trailingIconstring-
contentstring-
valuestringindex
disabledbooleanfalse
classstring-
uiRecord<Slot, Class>-