import {
DataGridPicker,
DataGridPickerItem,
DataGridPickerRow,
DataGridPickerRowGroup,
} from '@vega-ui/react';
<DataGridPicker aria-label='Plan length' defaultSelected='6m' defaultActive='6m' style={{ width: '100%' }}>
<DataGridPickerRowGroup>
<DataGridPickerRow row={0}>
<DataGridPickerItem col={0} value='1m'>1 mo</DataGridPickerItem>
<DataGridPickerItem col={1} value='6m'>6 mo</DataGridPickerItem>- Browser support
- Widely available
- Chrome 111
- Edge 111
- Firefox 113
- Safari 15.4
- Safari on iOS 15.4
- Bundle size
- Oklab and OkLCh — comes from the design tokens
- Scroll snap
- scrollend — has a fallback in the code, not counted in the minimum
- scrollbar-width — covered by a -webkit- fallback, not counted in the minimum
- Resize observer
- Logical properties
- :focus-visible
- :where()
- contain
- scroll-behavior
Summary
DataGridPicker is the visual picker layer built on top of DataGridSelectable. It keeps the same selection engine while adding shared picker size and variant semantics for dense grids such as dates, months, years, and custom matrices.
Imports
import {
DataGridPicker,
DataGridPickerItem,
DataGridPickerRow,
DataGridPickerRowGroup,
DataGridPickerScroller,
DataGridPickerScrollerContent,
type DataGridPickerItemProps,
type DataGridPickerProps,
type DataGridPickerRowGroupProps,
type DataGridPickerRowProps,
type DataGridPickerScrollerContentProps,
type DataGridPickerScrollerProps,
} from '@vega-ui/react';Exported Types
DataGridPickerProps<K, S>DataGridPickerItemPropsDataGridPickerRowPropsDataGridPickerRowGroupPropsDataGridPickerScrollerPropsDataGridPickerScrollerContentProps
Minimal Composition
import {
DataGridPicker,
DataGridPickerItem,
DataGridPickerRow,
DataGridPickerRowGroup,
} from '@vega-ui/react';
export default function MinimalComposition() {
return (
<DataGridPicker aria-label='Plan length' defaultActive='1m' style={{ width: 240 }}>
<DataGridPickerRowGroup>
<DataGridPickerRow row={0}>Required Parts
DataGridPicker: root picker behavior plus size and variant contextDataGridPickerRowGroupDataGridPickerRowDataGridPickerItem
Optional Parts
DataGridPickerScrollerDataGridPickerScrollerContent
Composition Order
DataGridPicker- optional
DataGridPickerScroller DataGridPickerScrollerContentwhen scrolling is usedDataGridPickerRowGroupDataGridPickerRowDataGridPickerItem
Variants
- Variant:
primary,secondary - Size:
xs,sm,md,lg,xl - Selection:
single,multiple,range - Layout: static grid or scroller-based paging
Edge Cases
- Verify active, focused, and selected states independently.
- Scrollable pickers should preserve keyboard navigation and visible focus.
- Scoped row groups matter in paged scroller compositions.
Common Mistakes
- Treating picker items as plain layout nodes without selection semantics.
- Forgetting to test scroll and keyboard interaction together.
- Rebuilding item styling manually when the picker layer already defines the intended visual semantics.
Examples
Basic
Basic: statement month
Twelve months in a 4×3 matrix with single selection. value on every DataGridPickerItem is its key, so defaultSelected and defaultActive use the same 2026-05 strings; the picker supplies the selected, hover and focus styles.
import {
DataGridPicker,
DataGridPickerItem,
DataGridPickerRow,
DataGridPickerRowGroup,
} from '@vega-ui/react';
const months = [
['Jan', 'Feb', 'Mar', 'Apr'],
['May', 'Jun', 'Jul', 'Aug'],
['Sep', 'Oct', 'Nov', 'Dec'],
];Controlled/Stateful
Controlled/Stateful: campaign months as a range
selection='range' with the range owned by the parent. Items between the ends get data-range styling automatically, the summary reads the same array, and "Clear" resets it. Keys are YYYY-MM strings, which already sort in calendar order.
import { useState } from 'react';
import {
Button,
DataGridPicker,
DataGridPickerItem,
DataGridPickerRow,
DataGridPickerRowGroup,
Text,
} from '@vega-ui/react';
const names = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const rows = [0, 1, 2];Form/Integration
Form/Integration: invoice period in a form
The selected quarter goes into a hidden input and is read with FormData on submit; the reset button restores the initial quarter through onReset. Q4 is disabled, and the hint explaining why is linked with aria-describedby.
import { FormEvent, useState } from 'react';
import {
Button,
DataGridPicker,
DataGridPickerItem,
DataGridPickerRow,
DataGridPickerRowGroup,
HelperText,
Text,
} from '@vega-ui/react';
const quarters = ['2026-Q1', '2026-Q2', '2026-Q3', '2026-Q4'];Layout/Overlay
Layout/Overlay: paged picker with own buttons
The scroller exposes prev() and next() through apiRef for buttons outside the grid. Each page reads its index from useIndexedSnapScrollerContext, derives its years and unique row numbers from it, and passes it as scope of the row group, so focus moves to the first available cell of the page in view. onScrollSnapChanging keeps the period label in sync.
import { useRef, useState } from 'react';
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import {
DataGridPicker,
DataGridPickerItem,
DataGridPickerRow,
DataGridPickerRowGroup,
DataGridPickerScroller,
DataGridPickerScrollerContent,
Icon,
IconButton,
Text,Error
Error: at least three training days
Multiple selection with a minimum. Submitting with fewer than three days turns the linked helper text into an error; reaching three clears it. The chosen days are submitted as repeated day fields.
import { FormEvent, useState } from 'react';
import {
Button,
DataGridPicker,
DataGridPickerItem,
DataGridPickerRow,
DataGridPickerRowGroup,
HelperText,
Text,
} from '@vega-ui/react';
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];Disabled
Disabled: sold-out sizes
disabled takes the sold-out values. The picker excludes disabled items from keyboard movement by default, and their labels say "sold out" for screen readers.
import {
DataGridPicker,
DataGridPickerItem,
DataGridPickerRow,
DataGridPickerRowGroup,
HelperText,
} from '@vega-ui/react';
const sizes = [[36, 37, 38, 39, 40, 41], [42, 43, 44, 45, 46, 47]];
const soldOut = [37, 41, 42, 46];
export default function BlockedCellsInsideADensePicker() {Edge
Edge: pick six of 49
A selection limit built from a disabled predicate: once six numbers are picked, every other number is disabled. excludeDisabled={false} keeps them reachable with the arrow keys, otherwise the keyboard could only move between the six picked numbers.
import { useState } from 'react';
import {
Button,
DataGridPicker,
DataGridPickerItem,
DataGridPickerRow,
DataGridPickerRowGroup,
Text,
} from '@vega-ui/react';
const limit = 6;
const rows = Array.from({ length: 7 }, (_, row) => row);Anatomy
Overview
DataGridPicker is a compound picker subsystem. It wraps DataGridSelectable and adds a picker-specific visual context for size and variant.
Required Parts
DataGridPicker: root picker layerDataGridPickerRowGroupDataGridPickerRowDataGridPickerItem
Optional Parts
DataGridPickerScrollerDataGridPickerScrollerContent
Composition Order
DataGridPicker- optional
DataGridPickerScroller DataGridPickerScrollerContentDataGridPickerRowGroupDataGridPickerRowDataGridPickerItem
Valid Composition Patterns
- static picker grids for months, quarters, or emoji sets
- paged scroller pickers with scoped row groups
- single, multiple, or range selection depending on the consumer subsystem
Invalid Composition Patterns
- using plain layout nodes instead of picker items for selectable content
- omitting scope management in paged compositions that depend on page identity
- treating
DataGridPickerlike a generic data table