From 729c02de768d0b12fce356b28a7e65acb466db48 Mon Sep 17 00:00:00 2001 From: Ricky Zhang Date: Tue, 13 Oct 2026 14:08:52 -0400 Subject: [PATCH 01/16] feat(DataTable): add bulk actions for effective row selection Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .changeset/data-table-bulk-actions.md | 5 + e2e/components/DataTableBulkActions.test.ts | 107 ++++++ .../src/DataTable/DataTable.accessibility.md | 83 ++++ .../DataTable.bulk-actions.stories.tsx | 208 +++++++++++ .../react/src/DataTable/DataTable.docs.json | 59 +++ packages/react/src/DataTable/DataTable.tsx | 70 +++- .../src/DataTable/DataTable.types.test.tsx | 34 +- packages/react/src/DataTable/Table.module.css | 1 + .../src/DataTable/TableBulkActions.module.css | 30 ++ .../react/src/DataTable/TableBulkActions.tsx | 110 ++++++ .../__tests__/DataTableBulkActions.test.tsx | 353 ++++++++++++++++++ packages/react/src/DataTable/index.ts | 6 +- packages/react/src/DataTable/useTable.ts | 4 + .../__snapshots__/exports.test.ts.snap | 2 + packages/react/src/experimental/index.ts | 2 + 15 files changed, 1070 insertions(+), 4 deletions(-) create mode 100644 .changeset/data-table-bulk-actions.md create mode 100644 e2e/components/DataTableBulkActions.test.ts create mode 100644 packages/react/src/DataTable/DataTable.bulk-actions.stories.tsx create mode 100644 packages/react/src/DataTable/TableBulkActions.module.css create mode 100644 packages/react/src/DataTable/TableBulkActions.tsx create mode 100644 packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx diff --git a/.changeset/data-table-bulk-actions.md b/.changeset/data-table-bulk-actions.md new file mode 100644 index 00000000000..02e0d2ab304 --- /dev/null +++ b/.changeset/data-table-bulk-actions.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +DataTable: Add bulk actions for selected rows with selection counts, clearing selection, and focus recovery. diff --git a/e2e/components/DataTableBulkActions.test.ts b/e2e/components/DataTableBulkActions.test.ts new file mode 100644 index 00000000000..4d14968faca --- /dev/null +++ b/e2e/components/DataTableBulkActions.test.ts @@ -0,0 +1,107 @@ +import {test, expect} from '@playwright/test' +import {visit} from '../test-helpers/storybook' +import {themes} from '../test-helpers/themes' + +const stories = ['flat', 'grouped', 'mixed', 'async-actions', 'composed-table'] as const + +test.describe('DataTable bulk actions', () => { + for (const story of stories) { + for (const theme of themes) { + test(`${story} ${theme} @avt`, async ({page}) => { + await visit(page, { + id: `experimental-components-datatable-features-bulk-actions--${story}`, + globals: {colorScheme: theme}, + }) + await expect(page).toHaveNoViolations() + }) + } + } + + for (const story of ['flat', 'grouped', 'mixed', 'composed-table'] as const) { + test(`${story} keyboard focus and unobscured header @avt`, async ({page}) => { + await visit(page, {id: `experimental-components-datatable-features-bulk-actions--${story}`}) + if (story === 'flat') { + await expect(page.getByRole('columnheader', {name: 'Repository', exact: true})).toHaveAttribute( + 'aria-sort', + 'ascending', + ) + } + const selectAll = page.getByRole('checkbox', {name: 'Select rows', exact: true}) + await selectAll.focus() + await page.keyboard.press('Space') + await expect(selectAll).toBeFocused() + const actions = page.getByRole('group', {name: 'Bulk actions'}) + await expect(actions.getByText('3 rows selected')).toBeVisible() + const actionsBox = await actions.boundingBox() + const headerBox = await selectAll.boundingBox() + expect(actionsBox).not.toBeNull() + expect(headerBox).not.toBeNull() + expect(actionsBox!.y + actionsBox!.height).toBeLessThanOrEqual(headerBox!.y) + + await actions.getByRole('button', {name: 'Clear selection'}).focus() + await page.keyboard.press('Enter') + await expect(selectAll).toBeFocused() + await expect(actions).toHaveCount(0) + await expect(page).toHaveNoViolations() + }) + } + + test('asynchronous failure retains selection; success handles deletion and final-record focus @avt', async ({ + page, + }) => { + await visit(page, {id: 'experimental-components-datatable-features-bulk-actions--async-actions'}) + await expect(page.getByRole('columnheader', {name: 'Repository', exact: true})).toHaveAttribute( + 'aria-sort', + 'ascending', + ) + await page.getByRole('button', {name: 'Simulate failed action'}).click() + await expect( + page + .locator('#storybook-root') + .getByText('Unable to delete repositories. Your selection is unchanged; try again.'), + ).toBeVisible() + await expect(page.getByRole('checkbox', {name: 'Select primer/react', exact: true})).toBeChecked() + await page.getByRole('button', {name: 'Delete selected'}).click() + await expect(page.locator('#storybook-root').getByText('1 repository deleted')).toBeVisible() + const selectAll = page.getByRole('checkbox', {name: 'Select rows', exact: true}) + await expect(selectAll).toBeFocused() + + await selectAll.click() + await page.getByRole('button', {name: 'Delete selected'}).click() + await expect(page.getByRole('rowheader')).toHaveCount(0) + await expect(page.getByRole('button', {name: 'Reset repositories'})).toBeFocused() + await expect(selectAll).toBeDisabled() + await expect(page).toHaveNoViolations() + }) + + for (const theme of ['light', 'dark'] as const) { + test(`mixed ${theme} @vrt`, async ({page}) => { + await visit(page, { + id: 'experimental-components-datatable-features-bulk-actions--mixed', + globals: {colorScheme: theme}, + }) + await expect(page).toHaveScreenshot(`DataTable.BulkActions.Mixed.${theme}.png`) + }) + } + + test('actions reflow without clipping at a narrow viewport and with text-spacing overrides @avt', async ({page}) => { + await page.setViewportSize({width: 320, height: 256}) + await visit(page, {id: 'experimental-components-datatable-features-bulk-actions--mixed'}) + await page.addStyleTag({ + content: + '* {line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important;} p {margin-bottom: 2em !important;}', + }) + const actions = page.getByRole('group', {name: 'Bulk actions'}) + await expect(actions.getByRole('button', {name: 'Clear selection'})).toBeVisible() + await expect(actions.getByRole('button', {name: 'Delete selected'})).toBeVisible() + const dimensions = await actions.evaluate(element => ({ + width: element.clientWidth, + scrollWidth: element.scrollWidth, + right: element.getBoundingClientRect().right, + })) + expect(dimensions.scrollWidth).toBeLessThanOrEqual(dimensions.width) + expect(dimensions.right).toBeLessThanOrEqual(320) + await actions.getByRole('button', {name: 'Clear selection'}).click() + await expect(page.getByRole('checkbox', {name: 'Select rows', exact: true})).toBeFocused() + }) +}) diff --git a/packages/react/src/DataTable/DataTable.accessibility.md b/packages/react/src/DataTable/DataTable.accessibility.md index 96b5a190124..b7bd09e9843 100644 --- a/packages/react/src/DataTable/DataTable.accessibility.md +++ b/packages/react/src/DataTable/DataTable.accessibility.md @@ -272,6 +272,87 @@ row count. The generated count description is currently English. disclosure. Focus outside the group is left alone. - Collapse does not clear selection or change its scope. +## Bulk actions + +`DataTable` composes `Table.BulkActions` when `rowSelection` and +`renderBulkActions` are provided. The render callback receives +`{selectedRows, selectedCount, clearSelection}`. The IDs and count are the same +effective selection: only currently supplied, selectable rows qualify. Missing +and non-selectable IDs remain in the owner's set but never reach business actions. +Sorting and refreshes preserve the contract; collapsing groups must only change +presentation, not remove their members from the selection model. + +`clearSelection` requests an empty selection, including previously retained IDs. +Controlled owners must apply `onSelectionChange` for it to take effect. No second +selection state is introduced. Page/filter owners still clear selection on scope +changes; query-wide and group-level select-all are not supported. + +The action group sits **above**, not over, the table header, following the +[focus-obscured finding](https://github.com/github/accessibility/issues/10267). +Sorting and selection controls remain visible and usable. It is a named +`role="group"`, not an ARIA toolbar: actions use native Tab/Shift+Tab navigation, +and the component does not impose arrow-key navigation on consumer children. +Use Primer buttons and menus with visible, non-color-only focus indicators. + +The selection tally stays mounted at zero (visually hidden), and uses the shared +`AriaStatus` announcement primitive. Count changes include deselection to zero. +`bulkActionsProps` localizes the action group's `aria-label`, clear button label, +and `getSelectedCountLabel(count)` (including zero). +The [follow-up audit](https://github.com/github/accessibility/issues/10807) +reports historical VoiceOver/Safari failures with Shadow DOM live regions in +IndexTable. This implementation reuses Primer's current announcement primitive; +automated announcement assertions do not establish VoiceOver support. Manual +VoiceOver/Safari verification remains required alongside NVDA and JAWS. + +### Focus and operation ownership + +- Showing actions does not move focus from the activating checkbox. +- Hiding actions only recovers focus if the focused action was removed and focus + fell back to the document body. It does not steal focus from a dialog, toast + action, or other consumer-selected destination. +- Config recovery targets select-all; with no selectable rows, it targets the + table programmatically without adding a Tab stop. `bulkActionsReturnFocusRef` + overrides this target, for example with an Add button for an empty table. +- `Table.BulkActions` consumers keep the component mounted at zero and supply + `onFocusReturn` to choose their recovery target. Consumers supply the effective + count, clear callback, and children in their intended order. +- Consumers own requests, pending/error states, success/failure announcements, + permanent removal reconciliation, and business-specific focus (including + closing dialogs or replacing the entire table). Clearing is explicit, not + automatic after an action. Failed operations should retain selection for retry. +- For asynchronous actions, snapshot the callback's effective IDs at activation. + Apply success/failure to that operation's IDs, not a subsequently changed + selection. Disabling actions while pending does not disable row checkboxes; + consumers decide whether to allow additional selection during the request. + +For example: + +```tsx + setSelectedRows(selectedRows)} + renderBulkActions={({selectedRows: effectiveIds, selectedCount, clearSelection}) => ( + + )} +/> +``` + +The snippet illustrates synchronous success. An asynchronous owner awaits success +before clearing, retains selection on failure, and announces the result itself. +The [bulk-action stories](./DataTable.bulk-actions.stories.tsx) demonstrate flat, +grouped, mixed, asynchronous failure/retry, and direct composition. + ## Verification - [Grouping tests](./__tests__/DataTableGrouping.test.tsx) cover mixed body @@ -283,6 +364,8 @@ row count. The generated count description is currently English. updates, disabled rows, focus, and hydration. - [Expansion tests](./__tests__/DataTableExpansion.test.tsx) cover disclosure semantics, focus recovery, hidden members, and selection compatibility. +- [Bulk-action tests](./__tests__/DataTableBulkActions.test.tsx) cover effective + IDs/counts, announcements, controlled clearing, focus recovery and hydration. - [DataTable browser tests](../../../../e2e/components/DataTable.test.ts) cover themed axe checks, visual snapshots, and a group split across pages. - [Table browser tests](../../../../e2e/components/Table.test.ts) cover explicit diff --git a/packages/react/src/DataTable/DataTable.bulk-actions.stories.tsx b/packages/react/src/DataTable/DataTable.bulk-actions.stories.tsx new file mode 100644 index 00000000000..81d0395905f --- /dev/null +++ b/packages/react/src/DataTable/DataTable.bulk-actions.stories.tsx @@ -0,0 +1,208 @@ +import type {Meta, StoryObj} from '@storybook/react-vite' +import {useId, useRef, useState} from 'react' +import {expect, userEvent} from 'storybook/test' +import {Button} from '../Button' +import {AriaAlert, AriaStatus} from '../live-region' +import {DataTable, Table, type DataTableData, type DataTableRowId} from '.' +import type {Column} from './column' + +export default { + title: 'Experimental/Components/DataTable/Features/Bulk actions', +} satisfies Meta + +interface Repository { + id: number + name: string + visibility: string +} + +const repositories: Array = [ + {id: 1, name: 'primer/react', visibility: 'Public'}, + {id: 2, name: 'primer/css', visibility: 'Public'}, + {id: 3, name: 'github/github', visibility: 'Internal'}, +] +const columns: Array> = [ + {header: 'Repository', field: 'name', rowHeader: true, sortBy: 'alphanumeric'}, + {header: 'Visibility', field: 'visibility'}, +] + +function BulkActionsExample({ + mode, + asyncActions = false, +}: { + mode: 'flat' | 'grouped' | 'mixed' + asyncActions?: boolean +}) { + const titleId = useId() + const [rows, setRows] = useState(repositories) + const [selectedRows, setSelectedRows] = useState>(() => new Set([1])) + const [pending, setPending] = useState(false) + const [error, setError] = useState('') + const [message, setMessage] = useState('') + const addButtonRef = useRef(null) + const publicRows = rows.filter(row => row.visibility === 'Public') + const internalRows = rows.filter(row => row.visibility === 'Internal') + const data: DataTableData = + mode === 'flat' + ? rows + : mode === 'grouped' + ? [ + {groupId: 'public', label: 'Public', rows: publicRows}, + {groupId: 'internal', label: 'Internal', rows: internalRows}, + ] + : [...internalRows, {groupId: 'public', label: 'Public', rows: publicRows}] + + return ( + + Repositories + + + + setSelectedRows(next)} + bulkActionsReturnFocusRef={rows.length === 0 ? addButtonRef : undefined} + renderBulkActions={({selectedRows: effectiveIds, selectedCount, clearSelection}) => ( + <> + {asyncActions ? ( + + ) : null} + + + )} + /> + {error} + {message} + + ) +} + +export const Flat: StoryObj = { + render: () => , + play: async ({canvas}) => { + await userEvent.click(canvas.getByRole('button', {name: 'Repository'})) + await expect(canvas.getByRole('columnheader', {name: 'Repository'})).toHaveAttribute('aria-sort', 'ascending') + await expect(canvas.getByText('1 row selected')).toBeVisible() + }, +} + +export const Grouped: StoryObj = { + render: () => , +} + +export const Mixed: StoryObj = { + render: () => , +} + +export const AsyncActions: StoryObj = { + render: () => , + play: async ({canvas}) => { + await userEvent.click(canvas.getByRole('button', {name: 'Repository'})) + await expect(canvas.getByRole('columnheader', {name: 'Repository'})).toHaveAttribute('aria-sort', 'ascending') + await expect(canvas.getByRole('checkbox', {name: 'Select primer/react'})).toBeChecked() + await expect(canvas.getByRole('button', {name: 'Delete selected'})).toBeEnabled() + }, +} + +export const ComposedTable: StoryObj = { + render: function ComposedTable() { + const titleId = useId() + const checkboxRef = useRef(null) + const [selectedRows, setSelectedRows] = useState>(() => new Set([1])) + const effectiveRows = repositories.filter(row => selectedRows.has(row.id)) + const allSelected = effectiveRows.length === repositories.length + return ( + + Composed repositories + setSelectedRows(new Set())} + onFocusReturn={() => checkboxRef.current?.focus()} + > + + + + + + 0 ? 'some' : 'none'} + onToggleSelect={() => + setSelectedRows(allSelected ? new Set() : new Set(repositories.map(row => row.id))) + } + /> + Repository + + + + {repositories.map(row => ( + + + setSelectedRows(current => { + const next = new Set(current) + if (next.has(row.id)) { + next.delete(row.id) + } else { + next.add(row.id) + } + return next + }) + } + /> + {row.name} + + ))} + +
+
+ ) + }, +} diff --git a/packages/react/src/DataTable/DataTable.docs.json b/packages/react/src/DataTable/DataTable.docs.json index 0cf2dca2360..db8358281ac 100644 --- a/packages/react/src/DataTable/DataTable.docs.json +++ b/packages/react/src/DataTable/DataTable.docs.json @@ -144,6 +144,21 @@ "type": "({ expandedGroups }: { expandedGroups: Set }) => void", "description": "Receive a new expansion set on a disclosure request. Sorting and data replacement do not emit this callback or clear stored IDs." }, + { + "name": "renderBulkActions", + "type": "(context: DataTableBulkActionsContext) => React.ReactNode", + "description": "Render actions for effectively selected rows when rowSelection is enabled. The context contains readonly selectedRows IDs, selectedCount, and clearSelection. Counts and action IDs exclude missing and non-selectable rows. Business operations and their outcomes are consumer-owned." + }, + { + "name": "bulkActionsProps", + "type": "Pick", + "description": "Localize the bulk-action group name, selected-count announcement (including zero), and clear-selection label." + }, + { + "name": "bulkActionsReturnFocusRef", + "type": "React.RefObject", + "description": "Override focus recovery when a focused action disappears. Defaults to select-all, or the table when no selectable rows remain. Does not override focus already moved by the consumer." + }, { "name": "cellPadding", "type": "'condensed' | 'normal' | 'spacious'", @@ -193,6 +208,50 @@ } ], "subcomponents": [ + { + "name": "Table.BulkActions", + "props": [ + { + "name": "selectedCount", + "type": "number", + "required": true, + "description": "The effectively selected row count. Keep the component mounted at zero so count announcements and focus recovery can complete." + }, + { + "name": "onClearSelection", + "type": "() => void", + "required": true, + "description": "Request clearing selection. The consumer owns selection state." + }, + { + "name": "onFocusReturn", + "type": "() => void", + "description": "Choose the recovery destination when a focused action disappears and focus has not moved elsewhere." + }, + { + "name": "getSelectedCountLabel", + "type": "(selectedCount: number) => string", + "description": "Localize the visible and announced selected count, including zero." + }, + { + "name": "clearSelectionLabel", + "type": "string", + "defaultValue": "'Clear selection'", + "description": "Localize the clear-selection button." + }, + { + "name": "aria-label", + "type": "string", + "defaultValue": "'Bulk actions'", + "description": "Name the action group." + }, + { + "name": "children", + "type": "React.ReactNode", + "description": "Consumer-owned action elements in native Tab order, rendered only when selectedCount is positive." + } + ] + }, { "name": "Table", "props": [ diff --git a/packages/react/src/DataTable/DataTable.tsx b/packages/react/src/DataTable/DataTable.tsx index c31ee59f967..21de112878b 100644 --- a/packages/react/src/DataTable/DataTable.tsx +++ b/packages/react/src/DataTable/DataTable.tsx @@ -1,4 +1,4 @@ -import type {ReactElement, ReactNode} from 'react' +import {useRef, type ReactElement, type ReactNode, type RefObject} from 'react' import type {Column} from './column' import {useTable} from './useTable' import type {SortDirection} from './sorting' @@ -16,6 +16,14 @@ import { TableRowSelection, } from './Table' import {TableGroup} from './TableGroup' +import {TableBulkActions, type TableBulkActionsProps} from './TableBulkActions' +import classes from './TableBulkActions.module.css' + +export interface DataTableBulkActionsContext { + selectedRows: ReadonlySet + selectedCount: number + clearSelection: () => void +} // ---------------------------------------------------------------------------- // DataTable @@ -125,6 +133,23 @@ type DataTableBaseProps = { * Handles requests to change the expanded group IDs. */ onExpandedGroupsChange?: ({expandedGroups}: {expandedGroups: Set}) => void + + /** + * Renders actions for effectively selected rows, excluding missing and + * non-selectable IDs. Requires rowSelection. Consumers own business operations. + */ + renderBulkActions?: (context: DataTableBulkActionsContext) => ReactNode + + /** + * Localizes bulk-action labels and the selected-count announcement. + */ + bulkActionsProps?: Pick + + /** + * Overrides the focus recovery target when a focused bulk action disappears. + * Defaults to select-all, or the table when no selectable rows remain. + */ + bulkActionsReturnFocusRef?: RefObject } export type DataTableProps = DataTableBaseProps & { @@ -172,7 +197,12 @@ function DataTableImplementation({ expandedGroups, defaultExpandedGroups, onExpandedGroupsChange, + renderBulkActions, + bulkActionsProps, + bulkActionsReturnFocusRef, }: DataTableProps) { + const selectionCheckboxRef = useRef(null) + const tableRef = useRef(null) const table = useTable({ data, columns, @@ -220,8 +250,10 @@ function DataTableImplementation({ ) - return ( + const renderedTable = ( ({ {rowSelection ? ( ({ )}
) + + if (!rowSelection || !renderBulkActions) { + return renderedTable + } + + return ( +
+ { + const target = bulkActionsReturnFocusRef?.current + if (target?.isConnected) { + target.focus() + } else if (selectionCheckboxRef.current && !selectionCheckboxRef.current.disabled) { + selectionCheckboxRef.current.focus() + } else { + tableRef.current?.focus() + } + }} + > + {selection.selectedCount > 0 + ? renderBulkActions({ + selectedRows: new Set(selection.selectedRows), + selectedCount: selection.selectedCount, + clearSelection: actions.clearSelection, + }) + : null} + + {renderedTable} +
+ ) } const DataTable = DataTableImplementation as DataTableComponent diff --git a/packages/react/src/DataTable/DataTable.types.test.tsx b/packages/react/src/DataTable/DataTable.types.test.tsx index e57d7741c87..80fe983f2ad 100644 --- a/packages/react/src/DataTable/DataTable.types.test.tsx +++ b/packages/react/src/DataTable/DataTable.types.test.tsx @@ -1,6 +1,6 @@ import {lazy} from 'react' import type {Column} from './column' -import {DataTable, type DataTableProps} from './DataTable' +import {DataTable, type DataTableProps, type DataTableBulkActionsContext} from './DataTable' import type {DataTableRowGroup} from './row' import {useTable} from './useTable' import {Table, type DataTableRowId} from '../experimental' @@ -248,6 +248,38 @@ export function shouldAcceptRowSelectionProps() { ) } +export function shouldAcceptBulkActions() { + const context: DataTableBulkActionsContext = { + selectedRows: new Set([1]), + selectedCount: 1, + clearSelection: () => {}, + } + const config = ( + { + const ids: ReadonlySet = selectedRows + // @ts-expect-error Bulk action IDs are read-only. + ids.add(3) + return ( + + ) + }} + bulkActionsProps={{getSelectedCountLabel: count => `${count} selected`}} + /> + ) + const composed = ( + + Actions + + ) + return {config, composed} +} + export function shouldInferMixedSelectionCallbacks() { return ( , 'role'> & { + /** + * The number of effectively selected rows. Keep this component mounted at zero + * so the count announcement and focus recovery can complete. + */ + selectedCount: number + /** + * Requests clearing selection. The consumer owns the selection state. + */ + onClearSelection: () => void + /** + * Restores focus when a focused action disappears. Not called if focus has + * already moved elsewhere, for example into a consumer-owned dialog. + */ + onFocusReturn?: () => void + /** + * Localizes the visible and announced selection count, including zero. + */ + getSelectedCountLabel?: (selectedCount: number) => string + /** + * Localizes the clear-selection button. + */ + clearSelectionLabel?: string +} + +function defaultSelectedCountLabel(selectedCount: number) { + return `${selectedCount} ${selectedCount === 1 ? 'row' : 'rows'} selected` +} + +const TableBulkActions = React.forwardRef(function TableBulkActions( + { + selectedCount, + onClearSelection, + onFocusReturn, + getSelectedCountLabel = defaultSelectedCountLabel, + clearSelectionLabel = 'Clear selection', + 'aria-label': ariaLabel = 'Bulk actions', + className, + children, + ...rest + }, + ref, +) { + const focusedAction = useRef(null) + const active = selectedCount > 0 + + // Recover only focus lost to removed actions, never steal it from a dialog or + // another control. The action owner decides where focus should return. + useLayoutEffect(() => { + const element = focusedAction.current + if (element && !element.isConnected) { + focusedAction.current = null + const document = element.ownerDocument + if (document.activeElement === document.body) { + onFocusReturn?.() + } + } + }) + + const count = ( + + {getSelectedCountLabel(selectedCount)} + + ) + + return ( +
) => { + focusedAction.current = event.target + }, + onBlurCapture: (event: React.FocusEvent) => { + if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) { + focusedAction.current = null + } + }, + }, + rest, + )} + ref={ref} + role={active ? 'group' : undefined} + aria-label={active ? ariaLabel : undefined} + data-component="Table.BulkActions" + data-active={active || undefined} + className={clsx(classes.TableBulkActions, className)} + > + {count} + {active ? ( + <> + +
{children}
+ + ) : null} +
+ ) +}) + +export {TableBulkActions} diff --git a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx new file mode 100644 index 00000000000..a6c201e6dd6 --- /dev/null +++ b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx @@ -0,0 +1,353 @@ +import React, {act} from 'react' +import {render, screen, waitFor, within} from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import {renderToString} from 'react-dom/server' +import {hydrateRoot, type Root} from 'react-dom/client' +import {createPortal} from 'react-dom' +import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest' +import {DataTable, Table, type DataTableBulkActionsContext, type DataTableData, type DataTableRowId} from '..' +import {Button} from '../../Button' +import {getLiveRegion} from '../../live-region/__tests__/test-helpers' +import {implementsClassName} from '../../utils/testing' +import type {Column} from '../column' +import classes from '../TableBulkActions.module.css' + +interface Row { + id: DataTableRowId + name: string +} + +const rows: Array = [ + {id: 1, name: 'Beta'}, + {id: '1', name: 'Alpha'}, + {id: 3, name: 'Gamma'}, +] +const columns: Array> = [{header: 'Name', field: 'name', rowHeader: true, sortBy: true}] + +function renderActions({selectedCount, clearSelection}: DataTableBulkActionsContext) { + return +} + +describe('DataTable bulk actions', () => { + beforeEach(() => { + document.body.appendChild(document.createElement('live-region')) + }) + afterEach(() => { + getLiveRegion().remove() + }) + + it.each(['flat', 'grouped', 'mixed'] as const)('uses effective IDs and counts (%s)', async mode => { + const user = userEvent.setup() + const onAction = vi.fn() + const data: DataTableData = + mode === 'flat' + ? rows + : mode === 'grouped' + ? [{groupId: 'all', label: 'All', rows}] + : [rows[0], {groupId: 'other', label: 'Other', rows: rows.slice(1)}] + render( + ([1, '1', 3, 'missing'])} + isRowSelectable={row => row.id !== 3} + renderBulkActions={({selectedRows, selectedCount}) => ( + + )} + />, + ) + + expect(screen.getByText('2 rows selected')).toBeVisible() + await user.click(screen.getByRole('button', {name: 'Archive'})) + expect(onAction).toHaveBeenLastCalledWith({selectedRows: new Set([1, '1']), selectedCount: 2}) + await user.click(screen.getByRole('button', {name: 'Name'})) + await user.click(screen.getByRole('button', {name: 'Archive'})) + expect(onAction).toHaveBeenLastCalledWith({selectedRows: new Set([1, '1']), selectedCount: 2}) + expect(screen.getByRole('columnheader', {name: 'Name'})).toHaveAttribute('aria-sort', 'ascending') + }) + + it('does not render actions without enabled selection or effectively selected rows', () => { + const renderer = vi.fn(renderActions) + const {rerender} = render( + , + ) + expect(renderer).not.toHaveBeenCalled() + rerender( + , + ) + expect(renderer).not.toHaveBeenCalled() + expect(screen.queryByRole('group', {name: 'Bulk actions'})).not.toBeInTheDocument() + expect(screen.queryByRole('button', {name: 'Clear selection'})).not.toBeInTheDocument() + }) + + it('preserves checkbox focus when actions appear and announces counts including zero', async () => { + const user = userEvent.setup() + render() + expect(getLiveRegion().getMessage('polite')).toBe('') + const checkbox = screen.getByRole('checkbox', {name: 'Select Beta'}) + checkbox.focus() + await user.keyboard(' ') + expect(checkbox).toHaveFocus() + await waitFor(() => expect(getLiveRegion().getMessage('polite')).toBe('1 row selected')) + await user.click(screen.getByRole('checkbox', {name: 'Select Alpha'})) + await waitFor(() => expect(getLiveRegion().getMessage('polite')).toBe('2 rows selected')) + await user.click(screen.getByRole('button', {name: 'Clear selection'})) + await waitFor(() => expect(getLiveRegion().getMessage('polite')).toBe('0 rows selected')) + expect(screen.getByRole('checkbox', {name: 'Select rows'})).toHaveFocus() + expect(screen.queryByRole('group', {name: 'Bulk actions'})).not.toBeInTheDocument() + }) + + it('clears stored IDs through the controlled selection callback without mutating its input', async () => { + const user = userEvent.setup() + const selectedRows = new Set([1, 'missing']) + const onSelectionChange = vi.fn() + const {rerender} = render( + , + ) + await user.click(screen.getByRole('button', {name: 'Apply to 1'})) + expect(onSelectionChange).toHaveBeenLastCalledWith({selectedRows: new Set()}) + expect(selectedRows).toEqual(new Set([1, 'missing'])) + expect(screen.getByRole('button', {name: 'Apply to 1'})).toHaveFocus() + rerender( + , + ) + expect(screen.getByRole('checkbox', {name: 'Select rows'})).toHaveFocus() + }) + + it('recovers focus when deleting the last selected record, including an empty table', async () => { + const user = userEvent.setup() + function Example() { + const [data, setData] = React.useState([rows[0]]) + return ( + ( + + )} + /> + ) + } + render() + await user.click(screen.getByRole('button', {name: 'Delete'})) + expect(screen.getByRole('table')).toHaveFocus() + expect(screen.getByRole('checkbox', {name: 'Select rows'})).toBeDisabled() + expect(screen.queryByRole('button', {name: 'Delete'})).not.toBeInTheDocument() + }) + + it('allows a consumer-selected recovery target', async () => { + const user = userEvent.setup() + function Example() { + const ref = React.useRef(null) + return ( + <> + + + + ) + } + render() + await user.click(screen.getByRole('button', {name: 'Clear selection'})) + expect(screen.getByRole('button', {name: 'Add repository'})).toHaveFocus() + }) + + it('does not steal focus from a consumer-owned action destination', async () => { + const user = userEvent.setup() + function Example() { + const destination = React.useRef(null) + return ( + <> + + ( + + )} + /> + + ) + } + render() + await user.click(screen.getByRole('button', {name: 'Complete'})) + expect(screen.getByRole('button', {name: 'Confirmation'})).toHaveFocus() + }) + + it('recovers focus from portalled actions in the same React subtree', async () => { + const user = userEvent.setup() + function PortalAction({clearSelection}: {clearSelection: () => void}) { + const [open, setOpen] = React.useState(false) + return ( + <> + + {open ? createPortal(, document.body) : null} + + ) + } + render( + } + />, + ) + await user.click(screen.getByRole('button', {name: 'Open actions'})) + await user.click(screen.getByRole('button', {name: 'Apply from portal'})) + expect(screen.getByRole('checkbox', {name: 'Select rows'})).toHaveFocus() + }) + + it('updates effective count after removal without emitting selection changes or stealing outside focus', () => { + const onSelectionChange = vi.fn() + const {rerender} = render( + <> + + ([1, '1'])} + onSelectionChange={onSelectionChange} + renderBulkActions={renderActions} + /> + , + ) + screen.getByRole('button', {name: 'Elsewhere'}).focus() + rerender( + <> + + + , + ) + expect(screen.getByText('1 row selected')).toBeVisible() + expect(onSelectionChange).not.toHaveBeenCalled() + expect(screen.getByRole('button', {name: 'Elsewhere'})).toHaveFocus() + }) + + it('supports localized labels', () => { + render( + `${count} repositories chosen`, + }} + />, + ) + const group = screen.getByRole('group', {name: 'Selected repositories'}) + expect(within(group).getByText('1 repositories chosen')).toBeVisible() + expect(within(group).getByRole('button', {name: 'Deselect repositories'})).toBeVisible() + }) + + it('preserves structure through server rendering and hydration', async () => { + const element = ( + + ) + const container = document.createElement('div') + container.innerHTML = renderToString(element) + document.body.appendChild(container) + const serverTable = within(container).getByRole('table') + expect(within(serverTable).queryByRole('group')).not.toBeInTheDocument() + const onRecoverableError = vi.fn() + let root: Root | undefined + try { + await act(async () => { + root = hydrateRoot(container, element, {onRecoverableError}) + }) + expect(onRecoverableError).not.toHaveBeenCalled() + expect(within(container).getByRole('table')).toBe(serverTable) + expect(within(container).getByText('1 row selected')).toBeVisible() + } finally { + await act(async () => root?.unmount()) + container.remove() + } + }) +}) + +describe('Table.BulkActions', () => { + implementsClassName( + props => {}} {...props} />, + classes.TableBulkActions, + ) + + it('forwards root attributes and ref, preserves child order and native Tab order', async () => { + const user = userEvent.setup() + const ref = React.createRef() + const onClearSelection = vi.fn() + render( + + + + , + ) + const group = screen.getByRole('group', {name: 'Bulk actions'}) + expect(ref.current).toBe(group) + expect(group).toHaveAttribute('data-testid', 'actions') + expect(group).toHaveAttribute('data-component', 'Table.BulkActions') + await user.tab() + expect(screen.getByRole('button', {name: 'Clear selection'})).toHaveFocus() + await user.keyboard('{Enter}') + expect(onClearSelection).toHaveBeenCalledOnce() + await user.tab() + expect(screen.getByRole('button', {name: 'First'})).toHaveFocus() + await user.tab() + expect(screen.getByRole('button', {name: 'Second'})).toHaveFocus() + }) +}) diff --git a/packages/react/src/DataTable/index.ts b/packages/react/src/DataTable/index.ts index 73707fd4d47..1da6ee1f9ae 100644 --- a/packages/react/src/DataTable/index.ts +++ b/packages/react/src/DataTable/index.ts @@ -18,6 +18,7 @@ import { TableSkeleton, } from './Table' import {TableGroup} from './TableGroup' +import {TableBulkActions} from './TableBulkActions' import {Pagination} from './Pagination' import type {SlotMarker} from '../utils/types/Slots' @@ -27,6 +28,7 @@ const Table: typeof TableImpl & Title: typeof TableTitle Subtitle: typeof TableSubtitle Actions: typeof TableActions + BulkActions: typeof TableBulkActions Divider: typeof TableDivider Skeleton: typeof TableSkeleton Head: typeof TableHead @@ -45,6 +47,7 @@ const Table: typeof TableImpl & Title: TableTitle, Subtitle: TableSubtitle, Actions: TableActions, + BulkActions: TableBulkActions, Divider: TableDivider, Skeleton: TableSkeleton, Head: TableHead, @@ -61,7 +64,8 @@ const Table: typeof TableImpl & }) export {DataTable, Table} -export type {DataTableProps} from './DataTable' +export type {DataTableProps, DataTableBulkActionsContext} from './DataTable' +export type {TableBulkActionsProps} from './TableBulkActions' export type { TableProps, TableHeadProps, diff --git a/packages/react/src/DataTable/useTable.ts b/packages/react/src/DataTable/useTable.ts index 23c9cf40fc8..a4656d8ca75 100644 --- a/packages/react/src/DataTable/useTable.ts +++ b/packages/react/src/DataTable/useTable.ts @@ -31,6 +31,7 @@ interface Table { toggleRowSelection: (row: Row) => void toggleAllRows: () => void toggleGroupExpansion: (group: RowGroup) => void + clearSelection: () => void } selection: { headerId: string @@ -414,6 +415,9 @@ export function useTable({ toggleRowSelection, toggleAllRows, toggleGroupExpansion, + clearSelection: () => { + setSelectedRows(new Set()) + }, }, selection: { headerId: `${tableId}-selection-column`, diff --git a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap index d83c4636a30..8d714899f42 100644 --- a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap +++ b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap @@ -325,6 +325,7 @@ exports[`@primer/react/experimental > should not update exports without a semver "type ColumnWidth", "createColumnHelper", "DataTable", + "type DataTableBulkActionsContext", "type DataTableData", "type DataTableProps", "type DataTableRowGroup", @@ -385,6 +386,7 @@ exports[`@primer/react/experimental > should not update exports without a semver "Table", "type TableActionsProps", "type TableBodyProps", + "type TableBulkActionsProps", "type TableCellProps", "type TableContainerProps", "type TableGroupProps", diff --git a/packages/react/src/experimental/index.ts b/packages/react/src/experimental/index.ts index 3d7dc23cf6a..309eb888b96 100644 --- a/packages/react/src/experimental/index.ts +++ b/packages/react/src/experimental/index.ts @@ -28,6 +28,8 @@ export type { export {DataTable, Table, createColumnHelper} from '../DataTable' export type { DataTableProps, + DataTableBulkActionsContext, + TableBulkActionsProps, DataTableData, DataTableRowGroup, DataTableRowId, From 671f36eff412ed99400afad447b5f63eb0565b5e Mon Sep 17 00:00:00 2001 From: Ricky Zhang Date: Tue, 13 Oct 2026 14:20:09 -0400 Subject: [PATCH 02/16] fix(DataTable): preserve compiler-safe focus handling and SSR tests Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../react/src/DataTable/TableBulkActions.tsx | 31 ++++++++++--------- .../__tests__/DataTableBulkActions.test.tsx | 20 +++++++++++- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/packages/react/src/DataTable/TableBulkActions.tsx b/packages/react/src/DataTable/TableBulkActions.tsx index 8a9b7d39530..dba56a8d4d0 100644 --- a/packages/react/src/DataTable/TableBulkActions.tsx +++ b/packages/react/src/DataTable/TableBulkActions.tsx @@ -3,7 +3,6 @@ import {clsx} from 'clsx' import {Button} from '../Button' import {AriaStatus} from '../live-region' import VisuallyHidden from '../_VisuallyHidden' -import {mergeProps} from '../utils/mergeProps' import useLayoutEffect from '../utils/useIsomorphicLayoutEffect' import classes from './TableBulkActions.module.css' @@ -46,6 +45,8 @@ const TableBulkActions = React.forwardRef 'aria-label': ariaLabel = 'Bulk actions', className, children, + onFocusCapture, + onBlurCapture, ...rest }, ref, @@ -74,19 +75,21 @@ const TableBulkActions = React.forwardRef return (
) => { - focusedAction.current = event.target - }, - onBlurCapture: (event: React.FocusEvent) => { - if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) { - focusedAction.current = null - } - }, - }, - rest, - )} + {...rest} + onFocusCapture={event => { + focusedAction.current = event.target + if (!event.defaultPrevented) { + onFocusCapture?.(event) + } + }} + onBlurCapture={event => { + if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) { + focusedAction.current = null + } + if (!event.defaultPrevented) { + onBlurCapture?.(event) + } + }} ref={ref} role={active ? 'group' : undefined} aria-label={active ? ariaLabel : undefined} diff --git a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx index a6c201e6dd6..16528dcdc84 100644 --- a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx +++ b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx @@ -301,6 +301,7 @@ describe('DataTable bulk actions', () => { /> ) const container = document.createElement('div') + const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}) container.innerHTML = renderToString(element) document.body.appendChild(container) const serverTable = within(container).getByRole('table') @@ -312,9 +313,15 @@ describe('DataTable bulk actions', () => { root = hydrateRoot(container, element, {onRecoverableError}) }) expect(onRecoverableError).not.toHaveBeenCalled() + expect( + consoleErrorSpy.mock.calls.every(([message]) => + String(message).includes('useLayoutEffect does nothing on the server'), + ), + ).toBe(true) expect(within(container).getByRole('table')).toBe(serverTable) expect(within(container).getByText('1 row selected')).toBeVisible() } finally { + consoleErrorSpy.mockRestore() await act(async () => root?.unmount()) container.remove() } @@ -331,8 +338,17 @@ describe('Table.BulkActions', () => { const user = userEvent.setup() const ref = React.createRef() const onClearSelection = vi.fn() + const onFocusCapture = vi.fn() + const onBlurCapture = vi.fn() render( - + , @@ -343,10 +359,12 @@ describe('Table.BulkActions', () => { expect(group).toHaveAttribute('data-component', 'Table.BulkActions') await user.tab() expect(screen.getByRole('button', {name: 'Clear selection'})).toHaveFocus() + expect(onFocusCapture).toHaveBeenCalledOnce() await user.keyboard('{Enter}') expect(onClearSelection).toHaveBeenCalledOnce() await user.tab() expect(screen.getByRole('button', {name: 'First'})).toHaveFocus() + expect(onBlurCapture).toHaveBeenCalledOnce() await user.tab() expect(screen.getByRole('button', {name: 'Second'})).toHaveFocus() }) From 7bf80fab8fc69209b6186942e737dfbe56d3dacc Mon Sep 17 00:00:00 2001 From: rickyzhangca <16908811+rickyzhangca@users.noreply.github.com> Date: Tue, 13 Oct 2026 18:22:11 +0000 Subject: [PATCH 03/16] test(vrt): update snapshots --- .../DataTable-BulkActions-Mixed-dark-linux.png | Bin 0 -> 21885 bytes .../DataTable-BulkActions-Mixed-light-linux.png | Bin 0 -> 21924 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 .playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-dark-linux.png create mode 100644 .playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-light-linux.png diff --git a/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-dark-linux.png b/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-dark-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..327c4acd4be1897d42721d3a555689b8828c9478 GIT binary patch literal 21885 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 z z;xNplNt?yCYulcaPAo$V)o-EeJvPSS);-J;R-I?wuIuaT#m2P)el7HEifv#Abg;KC zcW!*hPgv~QF1J4S+~|hPsmn(siTR%$Y)nv6QNHE9*p(0^y5X}n%!5JsG&AvJv|rO>my`47_{YzMNbh+d=df|#p0cay6e#wxta zKOUL~o2e%~m>G>~w6$HC5ry*_Hr$gu)BFDZ9<|iRR_t4O>XO`aS=-*DNd4F_F`jzF zIl|b%A$7cx7H|himb9}-eW@M?M@Q;)+(ZfP)gFB}vvLtHwtpmb;M=dtW+{vkU+WRg+ zu76Y@SynnGW8au$|XR(7r!f>S=}1kdw+57gQf|7V%{=N$!e(3eL7R#sMV zdU}^G1=Q6w&1gr*#>S?lr6pViJi0K3mT(R(Zfdu1n+d=lEp2TY8X8v@mm897j_Yh;i_4tEj#BjqF?I(=mHnTQ)W}F0b*XL@jywx+B2hJ?}${ z9Zu3}_*heD=nwvWrtDL<)#c?NF-?u6kI~WG+}tXvs@hswFHm8zjBZ?c+^rjm(NKD%;E{rK_52*W0HM#EY z9xgN#ewoA0K+G(x~_w}uuV|~;GTt>e}E_R=ra$b`# zs&5XZ4+sbVJ7({u6c+Vz=EoOB8b;w=-87355%{KVt8yW?afR39(VyV%AEwqsvNK>q zW;ttmV_J>gT5?8GJPR@|qJwZJ^Fm3{u!>mIgT?mH!mwg@)0*dxA5GWNul2j8BcwMZ zDo&5%&0_iotKnNDB4v%tAshrAQ#^ShJ222+SxF=|*dMhvCW*qcv$AMu-F?6&+uYh( zU#ABG;D_V_dp*5_@3Mh$+{dM+Qt8eXt?X4Nakcg&$Ocz)!Q#E_>CY^<2jh?}ptmG`ttEh8<(g&& z*O0!Wvqo?f=ao{|r3go(>LV{7$noC3nIGQL#%4Q;HBdhM7T5>HU0W!rse97nc>UJB zb_|F$N_P+S2_WenKLxt*v#f^xj`qgFuV9jSqeVvJlk25bL+_1pn^I5wk7s zsxT%A!wR30Lj+RD!7I>X!?4P?=*Yrvzb|kW|L%m!cf@h@fk)>uh@Qlwxk#z{!yx3q z8z!0K7w>9%oVMIp9_}{|I~rEojR`1AGFvan5X8n%K0Q)CXILcB53I~*cen&Q_;|C_ zpS_TBZ8W_?w;C?B-sw5yR;y96TAW0CdX6gnsz4s*TE(P;ty33=>}b6@(o@isb}g0A z%F%kIJ`|oto0K3UnaO8*KVcJwsjlistkb2dl@JjT)ql%W(oaSpE8`ZEOS#J5BZLF0EK@DE!5u$<+D;r5?jEJ-~ec7q94e)NKU@AIG(l?|{{GNGhsDMSrqhVU@1cf`)>dj)F@;TU&`D(Cdb+_yEU}GSox!^51wf9`O zC=UXfIgF@5uy}Wewbm>gjrIF^fKcm^zZ!p%oZOm%50SYjl?kkXQ9myazS+ly!Y*QOd`5b`< z-}{)9M0f3)^ZqD53(MAQDjZ~#M(r#x8HLyy65lEz9!;LUs_Qi#9;8vx zRNLUzg+Fvxn7l3=#ld`1O{q&S2 z72DYTqye_Q6DvXWdofce@7btv6Ppq`-c+O7QOD>aUU*9m?mc!>VEe=+ma5?g7>!cv2ZMkp#Q-!RWma3 zUCX;$k{+HrG~6%kAyhJGW`8^m)K;L42IB$A(JRrMDowHYR_lsi9f52uC&Xr5rl2T* z;&O_iQ}u_NataFcld=c|qI^*`S;#i!!-of6+vKpZFN)FUr__^m?hq*{i>VVTtos@r zr4zPr<^4AbB;hzmpSaR$3G{#m{31>R`S?Co1t60@fBqbGLgi09kDP5iJrR-gT7D@n zzX*oB$va3(3n1L#X2PEw7BrcU-(E_i5QCtliR;?-jEtpy)tZfR6m(|?6V9cjK+PFH zCJxYhvhALHo@xzGPe@GLX>1TDr(TCoRE3WM^|0c_&RslHNUg6C0RQrdm} zhAgRr)021yIq!~P$$P?n8|O`h#+GJhZ>bJx%+8nO&g7_U%q>ssRd(CvD~uQnGN!Aa za@ca#5>FDE3y~BQ(Z`z3*AfkuSYB|~Fy%;Er-k;=t1BsKLGx0J9AU6G2n&Gu3=ws) z;rOv~>$Ty$=+s#Enc3!K(MG=pza~|}Z-n<-=EKnP07@nS#9%In$0a~OIauEc3lDE{ z@caG_^=$ji_ZE5iyAh2)o={YY#qq)ItUksi9gGGZj_v^ZOZ`!M5Xa8W4#3oXwpo^| zy;Y8Ds>!1C4%hxH&MflV!usK>olBi5=y?rEnxaoQi^MQ|3q6xQuZrEmR%RxgV!Zbj z_xaFQAxsh#EHX}o2?>#*k?9Zo`;RG>C|Yv)gt%7qIXT;gMTSM4CaMK-g7JC#~BpNwtcDiFc_xV=M8Ov^7og(oo(wddTQ0 z4%c2UT7>lLJV4YL8XAiB6HiXRKnDb3mOA(Ft#6yc>J#XpCCN!iw-|0=BSIcV#SLfK z)0ZxErXvI1n*dT87IX?|I4xFFg(vhAy_vB6uyKReOlf8-z}Xn0|K^YP6f9CoDk|%x z7Omu0ZtHku{?yjYT6O2+EBO)MF6r+J`xv!jW*tpO7g_st{m=8WJ-)T!qC_$0v)N|l z+1XhM_f;{g!Q34h4mwIPujSrvuP=x=jNgkGEmw$4Nm&QtSFkvqrWHwJNp$K-6A=*s zpf?ibYHweV4lP+7fj@Fn*IeDB#vu;qNOw#vuJN%}*!01M3*mr0{3RhOd(ODx z%{N%!;+hkPBQBW2G+Bx6kF5N|-D+O$jpL@y?(@IJ?w)lewOlGOOx$<<>f73#ak>!H zIcbcknZE|zqVw*NqwGcGE~KyX7xah{_HzD+%~)E41%v%$u-K$NEizJ{Mbc(EOF91O zrWwZHM8}`0>|R013|X zL8+%>FK(65USWEuGc_`JwV!CZD=8au5?f}W<~t7)^PstFJL2bcN5o|r?F z+&h?n^BLBBdfu9)j1&+MAf;B~x)?!fMZ)(e2t=kYR+$A;-7Rj)D%g2X9eF)r*|%?! zjVbq;PhvWeOfSu1V-ut2%y)?v#^L)hNK?2&R;FWK0aHv8zYJHg^~r90o_g~#RQcT49KDB!kZW%wea>cKUvJ8FsV=(F=2`zri&e^bh4 z`&-yPr7OiAP%dRsaq+H8{(Ko2xzIQz|5nE2o9-Lq8!VCS9rhsI!KIrW7}#3pzLuk& zen;dA!|rzgJ-vYvRZ3W~PJfT1r2gAB@^r&#*5UJUL6>~wt<;YnQ&MA5E(=`z7CZue z2Oua^+9$`wi699-EIZ=FWBD+aYjhVboY%SgF*5>sQ1hbX=KE`_oQt$cfMRCSZ zOZ)s<`$B+Oy{jbuP~*>Odi9*gpR0SMo~3K`bw4&c%q;K>xwUO+NzUq60&Zy$pjn^Fp+O0Lb4qt&3$^vQYQI`W($?k}$< z8I4awhHwwg&>CdhwL@YE$Td$V_TJyb}@R#)yzbfAD>MA z9GxSco%uwqXcvrPtZb8#VqJx$2KacrkEa?A?M@PIg)m8l;kCpVm`h{in`<}T1`yx4PN%5+4Wd&qBqCG}q%23foih_X>~x@%Mu zwZd5tNkuucerlc9@$(tqs_XKdAQm-wL>>6fD`Hp;pZm_vPQZKVd$iR20s`D;9E~Kh zKXdX%K-(&wYrDr_RqJDPGbXFHw)Txe5KAbRHk1%mn8HQR!~2oEPL)zu4wLzZMl06-hQE%aXt6 zX*hmCPWD!-pUS=;4b3kL#iKlaVZlg{2P6qo=`mN+Q&TN1>~nry=3Z7w7%3nS z3vF#bDH4GM?TF56S5Z||45NnuDX)#C6i^&zH5_-X73WfZ zpx2=nvF$B-ZIIJveTTpLmZS8-!$HM#*vMdl>sG(yW>L}HoRSySRZ_o^Y$wvv(%tPX zhQ9>B7d9W$(uzsf{?BK1G~lwoj|U3*KOR=~-{5kxzTN+=$k_|NsU)9c$b!nBstDf* zVTg{tRa93cF5wnST5gYAEw3Fu96DL`zS7&@$LF6A7nPc3jocxY%R+zkPUwrp^B4Jj zR~FhOnwy^5SA@RaqBlITGBhL#aKm546<2vL6n?F2ADEt>7xHc5=t>fWBE5ZlBp$|L zT$eoLfya>j;Mb}u)2elj ztQ+qF0$N&{u;6Zm)m|Hw6PlXP;&)tR+XA)Db0>giKeb~K`)Y>D$}dPBy;}tzD-#!F zEze~N#puqTCYkvMM@I5BL|L1VdFe2ixDqMBoVYFS@)X6p=+zzz$uWiRwnN6KMn@+xF;hOW)=z?qgQGPoL;1;*+3r*fwl?}uB69~)GFYtJ(f@;smv?i2C3{(eYwzVm;x3ny@i~sS*QRs$AJ(`JzW^Zp*H)4T_@mM5ZYe-jRI~^}m zkK95}PNuvu8uFag!RGm$Ua_*ue*E~czt4fbzTp943q{i!$s*xVG5sjgZ@896wxa;JUSmisLb&lkQD3 zsc#nGUJpsfF;h^4^1?BW&uzYr^lWu+Oiav?xX&H3Cj~S>GjO6QT`_@}bRFUW9DYhx1 zd=B$WQ6Pyf+AObm46{QXcBcZ9!TZRY478kaZEbDUaGcXysqVQ-HK7 zdAgK7tIxnSv}sb`^b?@;D#wXoR8sv>mrj<;P;PE6IVb03vW5hw_kl8A+m9rtQll)sd>(nB(`aaLgm>1lvbMJU^{3A79Uo(IRGUs}Uy)s#Ei$Z@_THTjXB=sk zzu&M3;xA#*mL9urf| zCN5sm5gry6!_h+OnQ>zGB>kSZc&(DHqLR`L9$vKFNZvq=b0!&*SWz)JI7kli{EWjT z^c_Fmc6D|QLck)L&910$hp=TlO&w4a)NgsC~ai5=gg!08J#hTjpmANO2%)Xy) zWj2wrc#)KTH0w^rYLWSF0*Sh#(%`1?U>&3@i=CWQO>Mb``HUNKK^M61FT;TA=GL*u z@X&xR=C+~!ix=}Dv>jn#VJOs^h&^GofX8rsa%WA}0;D9H`#ZU}+O#EYAxYDu^;ft) zix#q45O&#Lj`GB=5XS9GHn1q=POjQ|XuPo{WpN`p1hxh8I~Mk%PT5Q@FN?}&ZYFtg!s30C{{JPx_D1+zU*xZBH?FS zxAbu<3xGUe7SmxyL9X^LJE3{gebp;f%=yWgw9kHNURhajfXPr_AJv~!dSuhh^tXKt zB=PShH_JKC57v3ju$qz(kM%+EyR*YUW2M05XBM%>#lPW24^=A1=Ia8Xn1Rrve88f6 zWB{EZJu=k}V8+d4YVf@kqVlF+Ja|&)>)h6lt2jHO#l) z-E{4TRZu!sRuKGNI2C_PCiI{0yc88Zj9`+;y2p_&=4|{M*%`TH=I>r@vCWp^51G&L z`P75Mgu}H{koVKMQ&7&wNAd~3il1;r7^r#tbm8G~oZ^DpFpkj*a&z!JTx*F~2e6j} zW|AP8_M7Ezkk`$A0V1uv>wY)b!RLR8{;SSmwqsU3=Cq+-SM5ps*yINo6A8LKvfbUa z{bUo=;X=CK|InrE7Ar8bxH+?`*Y%^nEP)?j7ii;?#^QJPN!J#F(m8LLb~SdRC$~5v z*xA_V1Un}uGxSpHLgMuFZNC1(Ru;KYPc;n`MZ@Ao%d4yYdtIWi785D7e0WkT@|5Skn7&k*>O>WckDr2V7}c=4IMuk6PCr?j z0J&Uy-D7^aFM!H#$Ovq~Ph@2~2sLEex39ad?kxgeutjV4RK1AP`25@)>*D(9{>rId zd@&7&>h%lkYAN^A+9Q}Hs!o>73LPDq;@sCneb4cQj59MPb#B+z<~YJ+JZ77iWiZXk zary=es^>vD3eM2L$lGHmYxSiOGbkAu@t*7CNYR?q`dlQdwmL4|Vo6&iES!^` zo_?o;^T_2T0}DM_n)=w-SokgBTT*s9OA)ESF@e}$c3z(T%&HLSFi~f@NN+}Y^TAik z0=@H-1ILl7qO92F?Q4zAyj-#EwXkNcST4t@I^DvN;tl+8G90~gvR1h^=rks<1xwqR zYh{t~pRJ_h5pkRpGN1k9BH6aOK&#(?m1?sKHbopH=?u{h$FkL6SI$qf#9XKIINr6y zx9CFjiuHjwuinvASFjX&FYzB*K)nyYCo?Ur@Y3lPhPYY3x6~7wB>Lb%?%V=f6}br| z*W4TcyA9X(n4pcjym~i!e5n1Nk3+hWPL7X(j}u^)l4DC%sdU8Z20iZ|z{_#RWp%Kv zW>jDEc%<00x--3&-av*J=nY#~?qiLJSfC~QCKKDIU@lDq`~xrsCK{f&YuB!+mvs~c zy)0ExQ@gG#H8txm)_1s70ENxXHubl(WFy?wcOa{?%@hF9ad*sN(SAn1y;{=B=F&#p zMVJ^VGT(Awd$&>w94c@UC{IaE88o9xpEjxD<>j?#2{)>EsTr#jn}pg0l-}!Ir!#Q^ zjtRExF-476I7--Te^Ma-l9dx`39OO8bbmhTQ{xVSV^O4hoD?OqYg@vsxzU+8_gFP17W6NZU0o=TzE1#W~hSmpJ1@)ZnRGz((p%onR5e|J$a5p0l zbV+1jI6d5;88~PRpdJ|>UhIEL<`o3mv6Lv-5qCbnu_3h;c-$JvgmnA1W1&C<9$HbH zZ@GPSF>q~vg+LdH4|=+$95)+SJhrg0)r!i>+;02(1j#+?BEw3nu9L-s)Cs|C)$*@j zb2UCcdG_oX0}J%GSM=?04DrBp3k#g9xJuWhl8I*Gd7aaFz_8=^Z5jV{vqSu$3?$8p z8sw9Qam4*R?Wm}0U@n59mG?G@2I4jqZ{yY9J|YU<+UU=O;_&uq`^V7C@67}K{rRh_ zNm*J`4c_G-vuQtEd`bWYtYj%8PRpLv8nCy1Q2g_U(W2;}UcOEnd<$D(ZjM6|&w>6J zo1E;kzO0$GFI6xHHrQ#lod4veQz)9OKHhFxlg%ki^6?+gz+?k`u~7+QDhk~+;Glii z^zLa%o%`wjhP|ED2`GU$*qSJbL0h{UgZusb^2dw`UHn3g?%vmGi096a+Am+4U;&BA zMnLLvClb!T_C6;?7q42WocM)z?*oF$gV!GVPW9WuQHqzPQ}T561_pF8l)Nqr0 zC;yD@^H103+z+jR5B?P8=GHl;vaNGz>7hF31wzqV!IR(Pm`Hw^GwygdPIf^#iPlbxtRYi1fVN&(0{WmtJ>WfY5tt>6GateT?M@Dwt`_jl{Yg1E@ zrJkAxzlGgMzB_(($Wn&K)!CVI_3~}NQ{d?1Y^7K(9P-fb<;(5;m4REryF9B`8sS(; zm-%NdS|78rEWvUHW++_)0}{CTE2=CFRaITRH72QDE_M*}Zh@G)rWrr{{|s))R@0DE0j5qwN61M}2lSc3`*B;Eb!RR6S&t zqNJqMD>0>YUW+3Elb>1ZvxMH6Mo?IB4dS_lrMi6iI>ca%tMo=CPn_Ox+$jYAFWxa{bR<`TI4 zBLPeL!;BS{B;&}ipz9r1n8wX&U9v!S=snyeZ(d*@DQjV2VLy`Z$NS&`E9+jL#El8~ zWKCa`N5)NfB$s~P(Vg3CkW?5iLjP^3C}Hm{K81&l$3;o&;D|$W;Gl* z4XS|i(#%h|qo=1N*TO(Q0ph(x84HS1bj~fU?6OHWxZd|)lPiB$-P#(<5x=x~?>Iq{ zt&S}1?!Ss$|NBz8UR|N383U95T>RuG>A!j$!w&L1|4WM>$fGm?!sNFQ4F!%4W}OKs zgQvE4)&$%6;OAyPS9R*HLbq2q*MaSlR|MBCl};tW{1 zIl*PQ+!DS9s?=~5w$ZynUPJi);bHU*H%)H@0y9!SAu)A>%*z>Aj2p+=6n&{!qzf~Y zn}NNIGii;`EdhK>8i0X#nPN30s-oL=IEUM{bpZ_KhYOvaZk-=&qFnH+pcH*eIZUo>`RubiD(6 ze%e@ULel{#I@htF%IsBHnKKQQ(Q1dGGWjk;pb@-Y`kiImw7U4P4$t_c_+2W9)Y5(@ z`CE=n9O<{kyzUEet4Q7ifD_*W)H{OnNlZff^~f)Pxbe^7H+@j~I(c_Dft;p8iq1P0 ztHG5LO8Z=0fj{kO;D78?c!J+Nu+rE7@%do2Ke_*zs#2Ko)jscjh65s8Djs} z&n3T;-5+oVPgf*5@19z#du6LHnIXWmY=_L`ylscE}JsaElNq&c{0;ghmiSBgPTtM$Plj>oh@3=nBx259P_$jh?@ zGwfAGh#wwE@wMnk^+TsA?3T=BG+)oL3*e+Fq<$a9jt%82dDS-2tF zIYw<~Ua@X74wYcJudWMx$NJ1ti21>`=+{f#RG?Tr%JJmM6OCRuBgSMvC}o~04vF^CFEN6S+jMqyAr97$Tj3abK`W49 zg)yY`lm{%yR)^%#QMm5C4ZIS952j(iPxcBXHCID#$+x&JH>Qpw#B`t^DQT7I11~oR z8#@3zxuOBMx-2zfU{iBzsHHptYyY?4KZCv37`)d`P7vA0&}MGavMW*-&#uh+} zgR-6x0hR?yYR&Uki2B6DT75LpAGwo-H7(63FHS4YJp- z=tTaZ;av!s5kNV4#i!)7F9jS*u2FkCtJ!726k$F z4CMc{;D4fT8)sS-HTZP2)mH;H463$F!AD<15kC9pr?6U3V!>lnm0KM;b`l9{F2^ei zyztNW7P}N8nFJpQ+?be~qiLEeT%5UMwGRq)S2T;p!&U}p$-Mf&b~6V&z0wt$DtR}I z(=A@u=zN`O@7F@X?5wUc(rAAltKByJb0?UN4oUU(>(}jr9cdSmb>RM!F%ws$a}5fz_0y;+eQgwwNFvCf_?#Zit8UcS`5*NufSg(#0x`?(cj2w+77B`OYx^C zeCEs@!*UvIcg^iBb~flSaiC}Qo}1SP=HFhTmUdm-KV$LNP*VEiL-ghZ0DK5Pa~Mp{SWepW96#`zWgKCZrwtxHwDu|puC1P+kH72u}Z?uKaLc&*%hA3 zfxK4aQ33{JV4MF>bnu#BEi~R-r>^n+WUx5fFL}}AjaKK7m~(+Wm-^dy=oIkTfxT)u zltGY`!JdAv^=6xQO?1$|ij9qvheJ@A(|3nN9$pcPxo4#%gbgQ_iNt3c>r!%7en60m zru&t%?KL)N@_?f-f3LN)NKSEycl)|I=3m)F~ytbUl3OUSMTz zYtWg{^zL1O`Db(J6Vi|ZT`{!Avt-fS+HCWXMj`s+^-u;YCnwDUH4`~y2)B?vsV$#A zm(_6RRu&!I4nA5tL zoa+?M+j^m$_A=Qc8Uf7bD*y8n7}f>^y3>s*pM}*SRU;9jiP4~q@1LQ1g@%>x6IDeM z)u4{pa%^{Ds?J>-PP7Gj5JWHNJ7#l|(?e#Blj%>TXTVn}jJ7}II%iZ)D3Y0~;)&ShAK#8f?etO`FK z&N%xB7{xSjIX69~r#~A-MS=Qv|Ev|rWwK}UziKjz?WWft!=mu1U7#7PZoD6n@Z3Dh z!4Thn`m{sSLXWL}zK90uy>)jQt$JDkl8|LCYX&q(p~N|92*iln&(9Am;=1*mEKma; zK*h*jl`9~4OW4jAauIX|~jvEb6`c<@9j#3Jd=aV8Q4p z*z|N=Y-(-^XOc3cOcV3|sBdMJ-&6)IG0jwn0Hu$0fq@D@I|7;=2~BW*|G%IKhMPB4 zlBHRtdHt6^+`*hRoHRyCgF&$yFU-4H7$s~K_R#8zAQakj|;|xg} zkoJRlgS?A2hx(;73DKjscR+Z zCVO;uanTACv7UiC`%s2*|EY(il-)}PjeDPsnsq|o*B*bDC2u}y`jh4c*`v}I5k8eM zUtW}|sH>|hsR)QxYrrWn?#ihI>fq2w`VL?+W82CU-@|fzh>EH%E&=9xD=s}cJ_D@> zHTm|m`1TS7c0XyF@P%P=WHFo))(XJpt zhBcf~1egO1CpUR?G z2YDoeM3q*S5HNou6}PsC22oEMUxa1@DfY zQiNhI>Fev0%#Z*bB%L|q$}Bs8bx|cr(!k6N$ZG>iioth5;#dn4Sp{S>kQ7!_ROFQW z1W=8=LpS*%D%oRX(*!1N+dp58McB8;Z~{C(R4^h2wy(kEzJ-o>nbRc$XM4NVw`jl9 zizeu^6Gphr+Nv?yO|e1g18^RZy$ZWNOOpbb_p5vKkGRik+OM;l_Qc-X%PURXb@4Nb z*W~i`JpoeIbgfaE;MK&zN=x>rZyv*Keb{ZnLdCeaxaq&xxpFLX_9e;bO z*lpqQ!NGYu{n4a!eleEO7owDY>*h|AiE__yWs< zPQUhEmFq(+#Dcmxy=F=p*Mp4p#wTz8ku6j2xYnjtc>$c96(TxFy8i#|{X4+drJJp! z03~4TDZp2VP8EBn?Tm7Hw9HGThw(ci6I z34dK#(i+qK6}K-N7kJNuKY`U&z}TfiOO>Z%5V6ofIzi4G`xiJ6Y*Odv3Qc`}P zkTG6Kmy#;H5pLQ6=BLmXORI%XF+s7h;qPN(OM~;kJR~)J8q?O zT>rmKF0a331NHll1Jb(#Nn*qQ>v#42`x*Wp8?ZPWjWmdKI;Vst00bJVi~s-t literal 0 HcmV?d00001 diff --git a/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-light-linux.png b/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-light-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..5017b68354f40b2006739ba5dd6702c78b2fb021 GIT binary patch literal 21924 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 Date: Tue, 13 Oct 2026 14:48:38 -0400 Subject: [PATCH 04/16] fix(DataTable): respect focus leaving bulk actions Clear stale action focus after clicks on non-interactive content, exercise real menu keyboard recovery, and condense the accessibility contract. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../src/DataTable/DataTable.accessibility.md | 99 ++++--------------- .../react/src/DataTable/DataTable.docs.json | 2 +- .../react/src/DataTable/TableBulkActions.tsx | 4 +- .../__tests__/DataTableBulkActions.test.tsx | 56 ++++++++--- 4 files changed, 67 insertions(+), 94 deletions(-) diff --git a/packages/react/src/DataTable/DataTable.accessibility.md b/packages/react/src/DataTable/DataTable.accessibility.md index b7bd09e9843..8615aa20057 100644 --- a/packages/react/src/DataTable/DataTable.accessibility.md +++ b/packages/react/src/DataTable/DataTable.accessibility.md @@ -274,84 +274,27 @@ row count. The generated count description is currently English. ## Bulk actions -`DataTable` composes `Table.BulkActions` when `rowSelection` and -`renderBulkActions` are provided. The render callback receives -`{selectedRows, selectedCount, clearSelection}`. The IDs and count are the same -effective selection: only currently supplied, selectable rows qualify. Missing -and non-selectable IDs remain in the owner's set but never reach business actions. -Sorting and refreshes preserve the contract; collapsing groups must only change -presentation, not remove their members from the selection model. - -`clearSelection` requests an empty selection, including previously retained IDs. -Controlled owners must apply `onSelectionChange` for it to take effect. No second -selection state is introduced. Page/filter owners still clear selection on scope -changes; query-wide and group-level select-all are not supported. - -The action group sits **above**, not over, the table header, following the -[focus-obscured finding](https://github.com/github/accessibility/issues/10267). -Sorting and selection controls remain visible and usable. It is a named -`role="group"`, not an ARIA toolbar: actions use native Tab/Shift+Tab navigation, -and the component does not impose arrow-key navigation on consumer children. -Use Primer buttons and menus with visible, non-color-only focus indicators. - -The selection tally stays mounted at zero (visually hidden), and uses the shared -`AriaStatus` announcement primitive. Count changes include deselection to zero. -`bulkActionsProps` localizes the action group's `aria-label`, clear button label, -and `getSelectedCountLabel(count)` (including zero). -The [follow-up audit](https://github.com/github/accessibility/issues/10807) -reports historical VoiceOver/Safari failures with Shadow DOM live regions in -IndexTable. This implementation reuses Primer's current announcement primitive; -automated announcement assertions do not establish VoiceOver support. Manual -VoiceOver/Safari verification remains required alongside NVDA and JAWS. - -### Focus and operation ownership - -- Showing actions does not move focus from the activating checkbox. -- Hiding actions only recovers focus if the focused action was removed and focus - fell back to the document body. It does not steal focus from a dialog, toast - action, or other consumer-selected destination. -- Config recovery targets select-all; with no selectable rows, it targets the - table programmatically without adding a Tab stop. `bulkActionsReturnFocusRef` - overrides this target, for example with an Add button for an empty table. -- `Table.BulkActions` consumers keep the component mounted at zero and supply - `onFocusReturn` to choose their recovery target. Consumers supply the effective - count, clear callback, and children in their intended order. -- Consumers own requests, pending/error states, success/failure announcements, - permanent removal reconciliation, and business-specific focus (including - closing dialogs or replacing the entire table). Clearing is explicit, not - automatic after an action. Failed operations should retain selection for retry. -- For asynchronous actions, snapshot the callback's effective IDs at activation. - Apply success/failure to that operation's IDs, not a subsequently changed - selection. Disabling actions while pending does not disable row checkboxes; - consumers decide whether to allow additional selection during the request. - -For example: - -```tsx - setSelectedRows(selectedRows)} - renderBulkActions={({selectedRows: effectiveIds, selectedCount, clearSelection}) => ( - - )} -/> -``` - -The snippet illustrates synchronous success. An asynchronous owner awaits success -before clearing, retains selection on failure, and announces the result itself. -The [bulk-action stories](./DataTable.bulk-actions.stories.tsx) demonstrate flat, -grouped, mixed, asynchronous failure/retry, and direct composition. +With `rowSelection`, `renderBulkActions` receives effective `selectedRows`, +`selectedCount`, and `clearSelection`. Use these IDs for operations, not the +unfiltered controlled selection. `clearSelection` requests an empty selection, +including retained IDs; controlled consumers apply `onSelectionChange`. + +Actions appear above the table header in a named group with native Tab/Shift+Tab +navigation. Count changes are announced, including zero. Use `bulkActionsProps` +to localize the group name, clear button, and count label. + +Showing actions preserves checkbox focus. When clearing selection or updating +rows removes the focused action, `DataTable` restores focus to select-all, or to +the table when no selectable rows remain. `bulkActionsReturnFocusRef` overrides +that destination. Focus is not restored after the user leaves the actions or +moves into a consumer-owned dialog. When composing `Table.BulkActions` directly, +keep it mounted at zero and provide `onFocusReturn` for recovery. + +Consumers own pending states, result announcements, and focus when closing +dialogs or replacing the table. For asynchronous operations, capture the effective +IDs at activation and reconcile only those IDs on success; preserve selection on +failure and do not clear selections added while waiting. +See the [bulk-action examples](./DataTable.bulk-actions.stories.tsx). ## Verification diff --git a/packages/react/src/DataTable/DataTable.docs.json b/packages/react/src/DataTable/DataTable.docs.json index db8358281ac..ddbf3eb9080 100644 --- a/packages/react/src/DataTable/DataTable.docs.json +++ b/packages/react/src/DataTable/DataTable.docs.json @@ -147,7 +147,7 @@ { "name": "renderBulkActions", "type": "(context: DataTableBulkActionsContext) => React.ReactNode", - "description": "Render actions for effectively selected rows when rowSelection is enabled. The context contains readonly selectedRows IDs, selectedCount, and clearSelection. Counts and action IDs exclude missing and non-selectable rows. Business operations and their outcomes are consumer-owned." + "description": "Render actions when rowSelection is enabled and selectable rows are selected. Receives selectedRows IDs, selectedCount, and clearSelection, excluding missing and non-selectable rows." }, { "name": "bulkActionsProps", diff --git a/packages/react/src/DataTable/TableBulkActions.tsx b/packages/react/src/DataTable/TableBulkActions.tsx index dba56a8d4d0..ec5cf062504 100644 --- a/packages/react/src/DataTable/TableBulkActions.tsx +++ b/packages/react/src/DataTable/TableBulkActions.tsx @@ -83,7 +83,9 @@ const TableBulkActions = React.forwardRef } }} onBlurCapture={event => { - if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) { + // A blur to non-focusable content has no relatedTarget. Only retain a + // detached target, whose removal may require focus recovery. + if (event.target.isConnected) { focusedAction.current = null } if (!event.defaultPrevented) { diff --git a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx index 16528dcdc84..0b3795f37c5 100644 --- a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx +++ b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx @@ -3,10 +3,11 @@ import {render, screen, waitFor, within} from '@testing-library/react' import userEvent from '@testing-library/user-event' import {renderToString} from 'react-dom/server' import {hydrateRoot, type Root} from 'react-dom/client' -import {createPortal} from 'react-dom' import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest' import {DataTable, Table, type DataTableBulkActionsContext, type DataTableData, type DataTableRowId} from '..' import {Button} from '../../Button' +import {ActionMenu} from '../../ActionMenu' +import {ActionList} from '../../ActionList' import {getLiveRegion} from '../../live-region/__tests__/test-helpers' import {implementsClassName} from '../../utils/testing' import type {Column} from '../column' @@ -212,28 +213,55 @@ describe('DataTable bulk actions', () => { expect(screen.getByRole('button', {name: 'Confirmation'})).toHaveFocus() }) - it('recovers focus from portalled actions in the same React subtree', async () => { + it('does not recover focus after the user leaves the actions for non-interactive content', async () => { + const user = userEvent.setup() + const renderExample = (data: Array) => ( + <> +

    Outside the table

    + + + ) + const {rerender} = render(renderExample(rows)) + screen.getByRole('button', {name: 'Apply to 1'}).focus() + await user.click(screen.getByText('Outside the table')) + expect(document.body).toHaveFocus() + + rerender(renderExample(rows.slice(1))) + + expect(document.body).toHaveFocus() + expect(screen.queryByRole('group', {name: 'Bulk actions'})).not.toBeInTheDocument() + }) + + it('recovers focus when a Primer menu action clears selection', async () => { const user = userEvent.setup() - function PortalAction({clearSelection}: {clearSelection: () => void}) { - const [open, setOpen] = React.useState(false) - return ( - <> - - {open ? createPortal(, document.body) : null} - - ) - } render( } + renderBulkActions={({clearSelection}) => ( + + More actions + + + Archive selected + + + + )} />, ) - await user.click(screen.getByRole('button', {name: 'Open actions'})) - await user.click(screen.getByRole('button', {name: 'Apply from portal'})) + screen.getByRole('button', {name: 'More actions'}).focus() + await user.keyboard(' ') + expect(screen.getByRole('menuitem', {name: 'Archive selected'})).toHaveFocus() + await user.keyboard('{Enter}') expect(screen.getByRole('checkbox', {name: 'Select rows'})).toHaveFocus() }) From 3d8c9bc0094b9b7c288a96a46b61559d28232c21 Mon Sep 17 00:00:00 2001 From: Ricky Zhang Date: Tue, 13 Oct 2026 18:46:02 -0400 Subject: [PATCH 05/16] docs(DataTable): consolidate bulk actions into one feature story Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- e2e/components/DataTableBulkActions.test.ts | 85 +++---- .../src/DataTable/DataTable.accessibility.md | 2 +- .../DataTable.bulk-actions.stories.tsx | 208 ------------------ .../react/src/DataTable/DataTable.docs.json | 3 + .../DataTable/DataTable.features.stories.tsx | 60 +++++ 5 files changed, 95 insertions(+), 263 deletions(-) delete mode 100644 packages/react/src/DataTable/DataTable.bulk-actions.stories.tsx diff --git a/e2e/components/DataTableBulkActions.test.ts b/e2e/components/DataTableBulkActions.test.ts index 4d14968faca..98b139b84c5 100644 --- a/e2e/components/DataTableBulkActions.test.ts +++ b/e2e/components/DataTableBulkActions.test.ts @@ -2,65 +2,42 @@ import {test, expect} from '@playwright/test' import {visit} from '../test-helpers/storybook' import {themes} from '../test-helpers/themes' -const stories = ['flat', 'grouped', 'mixed', 'async-actions', 'composed-table'] as const +const storyId = 'experimental-components-datatable-features--with-bulk-actions' test.describe('DataTable bulk actions', () => { - for (const story of stories) { - for (const theme of themes) { - test(`${story} ${theme} @avt`, async ({page}) => { - await visit(page, { - id: `experimental-components-datatable-features-bulk-actions--${story}`, - globals: {colorScheme: theme}, - }) - await expect(page).toHaveNoViolations() + for (const theme of themes) { + test(`${theme} @avt`, async ({page}) => { + await visit(page, { + id: storyId, + globals: {colorScheme: theme}, }) - } - } - - for (const story of ['flat', 'grouped', 'mixed', 'composed-table'] as const) { - test(`${story} keyboard focus and unobscured header @avt`, async ({page}) => { - await visit(page, {id: `experimental-components-datatable-features-bulk-actions--${story}`}) - if (story === 'flat') { - await expect(page.getByRole('columnheader', {name: 'Repository', exact: true})).toHaveAttribute( - 'aria-sort', - 'ascending', - ) - } - const selectAll = page.getByRole('checkbox', {name: 'Select rows', exact: true}) - await selectAll.focus() - await page.keyboard.press('Space') - await expect(selectAll).toBeFocused() - const actions = page.getByRole('group', {name: 'Bulk actions'}) - await expect(actions.getByText('3 rows selected')).toBeVisible() - const actionsBox = await actions.boundingBox() - const headerBox = await selectAll.boundingBox() - expect(actionsBox).not.toBeNull() - expect(headerBox).not.toBeNull() - expect(actionsBox!.y + actionsBox!.height).toBeLessThanOrEqual(headerBox!.y) - - await actions.getByRole('button', {name: 'Clear selection'}).focus() - await page.keyboard.press('Enter') - await expect(selectAll).toBeFocused() - await expect(actions).toHaveCount(0) await expect(page).toHaveNoViolations() }) } - test('asynchronous failure retains selection; success handles deletion and final-record focus @avt', async ({ - page, - }) => { - await visit(page, {id: 'experimental-components-datatable-features-bulk-actions--async-actions'}) - await expect(page.getByRole('columnheader', {name: 'Repository', exact: true})).toHaveAttribute( - 'aria-sort', - 'ascending', - ) - await page.getByRole('button', {name: 'Simulate failed action'}).click() - await expect( - page - .locator('#storybook-root') - .getByText('Unable to delete repositories. Your selection is unchanged; try again.'), - ).toBeVisible() - await expect(page.getByRole('checkbox', {name: 'Select primer/react', exact: true})).toBeChecked() + test('keyboard focus and unobscured header @avt', async ({page}) => { + await visit(page, {id: storyId}) + const selectAll = page.getByRole('checkbox', {name: 'Select rows', exact: true}) + await selectAll.focus() + await page.keyboard.press('Space') + await expect(selectAll).toBeFocused() + const actions = page.getByRole('group', {name: 'Bulk actions'}) + await expect(actions.getByText('3 rows selected')).toBeVisible() + const actionsBox = await actions.boundingBox() + const headerBox = await selectAll.boundingBox() + expect(actionsBox).not.toBeNull() + expect(headerBox).not.toBeNull() + expect(actionsBox!.y + actionsBox!.height).toBeLessThanOrEqual(headerBox!.y) + + await actions.getByRole('button', {name: 'Clear selection'}).focus() + await page.keyboard.press('Enter') + await expect(selectAll).toBeFocused() + await expect(actions).toHaveCount(0) + await expect(page).toHaveNoViolations() + }) + + test('deletion and final-record focus @avt', async ({page}) => { + await visit(page, {id: storyId}) await page.getByRole('button', {name: 'Delete selected'}).click() await expect(page.locator('#storybook-root').getByText('1 repository deleted')).toBeVisible() const selectAll = page.getByRole('checkbox', {name: 'Select rows', exact: true}) @@ -77,7 +54,7 @@ test.describe('DataTable bulk actions', () => { for (const theme of ['light', 'dark'] as const) { test(`mixed ${theme} @vrt`, async ({page}) => { await visit(page, { - id: 'experimental-components-datatable-features-bulk-actions--mixed', + id: storyId, globals: {colorScheme: theme}, }) await expect(page).toHaveScreenshot(`DataTable.BulkActions.Mixed.${theme}.png`) @@ -86,7 +63,7 @@ test.describe('DataTable bulk actions', () => { test('actions reflow without clipping at a narrow viewport and with text-spacing overrides @avt', async ({page}) => { await page.setViewportSize({width: 320, height: 256}) - await visit(page, {id: 'experimental-components-datatable-features-bulk-actions--mixed'}) + await visit(page, {id: storyId}) await page.addStyleTag({ content: '* {line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important;} p {margin-bottom: 2em !important;}', diff --git a/packages/react/src/DataTable/DataTable.accessibility.md b/packages/react/src/DataTable/DataTable.accessibility.md index 8615aa20057..96f1ce9d4cc 100644 --- a/packages/react/src/DataTable/DataTable.accessibility.md +++ b/packages/react/src/DataTable/DataTable.accessibility.md @@ -294,7 +294,7 @@ Consumers own pending states, result announcements, and focus when closing dialogs or replacing the table. For asynchronous operations, capture the effective IDs at activation and reconcile only those IDs on success; preserve selection on failure and do not clear selections added while waiting. -See the [bulk-action examples](./DataTable.bulk-actions.stories.tsx). +See `WithBulkActions` in [DataTable features](./DataTable.features.stories.tsx). ## Verification diff --git a/packages/react/src/DataTable/DataTable.bulk-actions.stories.tsx b/packages/react/src/DataTable/DataTable.bulk-actions.stories.tsx deleted file mode 100644 index 81d0395905f..00000000000 --- a/packages/react/src/DataTable/DataTable.bulk-actions.stories.tsx +++ /dev/null @@ -1,208 +0,0 @@ -import type {Meta, StoryObj} from '@storybook/react-vite' -import {useId, useRef, useState} from 'react' -import {expect, userEvent} from 'storybook/test' -import {Button} from '../Button' -import {AriaAlert, AriaStatus} from '../live-region' -import {DataTable, Table, type DataTableData, type DataTableRowId} from '.' -import type {Column} from './column' - -export default { - title: 'Experimental/Components/DataTable/Features/Bulk actions', -} satisfies Meta - -interface Repository { - id: number - name: string - visibility: string -} - -const repositories: Array = [ - {id: 1, name: 'primer/react', visibility: 'Public'}, - {id: 2, name: 'primer/css', visibility: 'Public'}, - {id: 3, name: 'github/github', visibility: 'Internal'}, -] -const columns: Array> = [ - {header: 'Repository', field: 'name', rowHeader: true, sortBy: 'alphanumeric'}, - {header: 'Visibility', field: 'visibility'}, -] - -function BulkActionsExample({ - mode, - asyncActions = false, -}: { - mode: 'flat' | 'grouped' | 'mixed' - asyncActions?: boolean -}) { - const titleId = useId() - const [rows, setRows] = useState(repositories) - const [selectedRows, setSelectedRows] = useState>(() => new Set([1])) - const [pending, setPending] = useState(false) - const [error, setError] = useState('') - const [message, setMessage] = useState('') - const addButtonRef = useRef(null) - const publicRows = rows.filter(row => row.visibility === 'Public') - const internalRows = rows.filter(row => row.visibility === 'Internal') - const data: DataTableData = - mode === 'flat' - ? rows - : mode === 'grouped' - ? [ - {groupId: 'public', label: 'Public', rows: publicRows}, - {groupId: 'internal', label: 'Internal', rows: internalRows}, - ] - : [...internalRows, {groupId: 'public', label: 'Public', rows: publicRows}] - - return ( - - Repositories - - - - setSelectedRows(next)} - bulkActionsReturnFocusRef={rows.length === 0 ? addButtonRef : undefined} - renderBulkActions={({selectedRows: effectiveIds, selectedCount, clearSelection}) => ( - <> - {asyncActions ? ( - - ) : null} - - - )} - /> - {error} - {message} - - ) -} - -export const Flat: StoryObj = { - render: () => , - play: async ({canvas}) => { - await userEvent.click(canvas.getByRole('button', {name: 'Repository'})) - await expect(canvas.getByRole('columnheader', {name: 'Repository'})).toHaveAttribute('aria-sort', 'ascending') - await expect(canvas.getByText('1 row selected')).toBeVisible() - }, -} - -export const Grouped: StoryObj = { - render: () => , -} - -export const Mixed: StoryObj = { - render: () => , -} - -export const AsyncActions: StoryObj = { - render: () => , - play: async ({canvas}) => { - await userEvent.click(canvas.getByRole('button', {name: 'Repository'})) - await expect(canvas.getByRole('columnheader', {name: 'Repository'})).toHaveAttribute('aria-sort', 'ascending') - await expect(canvas.getByRole('checkbox', {name: 'Select primer/react'})).toBeChecked() - await expect(canvas.getByRole('button', {name: 'Delete selected'})).toBeEnabled() - }, -} - -export const ComposedTable: StoryObj = { - render: function ComposedTable() { - const titleId = useId() - const checkboxRef = useRef(null) - const [selectedRows, setSelectedRows] = useState>(() => new Set([1])) - const effectiveRows = repositories.filter(row => selectedRows.has(row.id)) - const allSelected = effectiveRows.length === repositories.length - return ( - - Composed repositories - setSelectedRows(new Set())} - onFocusReturn={() => checkboxRef.current?.focus()} - > - - - - - - 0 ? 'some' : 'none'} - onToggleSelect={() => - setSelectedRows(allSelected ? new Set() : new Set(repositories.map(row => row.id))) - } - /> - Repository - - - - {repositories.map(row => ( - - - setSelectedRows(current => { - const next = new Set(current) - if (next.has(row.id)) { - next.delete(row.id) - } else { - next.add(row.id) - } - return next - }) - } - /> - {row.name} - - ))} - -
    -
    - ) - }, -} diff --git a/packages/react/src/DataTable/DataTable.docs.json b/packages/react/src/DataTable/DataTable.docs.json index ddbf3eb9080..ba84833960b 100644 --- a/packages/react/src/DataTable/DataTable.docs.json +++ b/packages/react/src/DataTable/DataTable.docs.json @@ -49,6 +49,9 @@ { "id": "experimental-components-datatable-features--with-row-selection" }, + { + "id": "experimental-components-datatable-features--with-bulk-actions" + }, { "id": "experimental-components-datatable-features--with-grouped-row-selection" }, diff --git a/packages/react/src/DataTable/DataTable.features.stories.tsx b/packages/react/src/DataTable/DataTable.features.stories.tsx index 44de054828f..6a0234de98e 100644 --- a/packages/react/src/DataTable/DataTable.features.stories.tsx +++ b/packages/react/src/DataTable/DataTable.features.stories.tsx @@ -20,6 +20,7 @@ import Heading from '../Heading' import Label from '../Label' import LabelGroup from '../LabelGroup' import RelativeTime from '../RelativeTime' +import {AriaStatus} from '../live-region' import VisuallyHidden from '../_VisuallyHidden' import {createColumnHelper} from './column' import type {DataTableData, DataTableRowGroup, UniqueRow} from './row' @@ -1773,6 +1774,65 @@ export const WithRowSelection = () => { ) } +export const WithBulkActions = () => { + const repositories = [ + {id: 1, name: 'primer/react', visibility: 'Public'}, + {id: 2, name: 'primer/css', visibility: 'Public'}, + {id: 3, name: 'github/github', visibility: 'Internal'}, + ] + const titleId = React.useId() + const [rows, setRows] = React.useState(repositories) + const [selectedRows, setSelectedRows] = React.useState>(() => new Set([1])) + const [message, setMessage] = React.useState('') + const resetButtonRef = React.useRef(null) + + return ( + + Repositories + + + + row.visibility === 'Internal'), + {groupId: 'public', label: 'Public', rows: rows.filter(row => row.visibility === 'Public')}, + ]} + columns={[ + {header: 'Repository', field: 'name', rowHeader: true, sortBy: 'alphanumeric'}, + {header: 'Visibility', field: 'visibility'}, + ]} + rowSelection + selectedRows={selectedRows} + onSelectionChange={({selectedRows: next}) => setSelectedRows(next)} + bulkActionsReturnFocusRef={rows.length === 0 ? resetButtonRef : undefined} + renderBulkActions={({selectedRows: effectiveIds, selectedCount, clearSelection}) => ( + + )} + /> + {message} + + ) +} + const repoGroupsWithDisabledRow = repoGroups.map(group => ({ ...group, rows: group.rows.map(repo => (repo.id === 1 ? {...repo, name: `${repo.name} (not selectable)`} : repo)), From acb5e6276b2a67eb818a34c5d781a8131f3450e0 Mon Sep 17 00:00:00 2001 From: Ricky Zhang Date: Tue, 13 Oct 2026 20:29:52 -0400 Subject: [PATCH 06/16] fix(DataTable): place bulk actions in the table header Keep the select-all control mounted, retain accessible column labels, and restore sorting controls when selection clears. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .changeset/data-table-bulk-actions.md | 2 +- e2e/components/DataTableBulkActions.test.ts | 26 +++-- .../src/DataTable/DataTable.accessibility.md | 7 +- .../react/src/DataTable/DataTable.docs.json | 2 +- packages/react/src/DataTable/DataTable.tsx | 97 ++++++++++++------- packages/react/src/DataTable/Table.module.css | 1 - packages/react/src/DataTable/Table.tsx | 4 +- .../src/DataTable/TableBulkActions.module.css | 29 ++++-- .../__tests__/DataTableBulkActions.test.tsx | 9 +- 9 files changed, 116 insertions(+), 61 deletions(-) diff --git a/.changeset/data-table-bulk-actions.md b/.changeset/data-table-bulk-actions.md index 02e0d2ab304..9d0b27b44ce 100644 --- a/.changeset/data-table-bulk-actions.md +++ b/.changeset/data-table-bulk-actions.md @@ -2,4 +2,4 @@ '@primer/react': minor --- -DataTable: Add bulk actions for selected rows with selection counts, clearing selection, and focus recovery. +DataTable: Add bulk actions in the table header with selection counts, clearing selection, and focus recovery. diff --git a/e2e/components/DataTableBulkActions.test.ts b/e2e/components/DataTableBulkActions.test.ts index 98b139b84c5..cfaad3abb86 100644 --- a/e2e/components/DataTableBulkActions.test.ts +++ b/e2e/components/DataTableBulkActions.test.ts @@ -15,24 +15,30 @@ test.describe('DataTable bulk actions', () => { }) } - test('keyboard focus and unobscured header @avt', async ({page}) => { + test('bulk actions replace column labels beside the header checkbox @avt', async ({page}) => { await visit(page, {id: storyId}) const selectAll = page.getByRole('checkbox', {name: 'Select rows', exact: true}) await selectAll.focus() await page.keyboard.press('Space') await expect(selectAll).toBeFocused() - const actions = page.getByRole('group', {name: 'Bulk actions'}) + const actions = page.getByRole('table').getByRole('group', {name: 'Bulk actions'}) + await expect(page.getByRole('button', {name: 'Repository', exact: true})).toHaveCount(0) + await expect(page.getByRole('columnheader', {name: 'Repository', exact: true})).toHaveCount(1) await expect(actions.getByText('3 rows selected')).toBeVisible() const actionsBox = await actions.boundingBox() const headerBox = await selectAll.boundingBox() expect(actionsBox).not.toBeNull() expect(headerBox).not.toBeNull() - expect(actionsBox!.y + actionsBox!.height).toBeLessThanOrEqual(headerBox!.y) + expect(headerBox!.y).toBeGreaterThanOrEqual(actionsBox!.y) + expect(headerBox!.y + headerBox!.height).toBeLessThanOrEqual(actionsBox!.y + actionsBox!.height) + expect(headerBox!.x + headerBox!.width).toBeLessThan(actionsBox!.x) - await actions.getByRole('button', {name: 'Clear selection'}).focus() + await page.keyboard.press('Tab') + await expect(actions.getByRole('button', {name: 'Clear selection'})).toBeFocused() await page.keyboard.press('Enter') await expect(selectAll).toBeFocused() await expect(actions).toHaveCount(0) + await expect(page.getByRole('button', {name: 'Repository', exact: true})).toBeVisible() await expect(page).toHaveNoViolations() }) @@ -61,7 +67,9 @@ test.describe('DataTable bulk actions', () => { }) } - test('actions reflow without clipping at a narrow viewport and with text-spacing overrides @avt', async ({page}) => { + test('header actions remain reachable in a narrow scrolling table with text-spacing overrides @avt', async ({ + page, + }) => { await page.setViewportSize({width: 320, height: 256}) await visit(page, {id: storyId}) await page.addStyleTag({ @@ -74,10 +82,14 @@ test.describe('DataTable bulk actions', () => { const dimensions = await actions.evaluate(element => ({ width: element.clientWidth, scrollWidth: element.scrollWidth, - right: element.getBoundingClientRect().right, })) expect(dimensions.scrollWidth).toBeLessThanOrEqual(dimensions.width) - expect(dimensions.right).toBeLessThanOrEqual(320) + expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBeLessThanOrEqual(320) + const deleteButton = actions.getByRole('button', {name: 'Delete selected'}) + await deleteButton.focus() + await expect(deleteButton).toBeInViewport({ratio: 1}) + const buttonBox = await deleteButton.boundingBox() + expect(buttonBox!.width).toBeLessThanOrEqual(320) await actions.getByRole('button', {name: 'Clear selection'}).click() await expect(page.getByRole('checkbox', {name: 'Select rows', exact: true})).toBeFocused() }) diff --git a/packages/react/src/DataTable/DataTable.accessibility.md b/packages/react/src/DataTable/DataTable.accessibility.md index 96f1ce9d4cc..debfda0c2dd 100644 --- a/packages/react/src/DataTable/DataTable.accessibility.md +++ b/packages/react/src/DataTable/DataTable.accessibility.md @@ -279,8 +279,11 @@ With `rowSelection`, `renderBulkActions` receives effective `selectedRows`, unfiltered controlled selection. `clearSelection` requests an empty selection, including retained IDs; controlled consumers apply `onSelectionChange`. -Actions appear above the table header in a named group with native Tab/Shift+Tab -navigation. Count changes are announced, including zero. Use `bulkActionsProps` +Actions occupy the table header beside select-all, replacing the visible column +labels while rows are selected. Column labels remain available to assistive +technology, but sorting controls are removed until selection is cleared. The +named action group uses native Tab/Shift+Tab navigation. Count changes are +announced, including zero. Use `bulkActionsProps` to localize the group name, clear button, and count label. Showing actions preserves checkbox focus. When clearing selection or updating diff --git a/packages/react/src/DataTable/DataTable.docs.json b/packages/react/src/DataTable/DataTable.docs.json index ba84833960b..028eab4af17 100644 --- a/packages/react/src/DataTable/DataTable.docs.json +++ b/packages/react/src/DataTable/DataTable.docs.json @@ -150,7 +150,7 @@ { "name": "renderBulkActions", "type": "(context: DataTableBulkActionsContext) => React.ReactNode", - "description": "Render actions when rowSelection is enabled and selectable rows are selected. Receives selectedRows IDs, selectedCount, and clearSelection, excluding missing and non-selectable rows." + "description": "Render actions in place of visible column labels when rowSelection is enabled and selectable rows are selected. Receives selectedRows IDs, selectedCount, and clearSelection, excluding missing and non-selectable rows." }, { "name": "bulkActionsProps", diff --git a/packages/react/src/DataTable/DataTable.tsx b/packages/react/src/DataTable/DataTable.tsx index 21de112878b..6205d537cd5 100644 --- a/packages/react/src/DataTable/DataTable.tsx +++ b/packages/react/src/DataTable/DataTable.tsx @@ -18,6 +18,7 @@ import { import {TableGroup} from './TableGroup' import {TableBulkActions, type TableBulkActionsProps} from './TableBulkActions' import classes from './TableBulkActions.module.css' +import VisuallyHidden from '../_VisuallyHidden' export interface DataTableBulkActionsContext { selectedRows: ReadonlySet @@ -221,6 +222,8 @@ function DataTableImplementation({ onExpandedGroupsChange, }) const {headers, bodies, actions, selection, gridTemplateColumns} = table + const hasBulkActions = Boolean(rowSelection && renderBulkActions) + const bulkActionsActive = hasBulkActions && selection.selectedCount > 0 const renderRow = (row: (typeof bodies)[number]['rows'][number]) => ( @@ -250,7 +253,7 @@ function DataTableImplementation({ ) - const renderedTable = ( + return ( ({ gridTemplateColumns={gridTemplateColumns} > - + {rowSelection ? ( ({ /> ) : null} {headers.map(header => { + if (bulkActionsActive) { + return ( + + + {typeof header.column.header === 'string' ? header.column.header : header.column.header()} + + + ) + } if (header.isSortable()) { return ( ({ ) })} + {hasBulkActions ? ( + // Share the visual header row without putting action names in column + // headers or removing their associations with the table body. + + + { + const target = bulkActionsReturnFocusRef?.current + if (target?.isConnected) { + target.focus() + } else if (selectionCheckboxRef.current && !selectionCheckboxRef.current.disabled) { + selectionCheckboxRef.current.focus() + } else { + tableRef.current?.focus() + } + }} + > + {bulkActionsActive + ? renderBulkActions?.({ + selectedRows: new Set(selection.selectedRows), + selectedCount: selection.selectedCount, + clearSelection: actions.clearSelection, + }) + : null} + + + + ) : null} {bodies.map(body => body.type === 'row-group' ? ( @@ -328,39 +388,6 @@ function DataTableImplementation({ )}
    ) - - if (!rowSelection || !renderBulkActions) { - return renderedTable - } - - return ( -
    - { - const target = bulkActionsReturnFocusRef?.current - if (target?.isConnected) { - target.focus() - } else if (selectionCheckboxRef.current && !selectionCheckboxRef.current.disabled) { - selectionCheckboxRef.current.focus() - } else { - tableRef.current?.focus() - } - }} - > - {selection.selectedCount > 0 - ? renderBulkActions({ - selectedRows: new Set(selection.selectedRows), - selectedCount: selection.selectedCount, - clearSelection: actions.clearSelection, - }) - : null} - - {renderedTable} -
    - ) } const DataTable = DataTableImplementation as DataTableComponent diff --git a/packages/react/src/DataTable/Table.module.css b/packages/react/src/DataTable/Table.module.css index 6d76e6821db..c03d844fa3e 100644 --- a/packages/react/src/DataTable/Table.module.css +++ b/packages/react/src/DataTable/Table.module.css @@ -7,7 +7,6 @@ 'divider divider' 'subtitle subtitle' 'filter filter' - 'bulk-actions bulk-actions' 'table table' 'footer footer'; column-gap: var(--base-size-8); diff --git a/packages/react/src/DataTable/Table.tsx b/packages/react/src/DataTable/Table.tsx index 6f881e7f6d3..3e0c512b357 100644 --- a/packages/react/src/DataTable/Table.tsx +++ b/packages/react/src/DataTable/Table.tsx @@ -261,9 +261,9 @@ function TableSelectionHeader({ export type TableRowProps = React.ComponentPropsWithoutRef<'tr'> -function TableRow({children, ...rest}: TableRowProps) { +function TableRow({children, className, ...rest}: TableRowProps) { return ( - + {children} ) diff --git a/packages/react/src/DataTable/TableBulkActions.module.css b/packages/react/src/DataTable/TableBulkActions.module.css index 3035df85c23..9969738eec5 100644 --- a/packages/react/src/DataTable/TableBulkActions.module.css +++ b/packages/react/src/DataTable/TableBulkActions.module.css @@ -1,17 +1,9 @@ .TableBulkActions { - grid-area: bulk-actions; - &:where([data-active]) { display: flex; flex-wrap: wrap; align-items: center; gap: var(--base-size-8); - padding: var(--base-size-12) var(--base-size-16); - margin-block-start: var(--base-size-8); - margin-block-end: var(--base-size-8); - background-color: var(--bgColor-muted); - border: var(--borderWidth-thin) solid var(--borderColor-default); - border-radius: var(--borderRadius-medium); font-size: var(--text-body-size-small); } } @@ -24,7 +16,24 @@ margin-inline-start: auto; } -.DataTableWithBulkActions { - grid-area: table; +.HeaderRow, +.HeaderRow > * { + grid-row: 1; +} + +.BulkActionsCell { + grid-row: 1; + grid-column: 2 / -1; + z-index: 1; min-width: 0; + align-content: center; + /* stylelint-disable-next-line primer/spacing */ + padding: var(--table-cell-padding); + padding-inline-end: var(--base-size-16); + background-color: var(--bgColor-muted); + border-block-start: var(--borderWidth-thin) solid var(--borderColor-default); + border-block-end: var(--borderWidth-thin) solid var(--borderColor-default); + border-inline-end: var(--borderWidth-thin) solid var(--borderColor-default); + /* stylelint-disable-next-line primer/borders */ + border-start-end-radius: var(--table-border-radius); } diff --git a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx index 0b3795f37c5..0baf7c46af0 100644 --- a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx +++ b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx @@ -62,10 +62,15 @@ describe('DataTable bulk actions', () => { expect(screen.getByText('2 rows selected')).toBeVisible() await user.click(screen.getByRole('button', {name: 'Archive'})) expect(onAction).toHaveBeenLastCalledWith({selectedRows: new Set([1, '1']), selectedCount: 2}) + expect(screen.queryByRole('button', {name: 'Name'})).not.toBeInTheDocument() + expect(screen.getByRole('columnheader', {name: 'Name'})).toBeInTheDocument() + await user.click(screen.getByRole('button', {name: 'Clear selection'})) await user.click(screen.getByRole('button', {name: 'Name'})) + expect(screen.getByRole('columnheader', {name: 'Name'})).toHaveAttribute('aria-sort', 'ascending') + await user.click(screen.getByRole('checkbox', {name: 'Select rows'})) + expect(screen.getByRole('columnheader', {name: 'Name'})).toHaveAttribute('aria-sort', 'ascending') await user.click(screen.getByRole('button', {name: 'Archive'})) expect(onAction).toHaveBeenLastCalledWith({selectedRows: new Set([1, '1']), selectedCount: 2}) - expect(screen.getByRole('columnheader', {name: 'Name'})).toHaveAttribute('aria-sort', 'ascending') }) it('does not render actions without enabled selection or effectively selected rows', () => { @@ -333,7 +338,7 @@ describe('DataTable bulk actions', () => { container.innerHTML = renderToString(element) document.body.appendChild(container) const serverTable = within(container).getByRole('table') - expect(within(serverTable).queryByRole('group')).not.toBeInTheDocument() + expect(within(serverTable).getByRole('group', {name: 'Bulk actions'})).toBeInTheDocument() const onRecoverableError = vi.fn() let root: Root | undefined try { From 40f1d941d33975a90b6fc13effaed415c857cc5a Mon Sep 17 00:00:00 2001 From: rickyzhangca <16908811+rickyzhangca@users.noreply.github.com> Date: Wed, 14 Oct 2026 00:41:01 +0000 Subject: [PATCH 07/16] test(vrt): update snapshots --- ...DataTable-BulkActions-Mixed-dark-linux.png | Bin 21885 -> 19465 bytes ...ataTable-BulkActions-Mixed-light-linux.png | Bin 21924 -> 19579 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-dark-linux.png b/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-dark-linux.png index 327c4acd4be1897d42721d3a555689b8828c9478..fc8613eb936eda8b249255485b873020b9ed9b3c 100644 GIT binary patch literal 19465 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 literal 21885 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 z z;xNplNt?yCYulcaPAo$V)o-EeJvPSS);-J;R-I?wuIuaT#m2P)el7HEifv#Abg;KC zcW!*hPgv~QF1J4S+~|hPsmn(siTR%$Y)nv6QNHE9*p(0^y5X}n%!5JsG&AvJv|rO>my`47_{YzMNbh+d=df|#p0cay6e#wxta zKOUL~o2e%~m>G>~w6$HC5ry*_Hr$gu)BFDZ9<|iRR_t4O>XO`aS=-*DNd4F_F`jzF zIl|b%A$7cx7H|himb9}-eW@M?M@Q;)+(ZfP)gFB}vvLtHwtpmb;M=dtW+{vkU+WRg+ zu76Y@SynnGW8au$|XR(7r!f>S=}1kdw+57gQf|7V%{=N$!e(3eL7R#sMV zdU}^G1=Q6w&1gr*#>S?lr6pViJi0K3mT(R(Zfdu1n+d=lEp2TY8X8v@mm897j_Yh;i_4tEj#BjqF?I(=mHnTQ)W}F0b*XL@jywx+B2hJ?}${ z9Zu3}_*heD=nwvWrtDL<)#c?NF-?u6kI~WG+}tXvs@hswFHm8zjBZ?c+^rjm(NKD%;E{rK_52*W0HM#EY z9xgN#ewoA0K+G(x~_w}uuV|~;GTt>e}E_R=ra$b`# zs&5XZ4+sbVJ7({u6c+Vz=EoOB8b;w=-87355%{KVt8yW?afR39(VyV%AEwqsvNK>q zW;ttmV_J>gT5?8GJPR@|qJwZJ^Fm3{u!>mIgT?mH!mwg@)0*dxA5GWNul2j8BcwMZ zDo&5%&0_iotKnNDB4v%tAshrAQ#^ShJ222+SxF=|*dMhvCW*qcv$AMu-F?6&+uYh( zU#ABG;D_V_dp*5_@3Mh$+{dM+Qt8eXt?X4Nakcg&$Ocz)!Q#E_>CY^<2jh?}ptmG`ttEh8<(g&& z*O0!Wvqo?f=ao{|r3go(>LV{7$noC3nIGQL#%4Q;HBdhM7T5>HU0W!rse97nc>UJB zb_|F$N_P+S2_WenKLxt*v#f^xj`qgFuV9jSqeVvJlk25bL+_1pn^I5wk7s zsxT%A!wR30Lj+RD!7I>X!?4P?=*Yrvzb|kW|L%m!cf@h@fk)>uh@Qlwxk#z{!yx3q z8z!0K7w>9%oVMIp9_}{|I~rEojR`1AGFvan5X8n%K0Q)CXILcB53I~*cen&Q_;|C_ zpS_TBZ8W_?w;C?B-sw5yR;y96TAW0CdX6gnsz4s*TE(P;ty33=>}b6@(o@isb}g0A z%F%kIJ`|oto0K3UnaO8*KVcJwsjlistkb2dl@JjT)ql%W(oaSpE8`ZEOS#J5BZLF0EK@DE!5u$<+D;r5?jEJ-~ec7q94e)NKU@AIG(l?|{{GNGhsDMSrqhVU@1cf`)>dj)F@;TU&`D(Cdb+_yEU}GSox!^51wf9`O zC=UXfIgF@5uy}Wewbm>gjrIF^fKcm^zZ!p%oZOm%50SYjl?kkXQ9myazS+ly!Y*QOd`5b`< z-}{)9M0f3)^ZqD53(MAQDjZ~#M(r#x8HLyy65lEz9!;LUs_Qi#9;8vx zRNLUzg+Fvxn7l3=#ld`1O{q&S2 z72DYTqye_Q6DvXWdofce@7btv6Ppq`-c+O7QOD>aUU*9m?mc!>VEe=+ma5?g7>!cv2ZMkp#Q-!RWma3 zUCX;$k{+HrG~6%kAyhJGW`8^m)K;L42IB$A(JRrMDowHYR_lsi9f52uC&Xr5rl2T* z;&O_iQ}u_NataFcld=c|qI^*`S;#i!!-of6+vKpZFN)FUr__^m?hq*{i>VVTtos@r zr4zPr<^4AbB;hzmpSaR$3G{#m{31>R`S?Co1t60@fBqbGLgi09kDP5iJrR-gT7D@n zzX*oB$va3(3n1L#X2PEw7BrcU-(E_i5QCtliR;?-jEtpy)tZfR6m(|?6V9cjK+PFH zCJxYhvhALHo@xzGPe@GLX>1TDr(TCoRE3WM^|0c_&RslHNUg6C0RQrdm} zhAgRr)021yIq!~P$$P?n8|O`h#+GJhZ>bJx%+8nO&g7_U%q>ssRd(CvD~uQnGN!Aa za@ca#5>FDE3y~BQ(Z`z3*AfkuSYB|~Fy%;Er-k;=t1BsKLGx0J9AU6G2n&Gu3=ws) z;rOv~>$Ty$=+s#Enc3!K(MG=pza~|}Z-n<-=EKnP07@nS#9%In$0a~OIauEc3lDE{ z@caG_^=$ji_ZE5iyAh2)o={YY#qq)ItUksi9gGGZj_v^ZOZ`!M5Xa8W4#3oXwpo^| zy;Y8Ds>!1C4%hxH&MflV!usK>olBi5=y?rEnxaoQi^MQ|3q6xQuZrEmR%RxgV!Zbj z_xaFQAxsh#EHX}o2?>#*k?9Zo`;RG>C|Yv)gt%7qIXT;gMTSM4CaMK-g7JC#~BpNwtcDiFc_xV=M8Ov^7og(oo(wddTQ0 z4%c2UT7>lLJV4YL8XAiB6HiXRKnDb3mOA(Ft#6yc>J#XpCCN!iw-|0=BSIcV#SLfK z)0ZxErXvI1n*dT87IX?|I4xFFg(vhAy_vB6uyKReOlf8-z}Xn0|K^YP6f9CoDk|%x z7Omu0ZtHku{?yjYT6O2+EBO)MF6r+J`xv!jW*tpO7g_st{m=8WJ-)T!qC_$0v)N|l z+1XhM_f;{g!Q34h4mwIPujSrvuP=x=jNgkGEmw$4Nm&QtSFkvqrWHwJNp$K-6A=*s zpf?ibYHweV4lP+7fj@Fn*IeDB#vu;qNOw#vuJN%}*!01M3*mr0{3RhOd(ODx z%{N%!;+hkPBQBW2G+Bx6kF5N|-D+O$jpL@y?(@IJ?w)lewOlGOOx$<<>f73#ak>!H zIcbcknZE|zqVw*NqwGcGE~KyX7xah{_HzD+%~)E41%v%$u-K$NEizJ{Mbc(EOF91O zrWwZHM8}`0>|R013|X zL8+%>FK(65USWEuGc_`JwV!CZD=8au5?f}W<~t7)^PstFJL2bcN5o|r?F z+&h?n^BLBBdfu9)j1&+MAf;B~x)?!fMZ)(e2t=kYR+$A;-7Rj)D%g2X9eF)r*|%?! zjVbq;PhvWeOfSu1V-ut2%y)?v#^L)hNK?2&R;FWK0aHv8zYJHg^~r90o_g~#RQcT49KDB!kZW%wea>cKUvJ8FsV=(F=2`zri&e^bh4 z`&-yPr7OiAP%dRsaq+H8{(Ko2xzIQz|5nE2o9-Lq8!VCS9rhsI!KIrW7}#3pzLuk& zen;dA!|rzgJ-vYvRZ3W~PJfT1r2gAB@^r&#*5UJUL6>~wt<;YnQ&MA5E(=`z7CZue z2Oua^+9$`wi699-EIZ=FWBD+aYjhVboY%SgF*5>sQ1hbX=KE`_oQt$cfMRCSZ zOZ)s<`$B+Oy{jbuP~*>Odi9*gpR0SMo~3K`bw4&c%q;K>xwUO+NzUq60&Zy$pjn^Fp+O0Lb4qt&3$^vQYQI`W($?k}$< z8I4awhHwwg&>CdhwL@YE$Td$V_TJyb}@R#)yzbfAD>MA z9GxSco%uwqXcvrPtZb8#VqJx$2KacrkEa?A?M@PIg)m8l;kCpVm`h{in`<}T1`yx4PN%5+4Wd&qBqCG}q%23foih_X>~x@%Mu zwZd5tNkuucerlc9@$(tqs_XKdAQm-wL>>6fD`Hp;pZm_vPQZKVd$iR20s`D;9E~Kh zKXdX%K-(&wYrDr_RqJDPGbXFHw)Txe5KAbRHk1%mn8HQR!~2oEPL)zu4wLzZMl06-hQE%aXt6 zX*hmCPWD!-pUS=;4b3kL#iKlaVZlg{2P6qo=`mN+Q&TN1>~nry=3Z7w7%3nS z3vF#bDH4GM?TF56S5Z||45NnuDX)#C6i^&zH5_-X73WfZ zpx2=nvF$B-ZIIJveTTpLmZS8-!$HM#*vMdl>sG(yW>L}HoRSySRZ_o^Y$wvv(%tPX zhQ9>B7d9W$(uzsf{?BK1G~lwoj|U3*KOR=~-{5kxzTN+=$k_|NsU)9c$b!nBstDf* zVTg{tRa93cF5wnST5gYAEw3Fu96DL`zS7&@$LF6A7nPc3jocxY%R+zkPUwrp^B4Jj zR~FhOnwy^5SA@RaqBlITGBhL#aKm546<2vL6n?F2ADEt>7xHc5=t>fWBE5ZlBp$|L zT$eoLfya>j;Mb}u)2elj ztQ+qF0$N&{u;6Zm)m|Hw6PlXP;&)tR+XA)Db0>giKeb~K`)Y>D$}dPBy;}tzD-#!F zEze~N#puqTCYkvMM@I5BL|L1VdFe2ixDqMBoVYFS@)X6p=+zzz$uWiRwnN6KMn@+xF;hOW)=z?qgQGPoL;1;*+3r*fwl?}uB69~)GFYtJ(f@;smv?i2C3{(eYwzVm;x3ny@i~sS*QRs$AJ(`JzW^Zp*H)4T_@mM5ZYe-jRI~^}m zkK95}PNuvu8uFag!RGm$Ua_*ue*E~czt4fbzTp943q{i!$s*xVG5sjgZ@896wxa;JUSmisLb&lkQD3 zsc#nGUJpsfF;h^4^1?BW&uzYr^lWu+Oiav?xX&H3Cj~S>GjO6QT`_@}bRFUW9DYhx1 zd=B$WQ6Pyf+AObm46{QXcBcZ9!TZRY478kaZEbDUaGcXysqVQ-HK7 zdAgK7tIxnSv}sb`^b?@;D#wXoR8sv>mrj<;P;PE6IVb03vW5hw_kl8A+m9rtQll)sd>(nB(`aaLgm>1lvbMJU^{3A79Uo(IRGUs}Uy)s#Ei$Z@_THTjXB=sk zzu&M3;xA#*mL9urf| zCN5sm5gry6!_h+OnQ>zGB>kSZc&(DHqLR`L9$vKFNZvq=b0!&*SWz)JI7kli{EWjT z^c_Fmc6D|QLck)L&910$hp=TlO&w4a)NgsC~ai5=gg!08J#hTjpmANO2%)Xy) zWj2wrc#)KTH0w^rYLWSF0*Sh#(%`1?U>&3@i=CWQO>Mb``HUNKK^M61FT;TA=GL*u z@X&xR=C+~!ix=}Dv>jn#VJOs^h&^GofX8rsa%WA}0;D9H`#ZU}+O#EYAxYDu^;ft) zix#q45O&#Lj`GB=5XS9GHn1q=POjQ|XuPo{WpN`p1hxh8I~Mk%PT5Q@FN?}&ZYFtg!s30C{{JPx_D1+zU*xZBH?FS zxAbu<3xGUe7SmxyL9X^LJE3{gebp;f%=yWgw9kHNURhajfXPr_AJv~!dSuhh^tXKt zB=PShH_JKC57v3ju$qz(kM%+EyR*YUW2M05XBM%>#lPW24^=A1=Ia8Xn1Rrve88f6 zWB{EZJu=k}V8+d4YVf@kqVlF+Ja|&)>)h6lt2jHO#l) z-E{4TRZu!sRuKGNI2C_PCiI{0yc88Zj9`+;y2p_&=4|{M*%`TH=I>r@vCWp^51G&L z`P75Mgu}H{koVKMQ&7&wNAd~3il1;r7^r#tbm8G~oZ^DpFpkj*a&z!JTx*F~2e6j} zW|AP8_M7Ezkk`$A0V1uv>wY)b!RLR8{;SSmwqsU3=Cq+-SM5ps*yINo6A8LKvfbUa z{bUo=;X=CK|InrE7Ar8bxH+?`*Y%^nEP)?j7ii;?#^QJPN!J#F(m8LLb~SdRC$~5v z*xA_V1Un}uGxSpHLgMuFZNC1(Ru;KYPc;n`MZ@Ao%d4yYdtIWi785D7e0WkT@|5Skn7&k*>O>WckDr2V7}c=4IMuk6PCr?j z0J&Uy-D7^aFM!H#$Ovq~Ph@2~2sLEex39ad?kxgeutjV4RK1AP`25@)>*D(9{>rId zd@&7&>h%lkYAN^A+9Q}Hs!o>73LPDq;@sCneb4cQj59MPb#B+z<~YJ+JZ77iWiZXk zary=es^>vD3eM2L$lGHmYxSiOGbkAu@t*7CNYR?q`dlQdwmL4|Vo6&iES!^` zo_?o;^T_2T0}DM_n)=w-SokgBTT*s9OA)ESF@e}$c3z(T%&HLSFi~f@NN+}Y^TAik z0=@H-1ILl7qO92F?Q4zAyj-#EwXkNcST4t@I^DvN;tl+8G90~gvR1h^=rks<1xwqR zYh{t~pRJ_h5pkRpGN1k9BH6aOK&#(?m1?sKHbopH=?u{h$FkL6SI$qf#9XKIINr6y zx9CFjiuHjwuinvASFjX&FYzB*K)nyYCo?Ur@Y3lPhPYY3x6~7wB>Lb%?%V=f6}br| z*W4TcyA9X(n4pcjym~i!e5n1Nk3+hWPL7X(j}u^)l4DC%sdU8Z20iZ|z{_#RWp%Kv zW>jDEc%<00x--3&-av*J=nY#~?qiLJSfC~QCKKDIU@lDq`~xrsCK{f&YuB!+mvs~c zy)0ExQ@gG#H8txm)_1s70ENxXHubl(WFy?wcOa{?%@hF9ad*sN(SAn1y;{=B=F&#p zMVJ^VGT(Awd$&>w94c@UC{IaE88o9xpEjxD<>j?#2{)>EsTr#jn}pg0l-}!Ir!#Q^ zjtRExF-476I7--Te^Ma-l9dx`39OO8bbmhTQ{xVSV^O4hoD?OqYg@vsxzU+8_gFP17W6NZU0o=TzE1#W~hSmpJ1@)ZnRGz((p%onR5e|J$a5p0l zbV+1jI6d5;88~PRpdJ|>UhIEL<`o3mv6Lv-5qCbnu_3h;c-$JvgmnA1W1&C<9$HbH zZ@GPSF>q~vg+LdH4|=+$95)+SJhrg0)r!i>+;02(1j#+?BEw3nu9L-s)Cs|C)$*@j zb2UCcdG_oX0}J%GSM=?04DrBp3k#g9xJuWhl8I*Gd7aaFz_8=^Z5jV{vqSu$3?$8p z8sw9Qam4*R?Wm}0U@n59mG?G@2I4jqZ{yY9J|YU<+UU=O;_&uq`^V7C@67}K{rRh_ zNm*J`4c_G-vuQtEd`bWYtYj%8PRpLv8nCy1Q2g_U(W2;}UcOEnd<$D(ZjM6|&w>6J zo1E;kzO0$GFI6xHHrQ#lod4veQz)9OKHhFxlg%ki^6?+gz+?k`u~7+QDhk~+;Glii z^zLa%o%`wjhP|ED2`GU$*qSJbL0h{UgZusb^2dw`UHn3g?%vmGi096a+Am+4U;&BA zMnLLvClb!T_C6;?7q42WocM)z?*oF$gV!GVPW9WuQHqzPQ}T561_pF8l)Nqr0 zC;yD@^H103+z+jR5B?P8=GHl;vaNGz>7hF31wzqV!IR(Pm`Hw^GwygdPIf^#iPlbxtRYi1fVN&(0{WmtJ>WfY5tt>6GateT?M@Dwt`_jl{Yg1E@ zrJkAxzlGgMzB_(($Wn&K)!CVI_3~}NQ{d?1Y^7K(9P-fb<;(5;m4REryF9B`8sS(; zm-%NdS|78rEWvUHW++_)0}{CTE2=CFRaITRH72QDE_M*}Zh@G)rWrr{{|s))R@0DE0j5qwN61M}2lSc3`*B;Eb!RR6S&t zqNJqMD>0>YUW+3Elb>1ZvxMH6Mo?IB4dS_lrMi6iI>ca%tMo=CPn_Ox+$jYAFWxa{bR<`TI4 zBLPeL!;BS{B;&}ipz9r1n8wX&U9v!S=snyeZ(d*@DQjV2VLy`Z$NS&`E9+jL#El8~ zWKCa`N5)NfB$s~P(Vg3CkW?5iLjP^3C}Hm{K81&l$3;o&;D|$W;Gl* z4XS|i(#%h|qo=1N*TO(Q0ph(x84HS1bj~fU?6OHWxZd|)lPiB$-P#(<5x=x~?>Iq{ zt&S}1?!Ss$|NBz8UR|N383U95T>RuG>A!j$!w&L1|4WM>$fGm?!sNFQ4F!%4W}OKs zgQvE4)&$%6;OAyPS9R*HLbq2q*MaSlR|MBCl};tW{1 zIl*PQ+!DS9s?=~5w$ZynUPJi);bHU*H%)H@0y9!SAu)A>%*z>Aj2p+=6n&{!qzf~Y zn}NNIGii;`EdhK>8i0X#nPN30s-oL=IEUM{bpZ_KhYOvaZk-=&qFnH+pcH*eIZUo>`RubiD(6 ze%e@ULel{#I@htF%IsBHnKKQQ(Q1dGGWjk;pb@-Y`kiImw7U4P4$t_c_+2W9)Y5(@ z`CE=n9O<{kyzUEet4Q7ifD_*W)H{OnNlZff^~f)Pxbe^7H+@j~I(c_Dft;p8iq1P0 ztHG5LO8Z=0fj{kO;D78?c!J+Nu+rE7@%do2Ke_*zs#2Ko)jscjh65s8Djs} z&n3T;-5+oVPgf*5@19z#du6LHnIXWmY=_L`ylscE}JsaElNq&c{0;ghmiSBgPTtM$Plj>oh@3=nBx259P_$jh?@ zGwfAGh#wwE@wMnk^+TsA?3T=BG+)oL3*e+Fq<$a9jt%82dDS-2tF zIYw<~Ua@X74wYcJudWMx$NJ1ti21>`=+{f#RG?Tr%JJmM6OCRuBgSMvC}o~04vF^CFEN6S+jMqyAr97$Tj3abK`W49 zg)yY`lm{%yR)^%#QMm5C4ZIS952j(iPxcBXHCID#$+x&JH>Qpw#B`t^DQT7I11~oR z8#@3zxuOBMx-2zfU{iBzsHHptYyY?4KZCv37`)d`P7vA0&}MGavMW*-&#uh+} zgR-6x0hR?yYR&Uki2B6DT75LpAGwo-H7(63FHS4YJp- z=tTaZ;av!s5kNV4#i!)7F9jS*u2FkCtJ!726k$F z4CMc{;D4fT8)sS-HTZP2)mH;H463$F!AD<15kC9pr?6U3V!>lnm0KM;b`l9{F2^ei zyztNW7P}N8nFJpQ+?be~qiLEeT%5UMwGRq)S2T;p!&U}p$-Mf&b~6V&z0wt$DtR}I z(=A@u=zN`O@7F@X?5wUc(rAAltKByJb0?UN4oUU(>(}jr9cdSmb>RM!F%ws$a}5fz_0y;+eQgwwNFvCf_?#Zit8UcS`5*NufSg(#0x`?(cj2w+77B`OYx^C zeCEs@!*UvIcg^iBb~flSaiC}Qo}1SP=HFhTmUdm-KV$LNP*VEiL-ghZ0DK5Pa~Mp{SWepW96#`zWgKCZrwtxHwDu|puC1P+kH72u}Z?uKaLc&*%hA3 zfxK4aQ33{JV4MF>bnu#BEi~R-r>^n+WUx5fFL}}AjaKK7m~(+Wm-^dy=oIkTfxT)u zltGY`!JdAv^=6xQO?1$|ij9qvheJ@A(|3nN9$pcPxo4#%gbgQ_iNt3c>r!%7en60m zru&t%?KL)N@_?f-f3LN)NKSEycl)|I=3m)F~ytbUl3OUSMTz zYtWg{^zL1O`Db(J6Vi|ZT`{!Avt-fS+HCWXMj`s+^-u;YCnwDUH4`~y2)B?vsV$#A zm(_6RRu&!I4nA5tL zoa+?M+j^m$_A=Qc8Uf7bD*y8n7}f>^y3>s*pM}*SRU;9jiP4~q@1LQ1g@%>x6IDeM z)u4{pa%^{Ds?J>-PP7Gj5JWHNJ7#l|(?e#Blj%>TXTVn}jJ7}II%iZ)D3Y0~;)&ShAK#8f?etO`FK z&N%xB7{xSjIX69~r#~A-MS=Qv|Ev|rWwK}UziKjz?WWft!=mu1U7#7PZoD6n@Z3Dh z!4Thn`m{sSLXWL}zK90uy>)jQt$JDkl8|LCYX&q(p~N|92*iln&(9Am;=1*mEKma; zK*h*jl`9~4OW4jAauIX|~jvEb6`c<@9j#3Jd=aV8Q4p z*z|N=Y-(-^XOc3cOcV3|sBdMJ-&6)IG0jwn0Hu$0fq@D@I|7;=2~BW*|G%IKhMPB4 zlBHRtdHt6^+`*hRoHRyCgF&$yFU-4H7$s~K_R#8zAQakj|;|xg} zkoJRlgS?A2hx(;73DKjscR+Z zCVO;uanTACv7UiC`%s2*|EY(il-)}PjeDPsnsq|o*B*bDC2u}y`jh4c*`v}I5k8eM zUtW}|sH>|hsR)QxYrrWn?#ihI>fq2w`VL?+W82CU-@|fzh>EH%E&=9xD=s}cJ_D@> zHTm|m`1TS7c0XyF@P%P=WHFo))(XJpt zhBcf~1egO1CpUR?G z2YDoeM3q*S5HNou6}PsC22oEMUxa1@DfY zQiNhI>Fev0%#Z*bB%L|q$}Bs8bx|cr(!k6N$ZG>iioth5;#dn4Sp{S>kQ7!_ROFQW z1W=8=LpS*%D%oRX(*!1N+dp58McB8;Z~{C(R4^h2wy(kEzJ-o>nbRc$XM4NVw`jl9 zizeu^6Gphr+Nv?yO|e1g18^RZy$ZWNOOpbb_p5vKkGRik+OM;l_Qc-X%PURXb@4Nb z*W~i`JpoeIbgfaE;MK&zN=x>rZyv*Keb{ZnLdCeaxaq&xxpFLX_9e;bO z*lpqQ!NGYu{n4a!eleEO7owDY>*h|AiE__yWs< zPQUhEmFq(+#Dcmxy=F=p*Mp4p#wTz8ku6j2xYnjtc>$c96(TxFy8i#|{X4+drJJp! z03~4TDZp2VP8EBn?Tm7Hw9HGThw(ci6I z34dK#(i+qK6}K-N7kJNuKY`U&z}TfiOO>Z%5V6ofIzi4G`xiJ6Y*Odv3Qc`}P zkTG6Kmy#;H5pLQ6=BLmXORI%XF+s7h;qPN(OM~;kJR~)J8q?O zT>rmKF0a331NHll1Jb(#Nn*qQ>v#42`x*Wp8?ZPWjWmdKI;Vst00bJVi~s-t diff --git a/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-light-linux.png b/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-light-linux.png index 5017b68354f40b2006739ba5dd6702c78b2fb021..499fe117c6ead0c0cb065d20fa4849b69d28884c 100644 GIT binary patch literal 19579 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

    6W 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 Date: Tue, 13 Oct 2026 21:01:39 -0400 Subject: [PATCH 08/16] fix(DataTable): match bulk actions to header typography and height Remove the built-in clear action, use the concise selected count, and preserve header dimensions across selection changes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .changeset/data-table-bulk-actions.md | 2 +- e2e/components/DataTableBulkActions.test.ts | 44 ++++++++++++++++--- .../src/DataTable/DataTable.accessibility.md | 3 +- .../react/src/DataTable/DataTable.docs.json | 16 +------ .../DataTable/DataTable.features.stories.tsx | 1 + packages/react/src/DataTable/DataTable.tsx | 11 ++--- .../src/DataTable/DataTable.types.test.tsx | 6 +-- .../src/DataTable/TableBulkActions.module.css | 12 ++++- .../react/src/DataTable/TableBulkActions.tsx | 24 ++-------- .../__tests__/DataTableBulkActions.test.tsx | 37 ++++++---------- 10 files changed, 80 insertions(+), 76 deletions(-) diff --git a/.changeset/data-table-bulk-actions.md b/.changeset/data-table-bulk-actions.md index 9d0b27b44ce..c37050478b3 100644 --- a/.changeset/data-table-bulk-actions.md +++ b/.changeset/data-table-bulk-actions.md @@ -2,4 +2,4 @@ '@primer/react': minor --- -DataTable: Add bulk actions in the table header with selection counts, clearing selection, and focus recovery. +DataTable: Add bulk actions in the table header with selection counts and focus recovery. diff --git a/e2e/components/DataTableBulkActions.test.ts b/e2e/components/DataTableBulkActions.test.ts index cfaad3abb86..3e7e911a528 100644 --- a/e2e/components/DataTableBulkActions.test.ts +++ b/e2e/components/DataTableBulkActions.test.ts @@ -24,7 +24,8 @@ test.describe('DataTable bulk actions', () => { const actions = page.getByRole('table').getByRole('group', {name: 'Bulk actions'}) await expect(page.getByRole('button', {name: 'Repository', exact: true})).toHaveCount(0) await expect(page.getByRole('columnheader', {name: 'Repository', exact: true})).toHaveCount(1) - await expect(actions.getByText('3 rows selected')).toBeVisible() + await expect(actions.getByText('3 selected')).toBeVisible() + await expect(actions.getByRole('button', {name: 'Clear selection'})).toHaveCount(0) const actionsBox = await actions.boundingBox() const headerBox = await selectAll.boundingBox() expect(actionsBox).not.toBeNull() @@ -34,8 +35,9 @@ test.describe('DataTable bulk actions', () => { expect(headerBox!.x + headerBox!.width).toBeLessThan(actionsBox!.x) await page.keyboard.press('Tab') - await expect(actions.getByRole('button', {name: 'Clear selection'})).toBeFocused() - await page.keyboard.press('Enter') + await expect(actions.getByRole('button', {name: 'Delete selected'})).toBeFocused() + await page.keyboard.press('Shift+Tab') + await page.keyboard.press('Space') await expect(selectAll).toBeFocused() await expect(actions).toHaveCount(0) await expect(page.getByRole('button', {name: 'Repository', exact: true})).toBeVisible() @@ -57,6 +59,38 @@ test.describe('DataTable bulk actions', () => { await expect(page).toHaveNoViolations() }) + for (const density of ['condensed', 'normal', 'spacious'] as const) { + test(`preserves header height and typography (${density}) @avt`, async ({page}) => { + await visit(page, {id: storyId}) + const table = page.getByRole('table') + await table.evaluate((element, value) => { + element.setAttribute('data-cell-padding', value) + }, density) + await page.getByRole('button', {name: 'Reset repositories'}).click() + const head = table.locator('thead') + const before = await head.boundingBox() + const columnStyle = await page.getByRole('columnheader', {name: 'Repository', exact: true}).evaluate(element => { + const style = getComputedStyle(element) + return [style.fontFamily, style.fontSize, style.fontWeight, style.lineHeight, style.color] + }) + + await page.getByRole('checkbox', {name: 'Select rows', exact: true}).click() + const count = table.getByText('3 selected', {exact: true}) + await expect(count).toBeVisible() + const selected = await head.boundingBox() + expect(selected!.height).toBe(before!.height) + expect( + await count.evaluate(element => { + const style = getComputedStyle(element) + return [style.fontFamily, style.fontSize, style.fontWeight, style.lineHeight, style.color] + }), + ).toEqual(columnStyle) + + await page.getByRole('checkbox', {name: 'Select rows', exact: true}).click() + expect((await head.boundingBox())!.height).toBe(before!.height) + }) + } + for (const theme of ['light', 'dark'] as const) { test(`mixed ${theme} @vrt`, async ({page}) => { await visit(page, { @@ -77,7 +111,7 @@ test.describe('DataTable bulk actions', () => { '* {line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important;} p {margin-bottom: 2em !important;}', }) const actions = page.getByRole('group', {name: 'Bulk actions'}) - await expect(actions.getByRole('button', {name: 'Clear selection'})).toBeVisible() + await expect(actions.getByText('1 selected')).toBeVisible() await expect(actions.getByRole('button', {name: 'Delete selected'})).toBeVisible() const dimensions = await actions.evaluate(element => ({ width: element.clientWidth, @@ -90,7 +124,7 @@ test.describe('DataTable bulk actions', () => { await expect(deleteButton).toBeInViewport({ratio: 1}) const buttonBox = await deleteButton.boundingBox() expect(buttonBox!.width).toBeLessThanOrEqual(320) - await actions.getByRole('button', {name: 'Clear selection'}).click() + await deleteButton.click() await expect(page.getByRole('checkbox', {name: 'Select rows', exact: true})).toBeFocused() }) }) diff --git a/packages/react/src/DataTable/DataTable.accessibility.md b/packages/react/src/DataTable/DataTable.accessibility.md index debfda0c2dd..84479748352 100644 --- a/packages/react/src/DataTable/DataTable.accessibility.md +++ b/packages/react/src/DataTable/DataTable.accessibility.md @@ -284,7 +284,8 @@ labels while rows are selected. Column labels remain available to assistive technology, but sorting controls are removed until selection is cleared. The named action group uses native Tab/Shift+Tab navigation. Count changes are announced, including zero. Use `bulkActionsProps` -to localize the group name, clear button, and count label. +to localize the group name and count label. The header checkbox toggles selection; +there is no separate clear button. Use small action buttons to fit the header. Showing actions preserves checkbox focus. When clearing selection or updating rows removes the focused action, `DataTable` restores focus to select-all, or to diff --git a/packages/react/src/DataTable/DataTable.docs.json b/packages/react/src/DataTable/DataTable.docs.json index 028eab4af17..9f5e5d672bb 100644 --- a/packages/react/src/DataTable/DataTable.docs.json +++ b/packages/react/src/DataTable/DataTable.docs.json @@ -154,8 +154,8 @@ }, { "name": "bulkActionsProps", - "type": "Pick", - "description": "Localize the bulk-action group name, selected-count announcement (including zero), and clear-selection label." + "type": "Pick", + "description": "Localize the bulk-action group name and selected-count announcement (including zero)." }, { "name": "bulkActionsReturnFocusRef", @@ -220,12 +220,6 @@ "required": true, "description": "The effectively selected row count. Keep the component mounted at zero so count announcements and focus recovery can complete." }, - { - "name": "onClearSelection", - "type": "() => void", - "required": true, - "description": "Request clearing selection. The consumer owns selection state." - }, { "name": "onFocusReturn", "type": "() => void", @@ -236,12 +230,6 @@ "type": "(selectedCount: number) => string", "description": "Localize the visible and announced selected count, including zero." }, - { - "name": "clearSelectionLabel", - "type": "string", - "defaultValue": "'Clear selection'", - "description": "Localize the clear-selection button." - }, { "name": "aria-label", "type": "string", diff --git a/packages/react/src/DataTable/DataTable.features.stories.tsx b/packages/react/src/DataTable/DataTable.features.stories.tsx index 6a0234de98e..38c6eda9f5a 100644 --- a/packages/react/src/DataTable/DataTable.features.stories.tsx +++ b/packages/react/src/DataTable/DataTable.features.stories.tsx @@ -1817,6 +1817,7 @@ export const WithBulkActions = () => { bulkActionsReturnFocusRef={rows.length === 0 ? resetButtonRef : undefined} renderBulkActions={({selectedRows: effectiveIds, selectedCount, clearSelection}) => ( -

      {children}
      - - ) : null} + {active ?
      {children}
      : null}
) }) diff --git a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx index 0baf7c46af0..44cb11e7412 100644 --- a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx +++ b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx @@ -59,12 +59,13 @@ describe('DataTable bulk actions', () => { />, ) - expect(screen.getByText('2 rows selected')).toBeVisible() + expect(screen.getByText('2 selected')).toBeVisible() + expect(screen.queryByRole('button', {name: 'Clear selection'})).not.toBeInTheDocument() await user.click(screen.getByRole('button', {name: 'Archive'})) expect(onAction).toHaveBeenLastCalledWith({selectedRows: new Set([1, '1']), selectedCount: 2}) expect(screen.queryByRole('button', {name: 'Name'})).not.toBeInTheDocument() expect(screen.getByRole('columnheader', {name: 'Name'})).toBeInTheDocument() - await user.click(screen.getByRole('button', {name: 'Clear selection'})) + await user.click(screen.getByRole('checkbox', {name: 'Select rows'})) await user.click(screen.getByRole('button', {name: 'Name'})) expect(screen.getByRole('columnheader', {name: 'Name'})).toHaveAttribute('aria-sort', 'ascending') await user.click(screen.getByRole('checkbox', {name: 'Select rows'})) @@ -101,11 +102,11 @@ describe('DataTable bulk actions', () => { checkbox.focus() await user.keyboard(' ') expect(checkbox).toHaveFocus() - await waitFor(() => expect(getLiveRegion().getMessage('polite')).toBe('1 row selected')) + await waitFor(() => expect(getLiveRegion().getMessage('polite')).toBe('1 selected')) await user.click(screen.getByRole('checkbox', {name: 'Select Alpha'})) - await waitFor(() => expect(getLiveRegion().getMessage('polite')).toBe('2 rows selected')) - await user.click(screen.getByRole('button', {name: 'Clear selection'})) - await waitFor(() => expect(getLiveRegion().getMessage('polite')).toBe('0 rows selected')) + await waitFor(() => expect(getLiveRegion().getMessage('polite')).toBe('2 selected')) + await user.click(screen.getByRole('button', {name: 'Apply to 2'})) + await waitFor(() => expect(getLiveRegion().getMessage('polite')).toBe('0 selected')) expect(screen.getByRole('checkbox', {name: 'Select rows'})).toHaveFocus() expect(screen.queryByRole('group', {name: 'Bulk actions'})).not.toBeInTheDocument() }) @@ -183,7 +184,7 @@ describe('DataTable bulk actions', () => { ) } render() - await user.click(screen.getByRole('button', {name: 'Clear selection'})) + await user.click(screen.getByRole('button', {name: 'Apply to 1'})) expect(screen.getByRole('button', {name: 'Add repository'})).toHaveFocus() }) @@ -298,7 +299,7 @@ describe('DataTable bulk actions', () => { /> , ) - expect(screen.getByText('1 row selected')).toBeVisible() + expect(screen.getByText('1 selected')).toBeVisible() expect(onSelectionChange).not.toHaveBeenCalled() expect(screen.getByRole('button', {name: 'Elsewhere'})).toHaveFocus() }) @@ -313,14 +314,13 @@ describe('DataTable bulk actions', () => { renderBulkActions={renderActions} bulkActionsProps={{ 'aria-label': 'Selected repositories', - clearSelectionLabel: 'Deselect repositories', getSelectedCountLabel: count => `${count} repositories chosen`, }} />, ) const group = screen.getByRole('group', {name: 'Selected repositories'}) expect(within(group).getByText('1 repositories chosen')).toBeVisible() - expect(within(group).getByRole('button', {name: 'Deselect repositories'})).toBeVisible() + expect(within(group).getAllByRole('button')).toHaveLength(1) }) it('preserves structure through server rendering and hydration', async () => { @@ -352,7 +352,7 @@ describe('DataTable bulk actions', () => { ), ).toBe(true) expect(within(container).getByRole('table')).toBe(serverTable) - expect(within(container).getByText('1 row selected')).toBeVisible() + expect(within(container).getByText('1 selected')).toBeVisible() } finally { consoleErrorSpy.mockRestore() await act(async () => root?.unmount()) @@ -362,15 +362,11 @@ describe('DataTable bulk actions', () => { }) describe('Table.BulkActions', () => { - implementsClassName( - props => {}} {...props} />, - classes.TableBulkActions, - ) + implementsClassName(props => , classes.TableBulkActions) it('forwards root attributes and ref, preserves child order and native Tab order', async () => { const user = userEvent.setup() const ref = React.createRef() - const onClearSelection = vi.fn() const onFocusCapture = vi.fn() const onBlurCapture = vi.fn() render( @@ -378,7 +374,6 @@ describe('Table.BulkActions', () => { ref={ref} data-testid="actions" selectedCount={2} - onClearSelection={onClearSelection} onFocusCapture={onFocusCapture} onBlurCapture={onBlurCapture} > @@ -391,14 +386,10 @@ describe('Table.BulkActions', () => { expect(group).toHaveAttribute('data-testid', 'actions') expect(group).toHaveAttribute('data-component', 'Table.BulkActions') await user.tab() - expect(screen.getByRole('button', {name: 'Clear selection'})).toHaveFocus() - expect(onFocusCapture).toHaveBeenCalledOnce() - await user.keyboard('{Enter}') - expect(onClearSelection).toHaveBeenCalledOnce() - await user.tab() expect(screen.getByRole('button', {name: 'First'})).toHaveFocus() - expect(onBlurCapture).toHaveBeenCalledOnce() + expect(onFocusCapture).toHaveBeenCalledOnce() await user.tab() expect(screen.getByRole('button', {name: 'Second'})).toHaveFocus() + expect(onBlurCapture).toHaveBeenCalledOnce() }) }) From 7c204dfb583810671c8d66308e59c92ad3b131ee Mon Sep 17 00:00:00 2001 From: rickyzhangca <16908811+rickyzhangca@users.noreply.github.com> Date: Wed, 14 Oct 2026 01:12:56 +0000 Subject: [PATCH 09/16] test(vrt): update snapshots --- ...DataTable-BulkActions-Mixed-dark-linux.png | Bin 19465 -> 17333 bytes ...ataTable-BulkActions-Mixed-light-linux.png | Bin 19579 -> 17385 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-dark-linux.png b/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-dark-linux.png index fc8613eb936eda8b249255485b873020b9ed9b3c..9c1e63d290f1f9c106014999d401d960dfb4e293 100644 GIT binary patch literal 17333 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 literal 19465 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 diff --git a/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-light-linux.png b/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-light-linux.png index 499fe117c6ead0c0cb065d20fa4849b69d28884c..9a76d1fe1dd8e9bf212119840cef01d6fb4bdf8c 100644 GIT binary patch literal 17385 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

6W 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 Date: Tue, 13 Oct 2026 21:34:25 -0400 Subject: [PATCH 10/16] Polish bulk action alignment and simplify the example Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- e2e/components/DataTableBulkActions.test.ts | 37 +++++++++++++++-- .../DataTable/DataTable.features.stories.tsx | 40 +++++++++++-------- .../src/DataTable/TableBulkActions.module.css | 8 +++- .../react/src/DataTable/TableBulkActions.tsx | 4 ++ 4 files changed, 68 insertions(+), 21 deletions(-) diff --git a/e2e/components/DataTableBulkActions.test.ts b/e2e/components/DataTableBulkActions.test.ts index 3e7e911a528..7d22fdb96c0 100644 --- a/e2e/components/DataTableBulkActions.test.ts +++ b/e2e/components/DataTableBulkActions.test.ts @@ -34,9 +34,12 @@ test.describe('DataTable bulk actions', () => { expect(headerBox!.y + headerBox!.height).toBeLessThanOrEqual(actionsBox!.y + actionsBox!.height) expect(headerBox!.x + headerBox!.width).toBeLessThan(actionsBox!.x) + await page.keyboard.press('Tab') + await expect(actions.getByRole('button', {name: 'Make internal'})).toBeFocused() await page.keyboard.press('Tab') await expect(actions.getByRole('button', {name: 'Delete selected'})).toBeFocused() await page.keyboard.press('Shift+Tab') + await page.keyboard.press('Shift+Tab') await page.keyboard.press('Space') await expect(selectAll).toBeFocused() await expect(actions).toHaveCount(0) @@ -47,7 +50,7 @@ test.describe('DataTable bulk actions', () => { test('deletion and final-record focus @avt', async ({page}) => { await visit(page, {id: storyId}) await page.getByRole('button', {name: 'Delete selected'}).click() - await expect(page.locator('#storybook-root').getByText('1 repository deleted')).toBeVisible() + await expect(page.getByRole('rowheader', {name: 'primer/react', exact: true})).toHaveCount(0) const selectAll = page.getByRole('checkbox', {name: 'Select rows', exact: true}) await expect(selectAll).toBeFocused() @@ -59,6 +62,15 @@ test.describe('DataTable bulk actions', () => { await expect(page).toHaveNoViolations() }) + test('makes only selected repositories internal @avt', async ({page}) => { + await visit(page, {id: storyId}) + await page.getByRole('button', {name: 'Make internal'}).click() + await expect(page.getByRole('row', {name: /primer\/react/}).getByRole('cell', {name: 'Internal'})).toBeVisible() + await expect(page.getByRole('row', {name: /primer\/css/}).getByRole('cell', {name: 'Public'})).toBeVisible() + await expect(page.getByRole('checkbox', {name: 'Select rows', exact: true})).toBeFocused() + await expect(page.getByRole('group', {name: 'Bulk actions'})).toHaveCount(0) + }) + for (const density of ['condensed', 'normal', 'spacious'] as const) { test(`preserves header height and typography (${density}) @avt`, async ({page}) => { await visit(page, {id: storyId}) @@ -69,6 +81,7 @@ test.describe('DataTable bulk actions', () => { await page.getByRole('button', {name: 'Reset repositories'}).click() const head = table.locator('thead') const before = await head.boundingBox() + const labelBefore = await page.getByRole('button', {name: 'Repository', exact: true}).boundingBox() const columnStyle = await page.getByRole('columnheader', {name: 'Repository', exact: true}).evaluate(element => { const style = getComputedStyle(element) return [style.fontFamily, style.fontSize, style.fontWeight, style.lineHeight, style.color] @@ -79,6 +92,16 @@ test.describe('DataTable bulk actions', () => { await expect(count).toBeVisible() const selected = await head.boundingBox() expect(selected!.height).toBe(before!.height) + expect((await count.boundingBox())!.x).toBe(labelBefore!.x) + const actions = table.getByRole('group', {name: 'Bulk actions'}) + await expect(actions.getByRole('button')).toHaveCount(2) + const padding = await actions.evaluate(element => { + const cell = element.parentElement! + return getComputedStyle(cell).paddingInlineEnd + }) + expect(padding).toBe('8px') + const lastAction = await actions.getByRole('button', {name: 'Delete selected'}).boundingBox() + expect(selected!.x + selected!.width - lastAction!.x - lastAction!.width).toBe(9) expect( await count.evaluate(element => { const style = getComputedStyle(element) @@ -119,12 +142,18 @@ test.describe('DataTable bulk actions', () => { })) expect(dimensions.scrollWidth).toBeLessThanOrEqual(dimensions.width) expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBeLessThanOrEqual(320) + const selectAll = page.getByRole('checkbox', {name: 'Select rows', exact: true}) + await selectAll.focus() + await page.keyboard.press('Tab') + await expect(actions.getByRole('button', {name: 'Make internal'})).toBeFocused() + await page.keyboard.press('Tab') const deleteButton = actions.getByRole('button', {name: 'Delete selected'}) - await deleteButton.focus() + await expect(deleteButton).toBeFocused() await expect(deleteButton).toBeInViewport({ratio: 1}) const buttonBox = await deleteButton.boundingBox() expect(buttonBox!.width).toBeLessThanOrEqual(320) - await deleteButton.click() - await expect(page.getByRole('checkbox', {name: 'Select rows', exact: true})).toBeFocused() + await page.keyboard.press('Enter') + await expect(selectAll).toBeFocused() + await expect(selectAll).toBeInViewport({ratio: 1}) }) }) diff --git a/packages/react/src/DataTable/DataTable.features.stories.tsx b/packages/react/src/DataTable/DataTable.features.stories.tsx index 38c6eda9f5a..cd1140359b7 100644 --- a/packages/react/src/DataTable/DataTable.features.stories.tsx +++ b/packages/react/src/DataTable/DataTable.features.stories.tsx @@ -20,7 +20,6 @@ import Heading from '../Heading' import Label from '../Label' import LabelGroup from '../LabelGroup' import RelativeTime from '../RelativeTime' -import {AriaStatus} from '../live-region' import VisuallyHidden from '../_VisuallyHidden' import {createColumnHelper} from './column' import type {DataTableData, DataTableRowGroup, UniqueRow} from './row' @@ -1783,7 +1782,6 @@ export const WithBulkActions = () => { const titleId = React.useId() const [rows, setRows] = React.useState(repositories) const [selectedRows, setSelectedRows] = React.useState>(() => new Set([1])) - const [message, setMessage] = React.useState('') const resetButtonRef = React.useRef(null) return ( @@ -1795,7 +1793,6 @@ export const WithBulkActions = () => { onClick={() => { setRows(repositories) setSelectedRows(new Set()) - setMessage('') }} > Reset repositories @@ -1815,21 +1812,32 @@ export const WithBulkActions = () => { selectedRows={selectedRows} onSelectionChange={({selectedRows: next}) => setSelectedRows(next)} bulkActionsReturnFocusRef={rows.length === 0 ? resetButtonRef : undefined} - renderBulkActions={({selectedRows: effectiveIds, selectedCount, clearSelection}) => ( - + renderBulkActions={({selectedRows: effectiveIds, clearSelection}) => ( + <> + + + )} /> - {message} ) } diff --git a/packages/react/src/DataTable/TableBulkActions.module.css b/packages/react/src/DataTable/TableBulkActions.module.css index 0966c60650b..f2027ed2431 100644 --- a/packages/react/src/DataTable/TableBulkActions.module.css +++ b/packages/react/src/DataTable/TableBulkActions.module.css @@ -39,7 +39,6 @@ /* stylelint-disable-next-line primer/spacing */ padding: var(--table-cell-padding); padding-block: 0; - padding-inline-end: var(--base-size-16); background-color: var(--bgColor-muted); border-block-start: var(--borderWidth-thin) solid var(--borderColor-default); border-block-end: var(--borderWidth-thin) solid var(--borderColor-default); @@ -47,3 +46,10 @@ /* stylelint-disable-next-line primer/borders */ border-start-end-radius: var(--table-border-radius); } + +/* This spans data columns, despite being the first cell in its DOM row. */ +.HeaderRow > .BulkActionsCell:first-child:last-child { + /* stylelint-disable-next-line primer/spacing */ + padding-inline-start: var(--cell-padding-inline, var(--base-size-12)); + padding-inline-end: var(--base-size-8); +} diff --git a/packages/react/src/DataTable/TableBulkActions.tsx b/packages/react/src/DataTable/TableBulkActions.tsx index 095d3a74155..483a49262b0 100644 --- a/packages/react/src/DataTable/TableBulkActions.tsx +++ b/packages/react/src/DataTable/TableBulkActions.tsx @@ -67,6 +67,10 @@ const TableBulkActions = React.forwardRef {...rest} onFocusCapture={event => { focusedAction.current = event.target + // Native focus scrolling can miss controls in the grid-overlaid header. + if (event.currentTarget.contains(event.target)) { + event.target.scrollIntoView({block: 'nearest', inline: 'nearest'}) + } if (!event.defaultPrevented) { onFocusCapture?.(event) } From 4ad4fa999a7b115f253add86f98f8393afddf20e Mon Sep 17 00:00:00 2001 From: Ricky Zhang Date: Tue, 13 Oct 2026 21:40:21 -0400 Subject: [PATCH 11/16] Trim redundant bulk action assertions and comments Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- e2e/components/DataTableBulkActions.test.ts | 18 +----- .../src/DataTable/DataTable.types.test.tsx | 9 +-- .../react/src/DataTable/TableBulkActions.tsx | 6 +- .../__tests__/DataTableBulkActions.test.tsx | 56 ++++++------------- 4 files changed, 22 insertions(+), 67 deletions(-) diff --git a/e2e/components/DataTableBulkActions.test.ts b/e2e/components/DataTableBulkActions.test.ts index 7d22fdb96c0..576873dfcc5 100644 --- a/e2e/components/DataTableBulkActions.test.ts +++ b/e2e/components/DataTableBulkActions.test.ts @@ -28,8 +28,6 @@ test.describe('DataTable bulk actions', () => { await expect(actions.getByRole('button', {name: 'Clear selection'})).toHaveCount(0) const actionsBox = await actions.boundingBox() const headerBox = await selectAll.boundingBox() - expect(actionsBox).not.toBeNull() - expect(headerBox).not.toBeNull() expect(headerBox!.y).toBeGreaterThanOrEqual(actionsBox!.y) expect(headerBox!.y + headerBox!.height).toBeLessThanOrEqual(actionsBox!.y + actionsBox!.height) expect(headerBox!.x + headerBox!.width).toBeLessThan(actionsBox!.x) @@ -72,7 +70,7 @@ test.describe('DataTable bulk actions', () => { }) for (const density of ['condensed', 'normal', 'spacious'] as const) { - test(`preserves header height and typography (${density}) @avt`, async ({page}) => { + test(`preserves header height, typography and alignment (${density}) @avt`, async ({page}) => { await visit(page, {id: storyId}) const table = page.getByRole('table') await table.evaluate((element, value) => { @@ -95,12 +93,8 @@ test.describe('DataTable bulk actions', () => { expect((await count.boundingBox())!.x).toBe(labelBefore!.x) const actions = table.getByRole('group', {name: 'Bulk actions'}) await expect(actions.getByRole('button')).toHaveCount(2) - const padding = await actions.evaluate(element => { - const cell = element.parentElement! - return getComputedStyle(cell).paddingInlineEnd - }) - expect(padding).toBe('8px') const lastAction = await actions.getByRole('button', {name: 'Delete selected'}).boundingBox() + // 8px padding plus the 1px header border. expect(selected!.x + selected!.width - lastAction!.x - lastAction!.width).toBe(9) expect( await count.evaluate(element => { @@ -135,12 +129,6 @@ test.describe('DataTable bulk actions', () => { }) const actions = page.getByRole('group', {name: 'Bulk actions'}) await expect(actions.getByText('1 selected')).toBeVisible() - await expect(actions.getByRole('button', {name: 'Delete selected'})).toBeVisible() - const dimensions = await actions.evaluate(element => ({ - width: element.clientWidth, - scrollWidth: element.scrollWidth, - })) - expect(dimensions.scrollWidth).toBeLessThanOrEqual(dimensions.width) expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBeLessThanOrEqual(320) const selectAll = page.getByRole('checkbox', {name: 'Select rows', exact: true}) await selectAll.focus() @@ -150,8 +138,6 @@ test.describe('DataTable bulk actions', () => { const deleteButton = actions.getByRole('button', {name: 'Delete selected'}) await expect(deleteButton).toBeFocused() await expect(deleteButton).toBeInViewport({ratio: 1}) - const buttonBox = await deleteButton.boundingBox() - expect(buttonBox!.width).toBeLessThanOrEqual(320) await page.keyboard.press('Enter') await expect(selectAll).toBeFocused() await expect(selectAll).toBeInViewport({ratio: 1}) diff --git a/packages/react/src/DataTable/DataTable.types.test.tsx b/packages/react/src/DataTable/DataTable.types.test.tsx index a11a7b3b235..ed30ab42ba3 100644 --- a/packages/react/src/DataTable/DataTable.types.test.tsx +++ b/packages/react/src/DataTable/DataTable.types.test.tsx @@ -1,6 +1,6 @@ import {lazy} from 'react' import type {Column} from './column' -import {DataTable, type DataTableProps, type DataTableBulkActionsContext} from './DataTable' +import {DataTable, type DataTableProps} from './DataTable' import type {DataTableRowGroup} from './row' import {useTable} from './useTable' import {Table, type DataTableRowId} from '../experimental' @@ -249,11 +249,6 @@ export function shouldAcceptRowSelectionProps() { } export function shouldAcceptBulkActions() { - const context: DataTableBulkActionsContext = { - selectedRows: new Set([1]), - selectedCount: 1, - clearSelection: () => {}, - } const config = ( `${count} selected`}} /> ) - const composed = Actions + const composed = Actions return {config, composed} } diff --git a/packages/react/src/DataTable/TableBulkActions.tsx b/packages/react/src/DataTable/TableBulkActions.tsx index 483a49262b0..1657d538da2 100644 --- a/packages/react/src/DataTable/TableBulkActions.tsx +++ b/packages/react/src/DataTable/TableBulkActions.tsx @@ -43,8 +43,7 @@ const TableBulkActions = React.forwardRef const focusedAction = useRef(null) const active = selectedCount > 0 - // Recover only focus lost to removed actions, never steal it from a dialog or - // another control. The action owner decides where focus should return. + // Controlled updates can remove the focused action after its event has finished. useLayoutEffect(() => { const element = focusedAction.current if (element && !element.isConnected) { @@ -76,8 +75,7 @@ const TableBulkActions = React.forwardRef } }} onBlurCapture={event => { - // A blur to non-focusable content has no relatedTarget. Only retain a - // detached target, whose removal may require focus recovery. + // Clicking non-focusable content blurs with a null relatedTarget. if (event.target.isConnected) { focusedAction.current = null } diff --git a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx index 44cb11e7412..7ab819d6ec0 100644 --- a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx +++ b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx @@ -60,18 +60,29 @@ describe('DataTable bulk actions', () => { ) expect(screen.getByText('2 selected')).toBeVisible() - expect(screen.queryByRole('button', {name: 'Clear selection'})).not.toBeInTheDocument() await user.click(screen.getByRole('button', {name: 'Archive'})) expect(onAction).toHaveBeenLastCalledWith({selectedRows: new Set([1, '1']), selectedCount: 2}) + }) + + it('preserves column names and sort state while replacing sorting controls', async () => { + const user = userEvent.setup() + render( + , + ) expect(screen.queryByRole('button', {name: 'Name'})).not.toBeInTheDocument() expect(screen.getByRole('columnheader', {name: 'Name'})).toBeInTheDocument() - await user.click(screen.getByRole('checkbox', {name: 'Select rows'})) + await user.click(screen.getByRole('button', {name: 'Apply to 1'})) await user.click(screen.getByRole('button', {name: 'Name'})) expect(screen.getByRole('columnheader', {name: 'Name'})).toHaveAttribute('aria-sort', 'ascending') await user.click(screen.getByRole('checkbox', {name: 'Select rows'})) expect(screen.getByRole('columnheader', {name: 'Name'})).toHaveAttribute('aria-sort', 'ascending') - await user.click(screen.getByRole('button', {name: 'Archive'})) - expect(onAction).toHaveBeenLastCalledWith({selectedRows: new Set([1, '1']), selectedCount: 2}) + expect(screen.queryByRole('button', {name: 'Name'})).not.toBeInTheDocument() }) it('does not render actions without enabled selection or effectively selected rows', () => { @@ -91,7 +102,6 @@ describe('DataTable bulk actions', () => { ) expect(renderer).not.toHaveBeenCalled() expect(screen.queryByRole('group', {name: 'Bulk actions'})).not.toBeInTheDocument() - expect(screen.queryByRole('button', {name: 'Clear selection'})).not.toBeInTheDocument() }) it('preserves checkbox focus when actions appear and announces counts including zero', async () => { @@ -271,39 +281,6 @@ describe('DataTable bulk actions', () => { expect(screen.getByRole('checkbox', {name: 'Select rows'})).toHaveFocus() }) - it('updates effective count after removal without emitting selection changes or stealing outside focus', () => { - const onSelectionChange = vi.fn() - const {rerender} = render( - <> - - ([1, '1'])} - onSelectionChange={onSelectionChange} - renderBulkActions={renderActions} - /> - , - ) - screen.getByRole('button', {name: 'Elsewhere'}).focus() - rerender( - <> - - - , - ) - expect(screen.getByText('1 selected')).toBeVisible() - expect(onSelectionChange).not.toHaveBeenCalled() - expect(screen.getByRole('button', {name: 'Elsewhere'})).toHaveFocus() - }) - it('supports localized labels', () => { render( { ) const group = screen.getByRole('group', {name: 'Selected repositories'}) expect(within(group).getByText('1 repositories chosen')).toBeVisible() - expect(within(group).getAllByRole('button')).toHaveLength(1) }) it('preserves structure through server rendering and hydration', async () => { @@ -364,7 +340,7 @@ describe('DataTable bulk actions', () => { describe('Table.BulkActions', () => { implementsClassName(props => , classes.TableBulkActions) - it('forwards root attributes and ref, preserves child order and native Tab order', async () => { + it('forwards root attributes, ref and focus handlers', async () => { const user = userEvent.setup() const ref = React.createRef() const onFocusCapture = vi.fn() From 9061484802351c8cf9951b87c044b2b0ac613f91 Mon Sep 17 00:00:00 2001 From: rickyzhangca <16908811+rickyzhangca@users.noreply.github.com> Date: Wed, 14 Oct 2026 01:45:28 +0000 Subject: [PATCH 12/16] test(vrt): update snapshots --- ...DataTable-BulkActions-Mixed-dark-linux.png | Bin 17333 -> 18784 bytes ...ataTable-BulkActions-Mixed-light-linux.png | Bin 17385 -> 18830 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-dark-linux.png b/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-dark-linux.png index 9c1e63d290f1f9c106014999d401d960dfb4e293..24cce1f7f8cea5c927e7ace59ecca27e28e7e1cf 100644 GIT binary patch literal 18784 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 diff --git a/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-light-linux.png b/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-light-linux.png index 9a76d1fe1dd8e9bf212119840cef01d6fb4bdf8c..5e162e365ec79d064bc2ea8c8f42d13c64266319 100644 GIT binary patch literal 18830 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 HTMz#i)!V>a literal 17385 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 f{%z-Ng*a$D5t Date: Thu, 29 Oct 2026 16:22:48 -0400 Subject: [PATCH 13/16] fix(DataTable): address bulk action review feedback Preserve accessible header names without hidden tab stops, recover focus after child-only action removal, and support nullable recovery refs. Run bulk action checks in accessibility CI and demonstrate collapsible groups. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- e2e/components/DataTableBulkActions.test.ts | 12 +- .../src/DataTable/DataTable.accessibility.md | 9 +- .../react/src/DataTable/DataTable.docs.json | 2 +- .../DataTable/DataTable.features.stories.tsx | 1 + packages/react/src/DataTable/DataTable.tsx | 20 ++- .../src/DataTable/DataTable.types.test.tsx | 4 +- .../react/src/DataTable/TableBulkActions.tsx | 26 ++- .../__tests__/DataTableBulkActions.test.tsx | 154 +++++++++++++++++- 8 files changed, 207 insertions(+), 21 deletions(-) diff --git a/e2e/components/DataTableBulkActions.test.ts b/e2e/components/DataTableBulkActions.test.ts index 576873dfcc5..dbb875355fb 100644 --- a/e2e/components/DataTableBulkActions.test.ts +++ b/e2e/components/DataTableBulkActions.test.ts @@ -6,7 +6,7 @@ const storyId = 'experimental-components-datatable-features--with-bulk-actions' test.describe('DataTable bulk actions', () => { for (const theme of themes) { - test(`${theme} @avt`, async ({page}) => { + test(`${theme} @aat`, async ({page}) => { await visit(page, { id: storyId, globals: {colorScheme: theme}, @@ -15,7 +15,7 @@ test.describe('DataTable bulk actions', () => { }) } - test('bulk actions replace column labels beside the header checkbox @avt', async ({page}) => { + test('bulk actions replace column labels beside the header checkbox @aat', async ({page}) => { await visit(page, {id: storyId}) const selectAll = page.getByRole('checkbox', {name: 'Select rows', exact: true}) await selectAll.focus() @@ -45,7 +45,7 @@ test.describe('DataTable bulk actions', () => { await expect(page).toHaveNoViolations() }) - test('deletion and final-record focus @avt', async ({page}) => { + test('deletion and final-record focus @aat', async ({page}) => { await visit(page, {id: storyId}) await page.getByRole('button', {name: 'Delete selected'}).click() await expect(page.getByRole('rowheader', {name: 'primer/react', exact: true})).toHaveCount(0) @@ -60,7 +60,7 @@ test.describe('DataTable bulk actions', () => { await expect(page).toHaveNoViolations() }) - test('makes only selected repositories internal @avt', async ({page}) => { + test('makes only selected repositories internal @aat', async ({page}) => { await visit(page, {id: storyId}) await page.getByRole('button', {name: 'Make internal'}).click() await expect(page.getByRole('row', {name: /primer\/react/}).getByRole('cell', {name: 'Internal'})).toBeVisible() @@ -70,7 +70,7 @@ test.describe('DataTable bulk actions', () => { }) for (const density of ['condensed', 'normal', 'spacious'] as const) { - test(`preserves header height, typography and alignment (${density}) @avt`, async ({page}) => { + test(`preserves header height, typography and alignment (${density}) @aat`, async ({page}) => { await visit(page, {id: storyId}) const table = page.getByRole('table') await table.evaluate((element, value) => { @@ -118,7 +118,7 @@ test.describe('DataTable bulk actions', () => { }) } - test('header actions remain reachable in a narrow scrolling table with text-spacing overrides @avt', async ({ + test('header actions remain reachable in a narrow scrolling table with text-spacing overrides @aat', async ({ page, }) => { await page.setViewportSize({width: 320, height: 256}) diff --git a/packages/react/src/DataTable/DataTable.accessibility.md b/packages/react/src/DataTable/DataTable.accessibility.md index 84479748352..27322c26ac8 100644 --- a/packages/react/src/DataTable/DataTable.accessibility.md +++ b/packages/react/src/DataTable/DataTable.accessibility.md @@ -280,8 +280,9 @@ unfiltered controlled selection. `clearSelection` requests an empty selection, including retained IDs; controlled consumers apply `onSelectionChange`. Actions occupy the table header beside select-all, replacing the visible column -labels while rows are selected. Column labels remain available to assistive -technology, but sorting controls are removed until selection is cleared. The +labels while rows are selected. Column names remain available to assistive +technology, but custom header controls are hidden and sorting controls are removed +until selection is cleared. The named action group uses native Tab/Shift+Tab navigation. Count changes are announced, including zero. Use `bulkActionsProps` to localize the group name and count label. The header checkbox toggles selection; @@ -290,7 +291,8 @@ there is no separate clear button. Use small action buttons to fit the header. Showing actions preserves checkbox focus. When clearing selection or updating rows removes the focused action, `DataTable` restores focus to select-all, or to the table when no selectable rows remain. `bulkActionsReturnFocusRef` overrides -that destination. Focus is not restored after the user leaves the actions or +that destination. This also applies when an action removes itself without updating +the table. Focus is not restored after the user leaves the actions or moves into a consumer-owned dialog. When composing `Table.BulkActions` directly, keep it mounted at zero and provide `onFocusReturn` for recovery. @@ -298,6 +300,7 @@ Consumers own pending states, result announcements, and focus when closing dialogs or replacing the table. For asynchronous operations, capture the effective IDs at activation and reconcile only those IDs on success; preserve selection on failure and do not clear selections added while waiting. +Collapsing a group does not exclude its selected rows from bulk actions. See `WithBulkActions` in [DataTable features](./DataTable.features.stories.tsx). ## Verification diff --git a/packages/react/src/DataTable/DataTable.docs.json b/packages/react/src/DataTable/DataTable.docs.json index 9f5e5d672bb..70a045c522b 100644 --- a/packages/react/src/DataTable/DataTable.docs.json +++ b/packages/react/src/DataTable/DataTable.docs.json @@ -159,7 +159,7 @@ }, { "name": "bulkActionsReturnFocusRef", - "type": "React.RefObject", + "type": "React.RefObject", "description": "Override focus recovery when a focused action disappears. Defaults to select-all, or the table when no selectable rows remain. Does not override focus already moved by the consumer." }, { diff --git a/packages/react/src/DataTable/DataTable.features.stories.tsx b/packages/react/src/DataTable/DataTable.features.stories.tsx index cd1140359b7..d5fc5eae81a 100644 --- a/packages/react/src/DataTable/DataTable.features.stories.tsx +++ b/packages/react/src/DataTable/DataTable.features.stories.tsx @@ -1812,6 +1812,7 @@ export const WithBulkActions = () => { selectedRows={selectedRows} onSelectionChange={({selectedRows: next}) => setSelectedRows(next)} bulkActionsReturnFocusRef={rows.length === 0 ? resetButtonRef : undefined} + collapsibleGroups renderBulkActions={({selectedRows: effectiveIds, clearSelection}) => ( <> + ), + field: 'id', + }, + ]} + rowSelection + defaultSelectedRows={new Set([1])} + renderBulkActions={renderActions} + />, + ) + for (const name of ['Name', 'Details']) { + const header = page.getByRole('columnheader', {name, exact: true}) + await expect.element(header).toBeInTheDocument() + const labelId = header.element().getAttribute('aria-labelledby') + expect(document.getElementById(labelId!)).toHaveAttribute('hidden') + } + await expect.element(page.getByRole('link', {name: 'Name', exact: true})).not.toBeInTheDocument() + await expect.element(page.getByRole('button', {name: 'Details', exact: true})).not.toBeInTheDocument() + const selectAll = page.getByRole('checkbox', {name: 'Select rows', exact: true}) + act(() => selectAll.element().focus()) + await browserUserEvent.tab() + const apply = page.getByRole('button', {name: 'Apply to 1', exact: true}) + await expect.element(apply).toHaveFocus() + await browserUserEvent.tab({shift: true}) + await expect.element(selectAll).toHaveFocus() + await browserUserEvent.click(apply) + await browserUserEvent.tab() + await expect.element(page.getByRole('link', {name: 'Name', exact: true})).toHaveFocus() + await browserUserEvent.tab() + await expect.element(page.getByRole('button', {name: 'Details', exact: true})).toHaveFocus() + }) + + it.each([false, true])('recovers focus after a child-only action removal (portal: %s)', async portal => { + function Action() { + const [visible, setVisible] = React.useState(true) + const button = visible ? : null + return portal ? createPortal(button, document.body) : button + } + render( + } + />, + ) + await browserUserEvent.click(page.getByRole('button', {name: 'Remove action', exact: true})) + await expect.element(page.getByRole('checkbox', {name: 'Select rows', exact: true})).toHaveFocus() + await expect.element(page.getByRole('group', {name: 'Bulk actions', exact: true})).toBeInTheDocument() + await expect + .element(page.getByRole('group', {name: 'Bulk actions', exact: true}).getByText('1 selected', {exact: true})) + .toBeVisible() + }) + + it('does not override a consumer destination after a child-only action removal', async () => { + const destination = React.createRef() + function Action() { + const [visible, setVisible] = React.useState(true) + return visible ? ( + + ) : null + } + render( + <> + + } + /> + , + ) + await browserUserEvent.click(page.getByRole('button', {name: 'Complete', exact: true})) + await expect.element(page.getByRole('button', {name: 'Confirmation', exact: true})).toHaveFocus() + }) + + it('acts on selected collapsed rows without changing expansion', async () => { + const onAction = vi.fn() + render( + ( + + )} + />, + ) + await expect + .element(page.getByRole('group', {name: 'Bulk actions', exact: true}).getByText('1 selected', {exact: true})) + .toBeVisible() + await expect + .element(page.getByRole('button', {name: 'Repositories', exact: true})) + .toHaveAttribute('aria-expanded', 'false') + await browserUserEvent.click(page.getByRole('button', {name: 'Apply', exact: true})) + expect(onAction).toHaveBeenCalledWith(new Set([1])) + await expect.element(page.getByRole('group', {name: 'Bulk actions', exact: true})).not.toBeInTheDocument() + await expect.element(page.getByRole('checkbox', {name: 'Select rows', exact: true})).toHaveFocus() + await expect + .element(page.getByRole('button', {name: 'Repositories', exact: true})) + .toHaveAttribute('aria-expanded', 'false') + }) + it('preserves checkbox focus when actions appear and announces counts including zero', async () => { const user = userEvent.setup() render() @@ -340,6 +478,18 @@ describe('DataTable bulk actions', () => { describe('Table.BulkActions', () => { implementsClassName(props => , classes.TableBulkActions) + it('does not recover focus when the entire component unmounts', async () => { + const onFocusReturn = vi.fn() + const {unmount} = render( + + + , + ) + await browserUserEvent.click(page.getByRole('button', {name: 'Apply', exact: true})) + await act(async () => unmount()) + expect(onFocusReturn).not.toHaveBeenCalled() + }) + it('forwards root attributes, ref and focus handlers', async () => { const user = userEvent.setup() const ref = React.createRef() From 1046033f11943e6fe001b13e6eecd0b3ef878f03 Mon Sep 17 00:00:00 2001 From: Ricky Zhang Date: Thu, 29 Oct 2026 16:45:08 -0400 Subject: [PATCH 14/16] fix(Table): preserve bottom corners for empty groups Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .changeset/table-empty-group-corners.md | 5 +++ packages/react/src/DataTable/Table.module.css | 2 +- .../__tests__/DataTableExpansion.test.tsx | 39 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 .changeset/table-empty-group-corners.md diff --git a/.changeset/table-empty-group-corners.md b/.changeset/table-empty-group-corners.md new file mode 100644 index 00000000000..9f50d1f49c5 --- /dev/null +++ b/.changeset/table-empty-group-corners.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +Table: Preserve bottom corners when the final row group is empty. diff --git a/packages/react/src/DataTable/Table.module.css b/packages/react/src/DataTable/Table.module.css index c03d844fa3e..8bdbcc2150a 100644 --- a/packages/react/src/DataTable/Table.module.css +++ b/packages/react/src/DataTable/Table.module.css @@ -166,7 +166,7 @@ /* stylelint-disable selector-pseudo-class-disallowed-list, selector-max-compound-selectors -- scoped to a group header and its adjacent member body */ .TableOverflowWrapper:last-child - .TableGroupHeaderBody:where(:has(+ .TableBody[hidden]:last-child)) + .TableGroupHeaderBody:where(:has(+ .TableBody:where([hidden], :empty):last-child)) .TableGroupHeaderCell { /* stylelint-disable-next-line primer/borders */ border-bottom-left-radius: var(--table-border-radius); diff --git a/packages/react/src/DataTable/__tests__/DataTableExpansion.test.tsx b/packages/react/src/DataTable/__tests__/DataTableExpansion.test.tsx index a43235b9e3c..6cd8bf7aa09 100644 --- a/packages/react/src/DataTable/__tests__/DataTableExpansion.test.tsx +++ b/packages/react/src/DataTable/__tests__/DataTableExpansion.test.tsx @@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event' import {hydrateRoot} from 'react-dom/client' import {renderToString} from 'react-dom/server' import {describe, expect, it, vi} from 'vitest' +import {page} from 'vitest/browser' import {DataTable, Table} from '../../DataTable' import {implementsClassName} from '../../utils/testing' import classes from '../Table.module.css' @@ -298,6 +299,44 @@ describe('DataTable group expansion', () => { }) describe('Table.Group expansion', () => { + describe.each([false, true])('empty group corners (pagination: %s)', pagination => { + it.each([false, true])('rounds only the final visible boundary (collapsible: %s)', collapsible => { + function Example({empty}: {empty: boolean}) { + return ( + + + + + {empty ? null : ( + + Member + + )} + +
+ {pagination ? : null} +
+ ) + } + const {rerender} = render() + const header = page.getByRole('columnheader', {name: /^Last/}).element() + expect(getComputedStyle(header).borderBottomLeftRadius).toBe('0px') + expect(getComputedStyle(header).borderBottomRightRadius).toBe('0px') + + rerender() + const radius = pagination ? '0px' : '6px' + expect(getComputedStyle(header).borderBottomLeftRadius).toBe(radius) + expect(getComputedStyle(header).borderBottomRightRadius).toBe(radius) + const first = page.getByRole('columnheader', {name: /^First/}).element() + expect(getComputedStyle(first).borderBottomLeftRadius).toBe('0px') + expect(getComputedStyle(first).borderBottomRightRadius).toBe('0px') + + rerender() + expect(getComputedStyle(header).borderBottomLeftRadius).toBe('0px') + expect(getComputedStyle(header).borderBottomRightRadius).toBe('0px') + }) + }) + it('keeps collapsed group corners square when pagination follows the table', () => { render( From 0a8a7ac1c5c71b983370a155f96d64e07f53146f Mon Sep 17 00:00:00 2001 From: Ricky Zhang Date: Thu, 29 Oct 2026 17:29:48 -0400 Subject: [PATCH 15/16] fix(DataTable): keep focused bulk actions fully visible Add scroll margin to accommodate fractional scroll-offset rounding without weakening the strict viewport assertion. Refresh the collapsible bulk-action story's Linux baselines from inspected CI screenshots. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ...DataTable-BulkActions-Mixed-dark-linux.png | Bin 18784 -> 18919 bytes ...ataTable-BulkActions-Mixed-light-linux.png | Bin 18830 -> 18972 bytes .../src/DataTable/TableBulkActions.module.css | 5 +++++ 3 files changed, 5 insertions(+) diff --git a/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-dark-linux.png b/.playwright/snapshots/components/DataTableBulkActions.test.ts-snapshots/DataTable-BulkActions-Mixed-dark-linux.png index 24cce1f7f8cea5c927e7ace59ecca27e28e7e1cf..1a0e74dbd9c26f641fcd482a2f4cc0e6ab20c89c 100644 GIT binary patch literal 18919 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�Wu85pH46se%I=ktrvR0A;5;VR5!u^ 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 Wq4r2?j{$fFa^srOpQTssJ^deR7DZM7 literal 18830 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 HTMz#i)!V>a diff --git a/packages/react/src/DataTable/TableBulkActions.module.css b/packages/react/src/DataTable/TableBulkActions.module.css index f2027ed2431..19e46079d78 100644 --- a/packages/react/src/DataTable/TableBulkActions.module.css +++ b/packages/react/src/DataTable/TableBulkActions.module.css @@ -23,6 +23,11 @@ align-items: center; gap: var(--base-size-8); margin-inline-start: auto; + + :focus { + /* Keep the focus ring inside the scroller despite scroll-offset rounding. */ + scroll-margin: var(--base-size-4); + } } .HeaderRow, From 842af5818eee95c940245527e4d7e04d08f6381f Mon Sep 17 00:00:00 2001 From: Ricky Zhang Date: Thu, 29 Oct 2026 17:47:57 -0400 Subject: [PATCH 16/16] refactor(DataTable): trim bulk action comments and test duplication Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- e2e/components/DataTableBulkActions.test.ts | 2 - packages/react/src/DataTable/DataTable.tsx | 18 +------ .../src/DataTable/TableBulkActions.module.css | 3 -- .../react/src/DataTable/TableBulkActions.tsx | 14 ------ .../__tests__/DataTableBulkActions.test.tsx | 49 ++++--------------- 5 files changed, 10 insertions(+), 76 deletions(-) diff --git a/e2e/components/DataTableBulkActions.test.ts b/e2e/components/DataTableBulkActions.test.ts index dbb875355fb..4b0e2d59d47 100644 --- a/e2e/components/DataTableBulkActions.test.ts +++ b/e2e/components/DataTableBulkActions.test.ts @@ -92,9 +92,7 @@ test.describe('DataTable bulk actions', () => { expect(selected!.height).toBe(before!.height) expect((await count.boundingBox())!.x).toBe(labelBefore!.x) const actions = table.getByRole('group', {name: 'Bulk actions'}) - await expect(actions.getByRole('button')).toHaveCount(2) const lastAction = await actions.getByRole('button', {name: 'Delete selected'}).boundingBox() - // 8px padding plus the 1px header border. expect(selected!.x + selected!.width - lastAction!.x - lastAction!.width).toBe(9) expect( await count.evaluate(element => { diff --git a/packages/react/src/DataTable/DataTable.tsx b/packages/react/src/DataTable/DataTable.tsx index aabc6671c88..ee38a9a40a6 100644 --- a/packages/react/src/DataTable/DataTable.tsx +++ b/packages/react/src/DataTable/DataTable.tsx @@ -135,21 +135,8 @@ type DataTableBaseProps = { */ onExpandedGroupsChange?: ({expandedGroups}: {expandedGroups: Set}) => void - /** - * Renders actions for effectively selected rows, excluding missing and - * non-selectable IDs. Requires rowSelection. Consumers own business operations. - */ renderBulkActions?: (context: DataTableBulkActionsContext) => ReactNode - - /** - * Localizes bulk-action labels and the selected-count announcement. - */ bulkActionsProps?: Pick - - /** - * Overrides the focus recovery target when a focused bulk action disappears. - * Defaults to select-all, or the table when no selectable rows remain. - */ bulkActionsReturnFocusRef?: RefObject } @@ -257,7 +244,7 @@ function DataTableImplementation({ return ( ({ {typeof header.column.header === 'string' ? ( {header.column.header} ) : ( - // Hidden content names the header without exposing its controls. @@ -338,8 +324,6 @@ function DataTableImplementation({ })} {hasBulkActions ? ( - // Share the visual header row without putting action names in column - // headers or removing their associations with the table body. .BulkActionsCell:first-child:last-child { /* stylelint-disable-next-line primer/spacing */ padding-inline-start: var(--cell-padding-inline, var(--base-size-12)); diff --git a/packages/react/src/DataTable/TableBulkActions.tsx b/packages/react/src/DataTable/TableBulkActions.tsx index e1180ca36a3..476efba6bb4 100644 --- a/packages/react/src/DataTable/TableBulkActions.tsx +++ b/packages/react/src/DataTable/TableBulkActions.tsx @@ -6,19 +6,8 @@ import useLayoutEffect from '../utils/useIsomorphicLayoutEffect' import classes from './TableBulkActions.module.css' export type TableBulkActionsProps = Omit, 'role'> & { - /** - * The number of effectively selected rows. Keep this component mounted at zero - * so the count announcement and focus recovery can complete. - */ selectedCount: number - /** - * Restores focus when a focused action disappears. Not called if focus has - * already moved elsewhere, for example into a consumer-owned dialog. - */ onFocusReturn?: () => void - /** - * Localizes the visible and announced selection count, including zero. - */ getSelectedCountLabel?: (selectedCount: number) => string } @@ -60,7 +49,6 @@ const TableBulkActions = React.forwardRef focusObserver.current?.disconnect() const element = focusedAction.current if (element) { - // Observe only while an action owns focus, including actions in portals. const observer = new MutationObserver(recoverFocus) observer.observe(element.ownerDocument.body, {childList: true, subtree: true}) focusObserver.current = observer @@ -87,7 +75,6 @@ const TableBulkActions = React.forwardRef onFocusCapture={event => { focusedAction.current = event.target observeFocusedAction() - // Native focus scrolling can miss controls in the grid-overlaid header. if (event.currentTarget.contains(event.target)) { event.target.scrollIntoView({block: 'nearest', inline: 'nearest'}) } @@ -96,7 +83,6 @@ const TableBulkActions = React.forwardRef } }} onBlurCapture={event => { - // Clicking non-focusable content blurs with a null relatedTarget. if (event.target.isConnected) { focusedAction.current = null focusObserver.current?.disconnect() diff --git a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx index 88099aeda03..d098f0ec480 100644 --- a/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx +++ b/packages/react/src/DataTable/__tests__/DataTableBulkActions.test.tsx @@ -107,14 +107,11 @@ describe('DataTable bulk actions', () => { }) it('names custom headers without leaving hidden controls in the tab order', async () => { - function CustomHeader() { - return Name - } render( , field: 'name', rowHeader: true}, + {header: () => Name, field: 'name', rowHeader: true}, { header: () => ( - ( - - )} - /> - - ) - } - render() - await user.click(screen.getByRole('button', {name: 'Complete'})) - expect(screen.getByRole('button', {name: 'Confirmation'})).toHaveFocus() - }) - it('does not recover focus after the user leaves the actions for non-interactive content', async () => { const user = userEvent.setup() const renderExample = (data: Array) => (