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).