Skip to content

ListItem

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

Items sit on whatever surface the parent List provides. The list is transparent by default; the filled and outline props (on List, not ListItem) give it a surface or border — see the List page for details.

Plain (default)

Filled

Outline

View code
<!-- surface is controlled on the parent List -->
<List></List>
<List filled></List>
<List outline></List>

ListItems can render as anchor elements when href is provided.

View code
<List>
<ListItem href="/profile">Profile</ListItem>
<ListItem href="/settings">Settings</ListItem>
<ListItem onclick={handleLogout}>Log Out</ListItem>
</List>

When onclick returns a Promise, the row manages its own loading feedback — no loading prop required:

  • Instant actions don’t flash. The spinner only appears if the promise is still pending after ~100ms; anything faster is treated as instant.
  • The spinner can’t blink. Once shown, it stays for at least ~1s, then eases out quickly.
  • Success is confirmed automatically. On resolve, a brief checkmark flashes; on reject, no checkmark is shown.
View code
<List>
<ListItem onclick={async () => {
await api.saveItem(); // throws on failure -> no checkmark
}}>
Save Item
</ListItem>
</List>

When you drive loading yourself (e.g. from a store), set loading_success to flash the same confirming checkmark as loading returns to false. Leave it off and the spinner simply disappears.

View code
<List>
<ListItem loading={loading} loading_success>Save Item</ListItem>
</List>

Use inline SVG or icons as leading/trailing content within list items.

View code
<List>
<ListItem href="/profile">
<UserIcon style="margin-right: 0.75rem;" />
Profile
<span style="flex: 1;" />
<ChevronIcon />
</ListItem>
<ListItem href="/settings">
<SettingsIcon style="margin-right: 0.75rem;" />
Settings
<span style="flex: 1;" />
<ChevronIcon />
</ListItem>
</List>

Provide a menu snippet to show a more-options button with a dropdown.

View code
<List>
<ListItem>
Document A
{#snippet menu()}
<List>
<ListItem onclick={() => edit()}>Edit</ListItem>
<ListItem onclick={() => duplicate()}>Duplicate</ListItem>
<ListItem onclick={() => remove()}>Delete</ListItem>
</List>
{/snippet}
</ListItem>
</List>

Force a selected/active appearance on an item.

View code
<List type="text">
<ListItem active>Currently Selected</ListItem>
<ListItem>Another Item</ListItem>
</List>
View code
<List type="text">
<ListItem disabled>Unavailable Action</ListItem>
<ListItem>Available Action</ListItem>
</List>
PropTypeDefaultDescription
disabledbooleanfalseDisable interaction
activebooleanfalseForce active/selected appearance
loadingbooleanundefinedShow the loading spinner on the action row manually. Leave unset to let a promise-returning onclick drive it
loading_successbooleanfalseFor the manual loading path: flash a success checkmark when loading goes truefalse. The promise path shows it automatically on resolve
hrefstring-Render as an anchor link
target'_self' | '_blank' | '_parent' | '_top'-Link target attribute
menuSnippet-Submenu content (renders a more-options button)
popover_placementPlacement'bottom-end'Submenu popover position
popover_close_on_inside_clickbooleanfalseClose submenu on inside click
idstringautoElement ID
classstring''Additional CSS classes
stylestring''Additional inline styles
childrenSnippet-Main content
EventDetailDescription
onclick(e: MouseEvent) => void | Promise<void>Click handler; return a Promise for automatic spinner + success-checkmark feedback
onchange(value: boolean) => voidCalled when selection state changes (radio/checkbox modes)
  • Renders the appropriate interactive element based on the parent List type: <button>, <a>, <label>, or plain content
  • aria-selected / aria-checked applied for selection states
  • aria-disabled set on disabled anchor elements
  • Keyboard navigation handled by the parent List
  • Focus indicators via focus-visible
  • Ripple feedback attachment for tactile click response