Skip to content
v2.5.0
English
Русский
Documentation

DataGridSelectable

DataGridSelectable extends DataGrid with active-cell management and single, multiple, or range selection.
Q1
Q2
Q3
Q4
data-grid-selectable.tsx · 16 lines
import {
  DataGridSelectable,
  DataGridSelectableCell,
  DataGridSelectableRow,
  DataGridSelectableRowGroup,
} from '@vega-ui/react';

<DataGridSelectable aria-label='Quarter' defaultSelected='q2' defaultActive='q2'>
  <DataGridSelectableRowGroup>
    {[['q1', 'q2'], ['q3', 'q4']].map((cells, row) => (
      <DataGridSelectableRow key={cells[0]} row={row}>
        {cells.map((cell, col) => <DataGridSelectableCell key={cell} col={col} cellKey={cell}>{cell.toUpperCase()}</DataGridSelectableCell>)}
Browser support
Widely available
  • Chrome 111
  • Edge 111
  • Firefox 113
  • Safari 15.4
  • Safari on iOS 15.4
Bundle size
Tested in
42 tests

Summary

DataGridSelectable extends DataGrid with active-cell management and single, multiple, or range selection. It is the behavioral selection layer underneath higher-level picker subsystems.

Imports

import {
  DataGridSelectable,
  DataGridSelectableCell,
  DataGridSelectableRow,
  DataGridSelectableRowGroup,
  type DataGridDisabled,
  type DataGridSelectableCellProps,
  type DataGridSelectableProps,
  type DataGridSelectableRowGroupProps,
  type DataGridSelectableRowProps,
  type DataGridSelection,
} from '@vega-ui/react';

Exported Types

  • DataGridSelectableProps<K, S>
  • DataGridSelectableRowGroupProps
  • DataGridSelectableRowProps
  • DataGridSelectableCellProps
  • DataGridSelection = 'single' | 'multiple' | 'range'
  • DataGridDisabled<K>

Minimal Composition

minimal-composition.tsx · 24 lines
import {
  DataGridSelectable,
  DataGridSelectableCell,
  DataGridSelectableRow,
  DataGridSelectableRowGroup,
} from '@vega-ui/react';
import './examples.css';

export default function MinimalComposition() {
  return (
    <DataGridSelectable aria-label='Quarter' defaultActive='q1' className='selectableGrid'>
      <DataGridSelectableRowGroup>

Required Parts

  • DataGridSelectable: root selection engine and active-cell coordinator
  • DataGridSelectableRowGroup: row grouping scope
  • DataGridSelectableRow: one row in the grid
  • DataGridSelectableCell: selectable cell surface

Optional Parts

  • custom apiRef, comparators, range resolver, and disabled maps for advanced behaviors

Composition Order

  1. DataGridSelectable
  2. DataGridSelectableRowGroup
  3. DataGridSelectableRow
  4. DataGridSelectableCell

Variants

  • Selection: single, multiple, range
  • Navigation wrapping: horizontal, vertical, both
  • Constraints: disabled, exclude, from, to, custom comparators

Edge Cases

  • Range expansion uses pointer and keyboard logic that should be tested in the real grid shape.
  • excludeDisabled changes how disabled cells affect navigation and range resolution.
  • from and to constrain the selectable space, not just the visible layout.

Common Mistakes

  • Using complex selection semantics without a stable key model.
  • Forgetting that range logic depends on compare and resolve-range behavior.
  • Treating it like a presentational grid instead of a selection engine.

Examples

Basic

Basic: reporting quarter

Single selection with meaningful keys: every cell gets a cellKey such as FY2025-Q3, which is what defaultSelected, defaultActive and onSelectCell work with. DataGridSelectable has no visuals of its own, so the selected look comes from [aria-selected='true'] in the example stylesheet.

quarter-selector-grid.tsx · 39 lines
import {
  DataGridSelectable,
  DataGridSelectableCell,
  DataGridSelectableRow,
  DataGridSelectableRowGroup,
} from '@vega-ui/react';
import './examples.css';

const years = [2024, 2025, 2026];
const quarters = ['Q1', 'Q2', 'Q3', 'Q4'];

export default function QuarterSelectorGrid() {

Controlled/Stateful

Controlled/Stateful: interview availability

selection='multiple' with the selected keys owned by the parent: the summary and the "Clear" button read and reset the same array. The grid does not set aria-multiselectable for you, so it is passed explicitly, and empty cells get their accessible name from aria-label.

parent-managed-multi-select.tsx · 56 lines
import { useState } from 'react';
import {
  Button,
  DataGridSelectable,
  DataGridSelectableCell,
  DataGridSelectableRow,
  DataGridSelectableRowGroup,
  Text,
} from '@vega-ui/react';
import './examples.css';

const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];

Form/Integration

Form/Integration: delivery window in a form

The grid is not a form control, so the selected key travels in a hidden input and is read with FormData on submit. Submitting without a choice shows an error linked to the grid with aria-describedby; picking a slot clears it, and the reset button clears the state through onReset. Full windows come from disabled.

delivery-slot-form.tsx · 85 lines
import { FormEvent, useState } from 'react';
import {
  Button,
  DataGridSelectable,
  DataGridSelectableCell,
  DataGridSelectableRow,
  DataGridSelectableRowGroup,
  HelperText,
  Text,
} from '@vega-ui/react';
import './examples.css';

Layout/Overlay

Layout/Overlay: slot grid in a popover

PopoverContent mounts its children only while open, so the grid starts fresh every time: defaultActive={slot ?? 'Mon 10:00'} puts the tab stop on the current choice. Picking a slot closes the popover, and the trigger shows the result.

slot-grid-in-a-popover.tsx · 55 lines
import { useState } from 'react';
import {
  Button,
  DataGridSelectable,
  DataGridSelectableCell,
  DataGridSelectableRow,
  DataGridSelectableRowGroup,
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@vega-ui/react';
import './examples.css';

Disabled

Disabled: booked rooms

Keys listed in disabled cannot be selected and get aria-disabled; with the default excludeDisabled they are also skipped by the arrow keys. Pass excludeDisabled={false} when users should still be able to land on them and hear why they are unavailable. The label adds "booked" for screen readers.

exclude-blocked-cells-from-movement.tsx · 42 lines
import {
  DataGridSelectable,
  DataGridSelectableCell,
  DataGridSelectableRow,
  DataGridSelectableRowGroup,
} from '@vega-ui/react';
import './examples.css';

const rooms = ['Atlas', 'Borealis', 'Cosmos'];
const hours = ['09:00', '10:00', '11:00', '12:00', '13:00'];
const booked = ['Atlas 10:00', 'Atlas 11:00', 'Borealis 09:00', 'Cosmos 12:00', 'Cosmos 13:00'];

Edge

Edge: booking window with from and to

from and to bound the selectable keys through compare. ISO dates compare correctly as strings, so days outside 5–24 March become disabled and unreachable without a custom comparator. The range is two keys, check-in and check-out.

booking-window-with-from-and-to.tsx · 69 lines
import { useState } from 'react';
import {
  DataGridSelectable,
  DataGridSelectableCell,
  DataGridSelectableRow,
  DataGridSelectableRowGroup,
  Text,
} from '@vega-ui/react';
import './examples.css';

const weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
const weeks = [0, 1, 2, 3];

Edge: every key of the range

By default a range is stored as its two ends. resolveRange receives both ends with their grid coordinates and the grid itself, so it can walk the cells in between: here onSelectCell gets every working day of the sprint, and weekends never appear because they are not in the grid.

custom-range-resolution.tsx · 78 lines
import { useState } from 'react';
import {
  DataGridSelectable,
  DataGridSelectableCell,
  DataGridSelectableRow,
  DataGridSelectableRowGroup,
  Text,
  type DataGridApiRef,
  type DataGridResolveValue,
} from '@vega-ui/react';
import './examples.css';

Anatomy

Overview

DataGridSelectable is a compound behavioral grid. It layers selection and active-cell logic on top of DataGrid and exposes row-group, row, and cell parts for composition.

Required Parts

  • DataGridSelectable: root behavioral grid
  • DataGridSelectableRowGroup: group of rows, optionally scoped
  • DataGridSelectableRow: one matrix row
  • DataGridSelectableCell: one selectable cell

Optional Parts

  • apiRef: inspect or control the underlying grid
  • resolveRange, compare, equals: advanced selection behavior hooks
  • disabled, exclude, from, to: selection constraints

Composition Order

  1. DataGridSelectable
  2. DataGridSelectableRowGroup
  3. DataGridSelectableRow
  4. DataGridSelectableCell

Valid Composition Patterns

  • dense selection grids with stable row and column keys
  • constrained subranges with from and to
  • range selection with a custom resolver when the key model is not purely sequential

Invalid Composition Patterns

  • unstable cell keys across renders
  • using presentational children that do not preserve cell semantics
  • expecting selection behavior from DataGrid without the selectable wrapper