Skip to content

List

import { List, ListItem } from '@delightstack/components';
<List>
<ListItem onclick={() => console.log('clicked')}>Action Item</ListItem>
<ListItem onclick={() => console.log('clicked')}>Another Action</ListItem>
</List>

The list is transparent by default, so it composes onto any surface (a card, a sidebar, a popover) without imposing its own. Add filled for a subtle surface or outline for a bordered card — both restore the visible rounded corners, and the two can be combined. The item hover/active highlights stay rounded in every mode.

Plain (default)

Filled

Outline

View code
<!-- transparent by default -->
<List>
<ListItem>Profile</ListItem>
<ListItem>Settings</ListItem>
<ListItem>Sign out</ListItem>
</List>
<!-- subtle filled surface -->
<List filled></List>
<!-- bordered card -->
<List outline></List>
<!-- combine for a filled, bordered card -->
<List filled outline></List>

Single-select mode using radio buttons. Bind value to track the selected index.

View code
<script>
import { List, ListItem } from '@delightstack/components';
let selected = $state<number[]>([]);
</script>
<List type="radio" bind:value={selected}>
<ListItem>Small</ListItem>
<ListItem>Medium</ListItem>
<ListItem>Large</ListItem>
</List>

Multiple-select mode using checkboxes. The value array contains all selected indices.

View code
<script>
import { List, ListItem } from '@delightstack/components';
let selected = $state<number[]>([]);
</script>
<List type="checkbox" bind:value={selected}>
<ListItem>Notifications</ListItem>
<ListItem>Email Updates</ListItem>
<ListItem>SMS Alerts</ListItem>
</List>

The same multi-select behavior as checkbox, rendered with toggle switches — a natural fit for settings lists.

View code
<script>
import { List, ListItem } from '@delightstack/components';
let selected = $state<number[]>([]);
</script>
<List type="toggle" bind:value={selected}>
<ListItem>Wi-Fi</ListItem>
<ListItem>Bluetooth</ListItem>
<ListItem>Airplane Mode</ListItem>
</List>

dense tightens the rows (great for action menus); comfortable relaxes them. The default sits between the two and lines up with the standard control height.

Dense

Default

Comfortable

View code
<!-- compact -->
<List dense>
<ListItem onclick={() => handleEdit()}>Edit</ListItem>
<ListItem onclick={() => handleDuplicate()}>Duplicate</ListItem>
<ListItem onclick={() => handleDelete()}>Delete</ListItem>
</List>
<!-- default -->
<List></List>
<!-- relaxed -->
<List comfortable></List>

Display-only list with no hover effects or click handlers.

  • Read-only item
  • Another item
View code
<List type="text">
<ListItem>Read-only item</ListItem>
<ListItem>Another item</ListItem>
</List>
View code
<List skeleton={loading} skeleton_count={3}></List>
PropTypeDefaultDescription
type'button' | 'text' | 'radio' | 'checkbox' | 'toggle''button'Interaction mode for items
valuenumber[][]Selected item indices (bindable)
densebooleanfalseCompact spacing
comfortablebooleanfalseRelaxed spacing
filledbooleanfalseRender on a subtle filled surface with rounded corners
outlinebooleanfalseRender with a 1px border + rounded corners (transparent fill); combine with filled for a card
disabledbooleanfalseDisable all items
touchedbooleanfalseWhether the user has interacted (bindable)
padding_xstring-Horizontal padding override (e.g. '16px')
padding_ystring-Vertical padding override (e.g. '16px')
skeletonbooleanfalseShow loading skeleton items
skeleton_countnumber5Number of skeleton items to show
idstringautoElement ID
classstring''Additional CSS classes
stylestring''Additional inline styles
childrenSnippet-ListItem children
EventDetailDescription
ontouch() => voidCalled when the first interaction occurs
onchange(value: number[]) => voidCalled when selection changes

The List component exports a ListContext interface used for parent-child communication via Svelte context:

interface ListContext {
type: 'button' | 'text' | 'radio' | 'checkbox' | 'toggle';
value: number[];
dense: boolean;
comfortable: boolean;
disabled: boolean;
level: number;
id: string;
}
  • Renders as a <ul> element with proper list semantics
  • aria-selected applied on items in selection modes
  • Full keyboard navigation: Arrow Up/Down to move focus, Home/End to jump, Space/Enter to activate
  • Focus management tracked via the onFocusWithin utility attachment
  • Disabled state communicated to assistive technology
  • Nested lists inherit parent context with incremented level