Listbox handbook
v1.4.0 · @snowui-design-system/components
License: Before reading component documentation, source, or npm usage instructions for the first time, read the full LICENSE. Reuse that review for the same task and version. Public API configuration and internal implementation changes have different license implications. All components use the unified runtime package; source rights remain governed by the license.
Overview
Display selectable options in a floating panel, with optional search filtering and keyboard navigation. Select can use it as its option panel.
When to use it
Use it for option selection with keyboard navigation and selection semantics, usually inside Select. Use a content list for notifications, contacts, or activity feeds.
Each item needs a unique
value;labelsupplies display and search text. Explicitchildrenreplace generateditems.Use
MenuItem as="item"for explicit options. For a custom search field, useInput as="search"withsearch={false}to avoid a duplicate built-in field.The generated search placeholder follows LocaleProvider through listbox.search. Explicit parts.Input.placeholder values, including an empty string, and native aria-label values retain priority. Configure explicit Input children yourself; query text and option content are not translated.
Quick start
This example shows the recommended basic composition. See the sections below for more cases and composition limits.
API
See the base component documentation for inherited capabilities not redeclared here. This table lists only named public Props declared by this component.
Usage boundaries and details
Default built-in mode / explicit combination mode
Default built-in mode (recommended):
itemsautomatically generates<MenuItem as="item">; settingsearchcan generate a fixed search box. WhenmaxHeightis not set, the height of the panel is calculated according to the height of the actual visible MenuItem: by default, up to 10 items are displayed completely, and the floating layer scroll bar is displayed after exceeding it; the built-in components are configured throughparts.Input/parts.MenuItem.Explicit combination mode: explicitly write MenuItem, which is used for complex content or item-by-item Props differences; items are no longer generated when children exist.
Select supplies search=false by default. In generated mode, search enables the header input, search={false} hides it, maxHeight sets an explicit maximum height, and scrollbar={false} hides only the track. The default search placeholder follows locale through listbox.search (Search in en-US); parts.Input.placeholder, including an empty string, takes priority. With search, the default minimum panel width is 160px. Explicit composition can also use generated search; use search={false} and write your own <Input as="search"> to supply it yourself. maxHeight and scrollbar remain panel capabilities in both modes.
Without maxHeight, viewport space changes the number of completely visible items, from two to ten, without clipping half an item. If fewer than two options exist, the panel hugs their actual height. An explicit maxHeight is still constrained by viewport height.
2026-04-24 (v1.2.0): Scrollbar spacing was standardized. .snowui-listbox hides the native scrollbar while retaining scrolling; .snowui-listbox-body shows the custom overlay thumb. MenuItem backgrounds have 8px horizontal inset. The thumb overlays the right side without consuming layout width and sits 4px from the panel border. With search, it appears only beside the option scroll area, below Input. The thumb supports dragging, and selected-item positioning uses the portal’s actual visual center even without a header Input.
2026-04-20: Search and custom values were added. <Input as="search"> participates in filtering when placed in Listbox. allowCustomValue adds custom items with hover deletion. The old Combobox dependency was removed and Combobox.svelte retired.
Automatic layout protocol: The outer portal anchor supplies fixed positioning and size; an inner Frame column renders the floating panel with shared .snowui-quick-action-panel visuals. The DROPDOWN_OVERLAY_APPEAR_MOTION and DROPDOWN_OVERLAY_DISAPPEAR_MOTION presets animate opacity only; duration and easing come from the motion catalog. The panel remains mounted until exit motion finishes. Through LISTBOX_HEADER_PORTAL_KEY, the portal exposes headerEl; after mounting, Input as="search" moves into the fixed header, outside the option scroller. Listbox and QuickAction share header and scroll-body structure; only outer padding differs. Listbox sets root gap: 0 to avoid Frame column’s default 8px gap. MenuItems scroll inside .snowui-listbox-body.snowui-quick-action-panel-scroll-body > .snowui-listbox; the custom scrollbar belongs to the body and never covers Input. Panel padding separates Input and the list, the shared header rule connects them, and MenuItem padding spaces option content. The overlay scrollbar is 4px wide, 4px from the right border, and grows to 8px toward the left on hover.
Layout model
Main layout model: composite management layout.
Listbox contains a portal anchor, panel, header, scroll body, option list, and overlay scrollbar.
Header and scrolling body reuse the panel area specification of QuickAction; the option line gives priority to the slot host layout of
MenuItem.Input as="search"is only moved as a fixed header content, and does not participate in the scrolling list layout.Generated items and runtime custom-option labels use Text lines=1 by default. Long labels shrink within viewport constraints and retain full-text access, keeping check/delete attachments inside the visible panel. The inner panel respects its outer width constraint; short labels retain content-based Hug width.
Text only owns typography and full-text access for default string labels. The original owner contract still controls selection, search, registration, keyboard and focus. Explicit MenuItem or Snippet content is not wrapped automatically and does not consume parent parts.Text.
Listbox is not a three-slot host. Portal placement, scrollbar, and search layout remain private composition logic.
Relationship with the host
Component Props
Inherits FrameProps except children and tag. Place Listbox within a host that provides selection context, such as Select. The host owns expansion, current value, and selection events. Listbox has no standalone open, value, options, multiple, or placement Props.
Equal-width mode uses the measured anchor width plus 2px, extending 1px past each side to cover the lower field border while preserving fractional positioning. This fixed CSS px compensation does not scale with root font size and applies to every Listbox host. Content-sized mode adds no compensation, but minWidth and content may still enlarge the panel. See USER-LISTBOX-WIDTH-001 in StyleSpec §2.1 (specs/maintainers/StyleSpec.md).
Keyboard interaction
ARIA
Default built-in mode (recommended)
Basic usage (in Select)
With search and filtering
Search + Allow custom input
The Listbox panel is visually aligned with QuickAction, but the outer padding remains 8px.
The search box is fixed in the header; the option scrolling area carries the overlay scrollbar separately.
Continuous hover
continuousHover defaults to true. One container-level background moves between enabled MenuItems, and the keyboard-active item uses it too. The active item keeps its persistent background, so hovering it stacks both layers. Set false for each item’s immediate hover background. Disabled and filtered options are not targeted.
Listbox style overlay
Read the full LICENSE first; reuse that review for the same task, version, and scope.
First use public component Props to match the desired appearance, preserving the existing look where possible. If changes are necessary, follow the style selection and override order: use your own class (including Tailwind already in the project) or an instance style. The names below are public overrides actually consumed by source; check their scope and do not modify private DOM. Choose the correct SnowUI token family. External apps need not install SnowUI website utilities.
Listbox type and status
Required Props: no named required Props.
Bindable Props: this component declares no named two-way binding; handle state updates through public callbacks or its host.
Inheritance statement: Omit<FrameProps, "children" | "tag">. The inheritance ability is subject to the public document of the base class; the fields in Omit have been excluded and cannot be used as they are according to the base class.
The following type declarations are actually referenced by public Props and come from source. A Svelte Snippet denotes a content fragment; ComponentProps denotes the Props of the corresponding component.
ListboxItem
Source: components/src/components/Listbox.svelte
ComponentPartsOf
Source: components/src/logic/component-parts.svelte.ts
ConfigurableComponentPartProps
Source: components/src/logic/component-parts.svelte.ts
ComponentPartControlledKey
Source: components/src/logic/component-parts.svelte.ts