Vize

Listbox Grid

Accessible, unstyled 2-D option grid (icon, color, and swatch pickers) with typed selection. The pure grid navigation (moveInGrid, gridMoveFromKey) stays internal to the family source so the subpath bundle keeps a single chunk order; source installs can import listbox-grid-model.ts directly.

Package @vizejs/ui/listbox-grid
Maturity stable
Own the source vize lib pull listbox-grid
Requires collection, context, controllable-state, id, typeahead
Aliases listbox grid, icon picker, color swatch picker, rich select grid
Covers WAI-ARIA listbox pattern (grid layout), React Aria ListBox grid layout, Ark UI Color Picker swatches

Usage

import { ListboxGrid, ListboxGridItem } from "@vizejs/ui/listbox-grid";

Or copy the source into your project with vize lib pull listbox-grid (see Source Distribution).

API

ListboxGrid<T, Multiple extends boolean = false>

Source: src/families/selection/listbox-grid/listbox-grid.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned listbox id. null and undefined select a deterministic fallback.
modelValue ListboxGridModelValue<T, Multiple> undefined Controlled selection: T | null, or readonly T[] when multiple is true.
defaultValue ListboxGridModelValue<T, Multiple> undefined Initial selection for uncontrolled use and the value restored by reset.
multiple Multiple false Allow selecting several options. The literal type decides the model type.
items readonly T[] undefined Option values in display order; used for inference and select-all.
by ListboxGridBy<T> undefined Compare values by a property key or with a custom equality function.
columns number 4 Options per row; must match the consumer's CSS grid so arrow keys follow the layout.
pageRows number 3 Rows traversed by PageUp and PageDown.
selectionFollowsFocus boolean false Select the option that becomes active through arrow keys (single mode, swatch pickers).
disabled boolean false Disable every option and remove the grid from the tab order.
required boolean false Mark a selection as required for assistive technology.
name string undefined Form field name; each selected value submits one hidden input.
form string undefined Id of the owning form when rendered outside it.
formValue (value: T) => string undefined Serialize a value for form submission.
dir "ltr" | "rtl" "ltr" Reading direction; rtl mirrors ArrowLeft and ArrowRight.
typeaheadTimeout number 500 Idle time before buffered typeahead starts a new query.
ariaLabel string undefined Accessible name when no visible label supplies one.
ariaLabelledby string undefined Space-separated ids that label the grid.
ariaDescribedby string undefined Space-separated ids that describe the grid.

Events

Event Payload Description
update:modelValue [value: ListboxGridModelValue<T, Multiple>] Fired when the selection requests a new controlled value (T | null or readonly T[]).
change [ value: ListboxGridModelValue<T, Multiple>, previous: ListboxGridModelValue<T, Multiple>, nativeEvent: Event, ] Fired after a user interaction changes the selection: next value, previous value, native event.

Slots

Slot Slot props Description
default ListboxGridSlotState<T> ListboxGridItem options. Receives selection, active option, and layout state.

Exposed

Member Type Description
selected readonly T[] Selected values.
activeId string | null Id of the highlighted option.
focus (options?: FocusOptions) => void Move DOM focus to the grid.
select (value: T) => boolean Select (single) or toggle (multiple) a value.
clear () => boolean Clear the selection.
reset () => boolean Restore defaultValue.

ListboxGridItem<T>

Source: src/families/selection/listbox-grid/listbox-grid-item.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned option id. null and undefined select a deterministic fallback.
value (required) T required Option value compared with the selection through by.
disabled boolean false Disable this option.
textValue string undefined Explicit typeahead text; icon and color swatches usually need one.
ariaLabel string undefined Accessible name, required when the option renders only an icon or swatch.

Slots

Slot Slot props Description
default ListboxGridItemSlotState<T> Option content. Receives position, selection, and highlight state.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
selected —
active —

Behavior

Contract

ListboxGrid is a headless, strongly typed 2-D option grid for icon, color, swatch, and "rich select" pickers. listbox-grid.vue is generic over the value type T and a Multiple literal (T | null or readonly T[]), renders role="listbox" with aria-activedescendant, and keeps DOM focus on itself. listbox-grid-item.vue renders role="option" and registers with the shared collection registry, which also powers buffered typeahead. Arrow keys follow the visual grid through the pure moveInGrid helper; columns must match the consumer's CSS grid. Named grids submit one hidden input per selected value. No CSS ships.

Normative Behavior

# State Input Outcome Proven by
G1 any render role="listbox", tabindex=0, data-columns, options expose row/column slot state, hidden form inputs renders listbox semantics with row and column slot state
G2 focused Arrow keys / Home / End / Ctrl+Home/End / PageUp / PageDown focus highlights the selection, then moves in two dimensions, skipping disabled options; edges hold focus highlights the selected option, then arrows move in two dimensions
G3 dir="rtl" ArrowLeft / ArrowRight mirrored rtl mirrors horizontal arrows
G4 single Enter / Space / selectionFollowsFocus selects the highlighted option; change carries the key event; follow-focus selects on arrows Enter and Space select in single mode; selectionFollowsFocus selects on arrows
G5 multiple Space / Shift+Arrow / Ctrl+A toggles, extends, selects every enabled option multiple mode toggles, extends with Shift+arrows, and selects all with Ctrl+A
G6 any pointer pointer-down keeps focus on the grid; click selects; disabled options ignore input click selects; disabled options ignore pointer input
G7 focused printable character typeahead moves the highlight by textValue typeahead moves the highlight by option text
G8 disabled Tab / keys removed from the tab order, keys ignored disabled grids leave the tab order and ignore keys
G9 controlled click emits and waits for the parent; by matches structurally equal values controlled values wait for the parent
G10 no provider mount an item throws VIZE_UI_CONTEXT_MISSING items require a ListboxGrid provider
G11 pure helper moveInGrid empty grids, ragged last rows, page moves, and row-wrap opt-out are deterministic pure grid navigation handles empty grids, ragged rows, and page moves

SSR

Ids come from the deterministic-id primitive; server markup is byte-identical across isolated requests and hydrates without warnings (renders byte-identical ListboxGrid markup across isolated SSR requests, hydrates ListboxGrid without mismatches or node replacement).