InputsReact
A list of rows that each hold their own buttons, links or fields, such as files with Share and Delete, people with a menu, or cards in a gallery.
Rendered by React 19.3.1
Loading React…Installation
npm i @hamur/reactNot on npm yet. The package goes out under the chosen name.
Anatomy
Import the component and assemble its parts:
<GridList.Root>
<GridList.Item>
<GridList.ItemContent>
<GridList.ItemText />
<GridList.ItemDescription />
</GridList.ItemContent>
</GridList.Item>
<GridList.Empty />
</GridList.Root>
// Not in this example: GridList.Group, GridList.GroupLabel, GridList.ItemHandle, GridList.ItemIndicatorExamples
Multiple
multiple with a checkbox per row: Alan Turing is disabled, so Control+A and ranges skip him; the selected values are listed below.
Layout
layout="grid": eight album cards in as many columns as fit, ArrowDown keeping the column and Home and End the line.
Move
allowMove with an ItemHandle per row: drag by the handle, or Control+X and Control+V; onItemMove reorders the playlist.
Virtualized
1,000 rows as items, virtualized, with fewer than 30 rows mounted; Home, End and the page keys reach rows that are not mounted.
API reference
35 props across 10 parts, in React syntax. className, style, render are listed once, under Shared props.
EmptyGridList.Empty
Content shown while the list has no rows. Renders nothing otherwise. It has no ARIA role. Renders a <div>.
GroupGridList.Group
Groups related rows with the corresponding label. Renders a <div>.
GroupLabelGridList.GroupLabel
A label that names its group. Hidden from assistive technology, which reads it as the group's name. Renders a <div>.
ItemGridList.Item
A row of the grid list, with its one cell (GridList.ItemContent). Renders a <div>.
| Prop | Type | Default |
|---|---|---|
children | React.ReactNode | — |
valuerequiredA unique value that identifies this row. | any | — |
labelOverrides the text that typeahead matches and the announcements read. | string | — |
disabledWhether the component should ignore user interaction. | boolean | false |
selectableWhether the row can be selected, in a list that is selectable. | boolean | true |
onActionCalled when the row is activated: Enter, or a press or Space on a row that does not select. | ((eventDetails: GridListActionDetails) => void) | — |
indexVirtualized only: the position of the row in items. | number | — |
| Data attribute | Description |
|---|---|
data-selected | Present when the row is selected. |
data-highlighted | Present when focus is on the row or inside it. |
data-disabled | Present when the row is disabled. |
data-moving | Present while the row is being moved. |
data-drop-target | Where a dragged row would land relative to this one. |
data-dragging | Present while the row is being dragged. |
ItemContentGridList.ItemContent
The one cell of a row: its text, description, indicator and controls. Renders a <div>.
ItemDescriptionGridList.ItemDescription
A description of a row, read after its name. Renders a <span>.
ItemHandleGridList.ItemHandle
The part of a row a drag starts from. While it is mounted, the rest of the row does not start a drag. Renders a <span>.
| Prop | Type | Default |
|---|---|---|
children | React.ReactNode | — |
ItemIndicatorGridList.ItemIndicator
Shows whether the row is selected. A press toggles the row's selection. Renders a <span>.
| Prop | Type | Default |
|---|---|---|
children | React.ReactNode | — |
keepMountedWhether to keep the element in the DOM when the row is not selected. | boolean | false |
ItemTextGridList.ItemText
The text of a row: it names the row, and typeahead matches it. Renders a <span>.
RootGridList.Root
Groups all parts of the grid list: a list of rows that hold their own buttons, links and inputs., followed by the status region. Renders a <div>.
| Prop | Type | Default |
|---|---|---|
valueThe selected value. | GridListInputValue<Value, Multiple> | null | — |
defaultValueThe uncontrolled selected value when the list is initially rendered. | GridListInputValue<Value, Multiple> | null | — |
onValueChangeEvent handler called when the selection changes, once per gesture. | ((value: GridListOutputValue<Value, Multiple>, eventDetails: GridListRootChangeEventDetails) => void) | — |
selectableWhether rows can be selected at all. | boolean | false |
multipleWhether several rows can be selected. | Multiple | false |
disallowEmptySelectionWhether the last selected row of a multiple list cannot be deselected. | boolean | false |
selectOnPressWhether a press on a selectable row selects it. | boolean | true |
isItemEqualToValueCustom comparison logic used to determine if an item value matches the current value. | ((itemValue: Value, value: Value) => boolean) | — |
layoutHow the rows are laid out: one row per line along orientation ('list'), or wrapped | GridListLayout | 'list' |
orientationThe orientation of layout="list". | GridListOrientation | 'vertical' |
columnsThe column count of layout="grid". | number | — |
loopFocusWhether the arrow keys wrap from the last row to the first and back. | boolean | false |
disabledWhether the component should ignore user interaction. | boolean | false |
highlightedValueThe value of the focused row. | Value | null | — |
onHighlightChangeEvent handler called when the current row changes (focus on a row or inside it). | ((value: Value | null) => void) | — |
itemsEvery item of the list in order, mounted or not. | readonly Value[] | — |
virtualizedWhether the app renders only some rows (a virtualizer), each with its index. | boolean | false |
itemToStringLabelConverts an item of items to its typeahead text. | ((item: Value) => string) | — |
isItemDisabledWhether an item of items is disabled, for rows that are not mounted. | ((item: Value) => boolean) | — |
onItemHighlightedVirtualized only: called when keyboard navigation (or highlightedValue) targets a row that | ((item: Value, eventDetails: GridListHighlightDetails) => void) | — |
allowMoveWhether rows can be moved by dragging, with Ctrl/Cmd+X and Ctrl/Cmd+V, and through | boolean | false |
canMoveWhether a move may happen. | ((details: GridListMoveDetails<Value>) => boolean) | — |
onItemMoveCalled with a move. | ((details: GridListMoveDetails<Value>, eventDetails: GridListRootItemMoveEventDetails) => void) | — |
actionsRefA ref to start, complete and cancel a move from the app (a context menu's "Move"). | React.RefObject<GridListRootActions | null> | — |
labelsThe texts of the status region. | Partial<GridListLabels> | — |
| Data attribute | Description |
|---|---|
data-layout | Indicates how the rows are laid out. |
data-orientation | Indicates the orientation of the list layout. |
data-multiple | Present when several rows can be selected. |
data-selectable | Present when rows can be selected. |
data-disabled | Present when the list is disabled. |
data-empty | Present when the list has no rows. |
data-moving | Present while a move is pending. |
Shared props
Every part that renders an element takes these.
| Prop | Type |
|---|---|
classNameCSS class applied to the element, or a function that
returns a class based on the component's state. | string | ((state: State) => string | undefined) |
styleStyle applied to the element, or a function that
returns a style object based on the component's state. | React.CSSProperties | ((state: State) => React.CSSProperties | undefined) |
renderAllows you to replace the component's HTML element
with a different tag, or compose it with another component. | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State> |
Keyboard and accessibility
Keyboard
| Keys | Does | Part |
|---|---|---|
| ArrowDownArrowUp | Moves focus to the next or previous row, disabled rows included | Root |
| ArrowRightArrowLeft | Moves into the row's controls and through them; ArrowLeft from the first control returns to the row | Item |
| HomeEnd | Moves focus to the first or last row; in the wrapped layout, the first or last card of the line | Root |
| PageDownPageUp | Moves focus ten rows and stops at the ends | Root |
| TabShiftTab | Moves through the focused row's controls, then out of the list | Item |
| F2 | Moves from the row to its first control and back | Item |
| Escape | From a control, returns to its row; on a row, cancels a move in progress | Item |
| Moves focus to the next row whose text starts with what was typed | Root | |
| Enter | Runs the row's onAction; without one, selects the row | Item |
| Space | Selects the focused row; with multiple, toggles it | Item |
| ShiftArrowDownShiftArrowUp | With multiple, extends the selection from the anchor | Root |
| ControlAMetaA | With multiple, selects every enabled row, or clears them when all are selected | Root |
| ControlXControlV | With allowMove, takes the row and puts it before the focused row going up, after it going down | Item |
Accessibility
| Part | Sets | So that |
|---|---|---|
| Root | role="grid", aria-multiselectable with multiple, aria-disabled, aria-rowcount when virtualized, never aria-orientation; named by aria-label or aria-labelledby | the list is read as one widget with its name; a development build warns without one |
| Item | role="row", named by its ItemText (aria-labelledby) and described by its ItemDescription (aria-describedby); aria-rowindex when virtualized | a row is read as "Report.pdf", not as the text of its buttons, and says where it is when its neighbours are not mounted |
| Item | aria-selected (true or false) on a selectable row only, aria-disabled on a disabled row | a list without selection says nothing about it; a disabled row keeps focus and is read as unavailable |
| ItemContent | role="gridcell", the row's only element child | the row's controls keep their own roles inside one cell |
| ItemIndicator | aria-hidden, never focusable | the check is for sight; the row's state says it |
| ItemHandle | aria-hidden, never focusable | the drag handle is for the pointer; Control+X and Control+V move from the keyboard |
| Group | role="rowgroup", labelled by its GroupLabel, which is aria-hidden | the rows are read under their heading once |
| Root | one polite role="status" region next to the list, always mounted | selecting, ranges, Control+A and moves are announced, since readers do not announce aria-selected changes on grid rows |
Focus order
- The list is one Tab stop: the last focused row, or the first selected one, or the first row. Nothing takes focus on mount;
Shift+Tabinto the list lands on the row, not on the last row's button. - Inside, the arrow keys,
Home,End, the page keys and typeahead move between rows;Tabfrom a row walks its controls, then leaves the list. EscapeorF2from a control returns to its row; removing the focused row moves focus to the next row, else the previous one.