WheelPicker
A wheel-style single select that keeps native select behavior as the source of truth.
Usage
Use standalone.
<WheelPicker {...props} />Anatomy
The class attribute values represent part names. Other attributes represent their corresponding props.
<div class="whole">
<select class="main" {...rest}>
{#each options as option}
<option value={option.value} disabled={option.disabled}>{option.text}</option>
{/each}
</select>
<div class="middle" aria-hidden="true">
{#each options as option, index}
<div class="label">{label ?? option.text}</div>
{/each}
</div>
<div class="aux" aria-hidden="true"></div>
<div class="extra" aria-hidden="true"></div>
</div>- The sr-only
select.mainremains the source of truth for focus, keyboard input, typeahead, change events, and form submission. middlerenders the decorative wheel and writes pointer or wheel movement back to the native select. Tapping a visible row selects that option, or the nearest enabled option if that row is disabled.loopvisually wraps movement, but the native select value stays a normal finite option list.auxis the center selection band, andextrais intended for overlays such as top and bottom fades.
Props
| Name | Type | Default | Description |
|---|---|---|---|
options* | WheelOption[] | - | Selectable values; disabled options remain visible but are skipped when snapping from pointer or wheel input |
value | string | - | Bindable selected option value; defaults to the first enabled option |
loop | boolean | false | Enables visual circular movement when there are at least two options |
perspective | number | - | 3D wheel perspective in px |
maxAngle | number | 60 | Maximum 3D wheel label angle in degrees |
label | Snippet | - | Custom content for each wheel row |
cssvar | Record | - | Mirrors measured values to CSS custom properties on whole |
attach | Attachment | - | Svelte attachment on the native select |
element | HTMLSelectElement | - | Bindable native select element |
styling | SVSClass | - | Styling override |
variant | SVSVariant | NEUTRAL | Variant for non-selected, enabled labels |
* required. Other HTMLSelectAttributes are passed to <select> via rest props; class is merged onto the root.
Styling
To learn more, see Styling.
Variant Management
The selected label renders with active. Disabled option labels render with inactive. Other labels use the supplied variant.
Default Class Name
svs-wheelpicker
Behavior
- The sr-only
<select>is the source of truth: focus, arrow keys, typeahead, change, andnamesubmission stay native; it remains focusable through clip-based hiding. .middleis the decorative drum: it isaria-hidden, pointer/wheel gestures writeselectedIndexto the select, item height is measured, and visible row count is derived.- Tapping a visible drum row selects that option; a tap on a disabled row snaps to the nearest enabled option. This relies on
.aux/.extrastayingpointer-events: none. loopwrapsselectedIndexmodularly with seam clones; the<select>itself never loops.cssvarmirrors named keys onto.wholeonly.
Accessibility
ARIA Roles and Attributes
The component applies these automatically:
- Select (
main<select>):aria-orientation="vertical". - Visual layers (
middle,aux, andextra):aria-hidden="true"because the native select owns focus, value, and assistive-technology exposure.
Provide an accessible name yourself because there is no built-in visible label. Pass aria-label or aria-labelledby through the rest props, or associate a <label> with the select.
Standards Basis
WheelPicker is built on a native <select> for focus, typeahead, arrow-key navigation, and value changes, so keyboard and assistive-technology support follows the browser standard for select controls. See the Concepts standards-first guidance for the library's approach.
Exports
Types
interface WheelPickerProps extends Omit<HTMLSelectAttributes, "value" | "multiple" | "size" | "style"> {
options: WheelOption[];
value?: string; // bindable; first enabled option's value
loop?: boolean; // (false)
perspective?: number; // px
maxAngle?: number; // deg (60)
label?: Snippet<[WheelOption, string, number]>; // Snippet<[option,variant,index]>
cssvar?: Partial<Record<WheelCssVar, string>>;
attach?: Attachment<HTMLSelectElement>;
element?: HTMLSelectElement; // bindable
styling?: SVSClass;
variant?: SVSVariant; // (VARIANT.NEUTRAL)
// class is merged onto .whole; style is component-owned
}
type WheelPickerReqdProps = "options";
type WheelPickerBindProps = "value" | "element";
type WheelOption = { value: string; text: string; disabled?: boolean };
type WheelCssVar = "itemHeight" | "visible" | "perspective" | "maxAngle";Others
No additional exports are available.
Examples
The example code uses Tailwind CSS along with SVSClass.