Skip to content

feat: Extract RowActionMenu + add BulkActionBar to ObjectGrid#784

Merged
hotlong merged 4 commits intomainfrom
copilot/add-row-actions-and-bulk-actions
Feb 23, 2026
Merged

feat: Extract RowActionMenu + add BulkActionBar to ObjectGrid#784
hotlong merged 4 commits intomainfrom
copilot/add-row-actions-and-bulk-actions

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 23, 2026

RowActions and BulkActions specs (rowActions: string[], batchActions: string[]) existed in types but had no standalone components. The row action dropdown was inline in ObjectGrid; bulk action bar only existed in ListView with no grid-level support.

New components

  • RowActionMenu — Extracted from ObjectGrid inline code. Configurable via rowActions, canEdit/canDelete, and action callbacks.
  • BulkActionBar — Shows "N selected" + action buttons + Clear. Auto-hides when empty. Renders below grid content.

ObjectGrid integration

  • Replaced inline DropdownMenu with <RowActionMenu> component
  • Added selectedRows state tracking via onSelectionChange passthrough
  • Renders <BulkActionBar> in both normal and split-pane paths
  • Supports both batchActions (ObjectUI naming) and bulkActions (spec naming)

ListView integration

  • Passes schema.bulkActionsbatchActions when generating grid view schema
  • Passes onRowSelect={setSelectedRows} to SchemaRenderer so grid selection changes sync to ListView's state
  • Skips ListView's own bulk action bar when currentView === 'grid' to avoid duplicate bars (grid renders its own BulkActionBar)

Usage

// Grid with row actions + bulk actions
<ObjectGrid schema={{
  type: 'object-grid',
  objectName: 'contacts',
  columns: ['name', 'email', 'status'],
  rowActions: ['archive', 'send_email'],
  batchActions: ['delete', 'export'],
  selection: { type: 'multiple' },
}} />

Tests

26 new tests covering formatActionLabel, RowActionMenu (standalone + integrated), BulkActionBar (standalone + integrated), onRowSelect callback propagation with checkbox interaction, and bulkActions alias support. All existing grid tests pass unchanged.

Original prompt

This section details on the original issue you should resolve

<issue_title>[P2] RowActions 行菜单 + BulkActions 批量操作栏</issue_title>
<issue_description>## 背景
Parent Issue: #736

Spec rowActions: string[]bulkActions: string[] 已定义,ObjectUI 类型已存在但无 UI 渲染。

目标

  1. RowActions:每行末尾渲染 "..." 操作下拉菜单,菜单项由 rowActions 配置
  2. BulkActions:多选行后在 toolbar 下方显示批量操作栏,操作项由 bulkActions 配置

技术要点

  • packages/plugin-grid/src/ObjectGrid.tsx — 添加 action 列 + 批量操作栏
  • packages/plugin-list/src/ListView.tsx L335 — 已有 selectedRows state

改动范围

  • packages/plugin-grid/src/components/RowActionMenu.tsx — 新增行菜单组件
  • packages/plugin-grid/src/components/BulkActionBar.tsx — 新增批量操作栏
  • packages/plugin-grid/src/ObjectGrid.tsx — 集成行菜单和批量栏
  • packages/plugin-list/src/ListView.tsx — 传递 rowActions/bulkActions 到子视图

验收标准

  • Grid 每行末尾显示 "..." 按钮
  • 点击展开下拉菜单,包含 rowActions 配置的操作项
  • 多选后 toolbar 下方出现 "N selected" + 批量操作按钮
  • 批量操作按钮触发对应 action
  • 所有新增代码有对应单元测试
  • pnpm test 全部通过
    </issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
objectui Ready Ready Preview, Comment Feb 23, 2026 11:24am
objectui-demo Error Error Feb 23, 2026 11:24am
objectui-storybook Error Error Feb 23, 2026 11:24am

Request Review

- Extract row action dropdown into RowActionMenu component
- Create BulkActionBar component for bulk operations
- Integrate both components into ObjectGrid
- Pass bulkActions from ListView to ObjectGrid as batchActions
- Add 23 unit tests covering all new functionality

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI changed the title [WIP] Add RowActions and BulkActions components for UI rendering feat: Extract RowActionMenu + add BulkActionBar to ObjectGrid Feb 23, 2026
Copilot AI requested a review from hotlong February 23, 2026 10:52
@hotlong
Copy link
Copy Markdown
Collaborator

hotlong commented Feb 23, 2026

@copilot 仔细评估需要实现任务中的所有功能

…add tests

- ListView passes onRowSelect to SchemaRenderer so grid selection updates parent
- Skip ListView's own bulk action bar in grid view (grid has its own)
- Add tests for bulkActions alias and onRowSelect callback
- All 25 tests pass; 490 total pass (6 pre-existing failures unchanged)

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…s callback

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 23, 2026

@copilot 仔细评估需要实现任务中的所有功能

Completed thorough evaluation. Here's the full feature checklist:

RowActions

  • Grid renders "..." MoreVertical button at end of each row (via RowActionMenu component)
  • Click opens dropdown with rowActions items, plus Edit/Delete when CRUD operations configured
  • Each action triggers executeAction({ type, params: { record } })

BulkActions

  • BulkActionBar renders "N selected" + action buttons + Clear when rows selected
  • Integrated in both normal and split-pane grid rendering
  • Supports both batchActions (ObjectUI) and bulkActions (spec) field names
  • Bulk action buttons trigger executeAction({ type, params: { records } })

ListView → Grid sync ✅ (fixed in 049b1bb)

  • ListView passes onRowSelect={setSelectedRows} to SchemaRenderer so grid selection updates parent state
  • Skips duplicate bulk action bar when grid view is active (currentView !== 'grid')
  • Passes both rowActions and bulkActionsbatchActions to grid view

Tests ✅ (26 tests, all passing in 30f4f2d)

  • formatActionLabel utility (3 tests)
  • RowActionMenu standalone + integrated (11 tests)
  • BulkActionBar standalone + integrated (9 tests)
  • onRowSelect callback verifies checkbox triggers callback (3 tests)

All 490 tests pass (6 pre-existing failures unrelated to this PR).

@hotlong hotlong marked this pull request as ready for review February 23, 2026 11:24
Copilot AI review requested due to automatic review settings February 23, 2026 11:24
@hotlong hotlong merged commit 78bbfd0 into main Feb 23, 2026
3 of 5 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extracts reusable row/bulk action UI from ObjectGrid into standalone components and integrates a grid-level bulk action bar, while updating ListView to pass bulk-action config/selection state appropriately for grid view.

Changes:

  • Extracts RowActionMenu (and formatActionLabel) and introduces BulkActionBar under packages/plugin-grid/src/components/.
  • Integrates RowActionMenu + BulkActionBar into ObjectGrid, adding selectedRows tracking via onSelectionChange.
  • Updates ListView to map bulkActions → batchActions for grid view schema and avoid rendering a duplicate bulk bar when currentView === 'grid'.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/plugin-list/src/ListView.tsx Maps bulkActions into grid schema as batchActions, passes onRowSelect, and suppresses ListView bulk bar in grid view.
packages/plugin-grid/src/index.tsx Exports new RowActionMenu/BulkActionBar components and their prop types.
packages/plugin-grid/src/components/RowActionMenu.tsx New extracted dropdown menu for per-row actions + shared formatActionLabel.
packages/plugin-grid/src/components/BulkActionBar.tsx New bulk action bar component rendered when rows are selected.
packages/plugin-grid/src/tests/row-bulk-actions.test.tsx Adds unit + integration tests for label formatting, row menu, bulk bar, selection callback propagation, and alias support.
packages/plugin-grid/src/ObjectGrid.tsx Replaces inline dropdown with RowActionMenu, tracks selection locally, and renders BulkActionBar (including bulkActions alias support).

import { useGroupedData } from './useGroupedData';
import { GroupRow } from './GroupRow';
import { useColumnSummary } from './useColumnSummary';
import { RowActionMenu, formatActionLabel } from './components/RowActionMenu';
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatActionLabel is imported from ./components/RowActionMenu but not used in this file anymore. This will typically fail lint/typecheck with an unused import. Remove the unused import (or use it if intended).

Suggested change
import { RowActionMenu, formatActionLabel } from './components/RowActionMenu';
import { RowActionMenu } from './components/RowActionMenu';

Copilot uses AI. Check for mistakes.
Comment on lines +1265 to +1270
<BulkActionBar
selectedRows={selectedRows}
actions={effectiveBulkActions ?? []}
onAction={(action, rows) => executeAction({ type: action, params: { records: rows } })}
onClearSelection={() => setSelectedRows([])}
/>
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onClearSelection={() => setSelectedRows([])} only clears ObjectGrid's local selectedRows state, but it does not clear the underlying DataTable's internal selection state (checkboxes will remain checked). Consider wiring a real selection reset (e.g., add a clear-selection signal/controlled selection to the DataTable schema, or force a remount/reset of the DataTable selection state) and also notify onRowSelect with an empty array when cleared.

Copilot uses AI. Check for mistakes.
Comment on lines +1291 to +1296
<BulkActionBar
selectedRows={selectedRows}
actions={effectiveBulkActions ?? []}
onAction={(action, rows) => executeAction({ type: action, params: { records: rows } })}
onClearSelection={() => setSelectedRows([])}
/>
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as the split-pane path: onClearSelection={() => setSelectedRows([])} hides the BulkActionBar but does not clear the DataTable's actual row selection state. Clearing should reset the table selection itself (and ideally propagate onRowSelect([])), otherwise the UI ends up with checked rows but no bulk bar.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P2] RowActions 行菜单 + BulkActions 批量操作栏

3 participants