Skip to content

feat: add row grouping to database table view #1252

Description

@sw-factory-automations

Description

The board view supports grouping rows by a select property via config.group_by, but the table view does not. Table row grouping is one of the most-requested database features in Notion-style tools — it lets users organize rows into collapsible sections based on a property value (e.g., group tasks by Status or Priority). The DatabaseViewConfig.group_by field and the ViewConfigDropdown component already exist, so the infrastructure is partially in place.

Approval Required

This is a HIGH risk change because:

  • Adds collapsible group headers to the table view that interact with virtualization (@tanstack/react-virtual), column resize, column reorder, and bulk selection
  • Group headers must span the full table width and render a collapse/expand toggle + group value + row count
  • Collapsed groups must be excluded from the virtualized item list, affecting scroll position calculations
  • Bulk selection ("select all") must respect group boundaries (select all in group vs. select all globally)
  • Sort order within groups must be maintained independently
  • Filter changes may create/remove groups dynamically

Comment "approved" to release this to the automation queue.

Acceptance Criteria

  • A "Group by" dropdown appears in the table view toolbar (reusing ViewConfigDropdown from database-view-helpers.tsx)
  • Grouping is available for select, multi-select, status, person, and checkbox property types
  • When a group-by property is selected, rows are organized under collapsible group headers
  • Each group header shows: expand/collapse chevron, property value (with color for select/status), row count
  • Groups are collapsible — clicking the header or pressing Enter/Space toggles the group
  • Collapsed group state is stored in component state (not persisted — resets on page reload)
  • Rows without a value for the group-by property appear in an "No value" group at the bottom
  • The "Group by" selection is persisted in config.group_by (same field used by board view)
  • Removing the group-by property returns to the flat table layout
  • Group headers span the full table width and align with the column grid
  • Bulk selection checkboxes in group headers select/deselect all rows in that group
  • Sorting within groups is maintained (rows within each group follow the active sort order)
  • Storybook stories cover: ungrouped (default), grouped by select, grouped with collapsed groups, grouped with empty group
  • E2E test: add select column → set values → enable "Group by" → verify groups appear → collapse a group → verify rows hidden → expand → verify rows visible → remove grouping → verify flat layout
  • pnpm lint && pnpm typecheck && pnpm test pass

Dependencies

None

Technical Notes

  • Add the ViewConfigDropdown for group_by to the table toolbar in database-view-client.tsx (same pattern as board view, line ~403)
  • Filter eligible properties to types that support grouping: select, multi_select, status, person, checkbox
  • Create a groupRows(rows, propertyId, properties) utility in src/lib/database-group.ts that returns { value: string | null, rows: DatabaseRow[] }[]
  • In table-view.tsx, when config.group_by is set, replace the flat row list with a grouped structure. Each group header is a non-data row in the virtualized list
  • Use @tanstack/react-virtual estimateSize to account for group header rows (which have a different height than data rows)
  • Track collapsed groups in a Set<string> state variable. Collapsed groups contribute only their header row to the virtualized list
  • The board view's groupRowsByProperty in board-view-helpers.ts can be referenced but table grouping needs a different output format (flat list with interleaved headers vs. column-based groups)
  • Reference .agents/conventions.md for component patterns and .agents/design.md for visual styling

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestneeds-humanNeeds human input — automation will re-queue when user respondspriority:3

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions