Grid List
Accessible, unstyled GridList (WAI-ARIA APG grid pattern for interactive lists): roving focus, typeahead, single/multiple selection with ranges, list or 2D grid layouts, and pointer + keyboard drag reordering.
|
|
| Package |
@vizejs/ui/grid-list |
| Maturity |
stable |
| Own the source |
vize lib pull grid-list |
| Requires |
collection, context, controllable-state, drag-and-drop, id, sortable, typeahead |
| Aliases |
selectable list, reorderable list, card grid, gallery grid |
| Covers |
WAI-ARIA grid pattern, React Aria GridList, Reka UI Listbox |
Usage
import { GridList, GridListItem } from "@vizejs/ui/grid-list";
Or copy the source into your project with vize lib pull grid-list (see Source Distribution).
API
GridList<Item>
Source: src/families/data/grid-list/grid-list.vue
Props
| Prop |
Type |
Default |
Description |
items (required) |
readonly Item[] |
undefined |
Items rendered as rows. |
getKey |
(item: Item, index: number) => string |
undefined |
Stable key per item; defaults to the index. |
getTextValue |
(item: Item) => string |
undefined |
Typeahead text per item; defaults to the rendered text. |
id |
string | null |
undefined |
Consumer-owned list id. null and undefined select a deterministic fallback. |
selectionMode |
GridListSelectionMode |
"single" |
Selection policy. |
selection |
readonly string[] |
undefined |
Controlled selected keys (v-model:selection). |
defaultSelection |
readonly string[] |
[] |
Initial uncontrolled selection. |
disabledKeys |
readonly string[] |
[] |
Keys that stay focusable but cannot be selected, activated, or dragged. |
layout |
GridListLayout |
"list" |
list moves with Up/Down; grid also moves with Left/Right and steps Up/Down by columns. |
columns |
number |
1 |
Items per visual row in the grid layout. |
dir |
"ltr" | "rtl" |
"ltr" |
Reading direction for Left/Right in the grid layout. |
loop |
boolean |
false |
Wrap arrow navigation at both ends. |
reorderable |
boolean |
false |
Allow pointer and keyboard reordering through the slot's dragHandleProps. |
ariaLabel |
string |
undefined |
Accessible name of the grid. |
ariaLabelledby |
string |
undefined |
Ids that label the grid. |
Events
| Event |
Payload |
Description |
update:selection |
[value: readonly string[]] |
Fired with the new selected keys (supports v-model:selection). |
action |
[item: Item, key: string] |
Fired when Enter or a double click activates an enabled item. |
update:items |
[value: readonly Item[]] |
Fired with the reordered items (supports v-model:items). |
reorder |
[event: GridListReorderEvent<Item>] |
Fired after a reorder commits. |
Slots
| Slot |
Slot props |
Description |
item |
GridListItemSlotProps<Item> |
Item contents. |
empty |
— |
Rendered when items is empty. |
Exposed
| Member |
Type |
Description |
element |
HTMLDivElement | null |
Rendered role="grid" element. |
focus |
(key?: string) => void |
Focus an item by key (or the active/first item). |
selectAll |
() => boolean |
Select every enabled item (multiple selection only). |
clearSelection |
() => boolean |
Clear the selection. |
GridListItem
Source: src/families/data/grid-list/grid-list-item.vue
Props
| Prop |
Type |
Default |
Description |
itemKey (required) |
string |
undefined |
Stable item key (registry key and DOM data hook). |
index (required) |
number |
undefined |
Zero-based item index, published as aria-rowindex (one-based). |
selected |
boolean |
false |
Whether the item is selected. |
disabled |
boolean |
false |
Whether the item is disabled (focusable, not selectable or draggable). |
textValue |
string |
undefined |
Typeahead text; rendered text is used when omitted. |
Slots
| Slot |
Slot props |
Description |
default |
{ readonly active: boolean; readonly dragging: boolean; readonly dragHandleProps: Readonly<DragSourceProps> | null; } |
Item contents. Receives drag state and handle props. |
Behavior
@vizejs/ui/grid-list applies the WAI-ARIA APG grid pattern to interactive lists. grid-list.vue is the
generic root (Item); grid-list-item.vue renders each role="row" with one role="gridcell". Reordering
uses the shared sortable foundation through a drag handle. Every row is proven by the named test in
grid-list.test.ts or grid-list-ssr.test.ts.
| # |
State |
Input |
Outcome |
Proven by |
| L1 |
any |
render |
role="grid" with aria-rowcount, rows with aria-rowindex and one gridcell, a single tab stop |
renders an APG grid of rows with one gridcell and a single tab stop |
| L2 |
layout="list" |
Up/Down, Home/End, PageUp/PageDown, loop, characters |
roving focus moves, wraps with loop, and typeahead matches getTextValue |
list layout: Up/Down, Home/End, PageUp/PageDown, loop, and typeahead |
| L3 |
layout="grid" |
Left/Right, Up/Down, dir="rtl" |
Left/Right step items, Up/Down step by columns, rtl flips |
grid layout: Left/Right step items, Up/Down step rows, rtl flips |
| L4 |
selectionMode="multiple" |
click, Ctrl, Shift, Space, Shift+Arrow, Ctrl+A |
replace, toggle, and range selection skipping disabled items; aria-selected / aria-disabled |
multiple selection: click, Ctrl-click, Shift-click, Space, Shift+Arrow, Ctrl+A |
| L5 |
single / none |
click, Enter, double click |
single replaces; none publishes no aria-selected; Enter and double click emit action |
single selection replaces; none mode publishes no aria-selected; Enter and double click act |
| L6 |
reorderable |
Enter on handle, arrows, Enter |
a keyboard move commits; reorder and update:items fire; list keys ignore handle events |
keyboard reorder through the drag handle commits and emits the new order |
| L7 |
no items |
render |
an empty row renders the empty slot |
empty lists render an empty row |
| L8 |
custom compositions |
import |
GridListItem is exported |
GridListItem is exported for custom compositions |
| L9 |
SSR |
two requests + hydrate |
byte-identical markup with one tab stop; warning-free hydration |
renders identical grid-list markup across SSR requests and hydrates cleanly |