PUI-28 feat(table): two-level tree and click-to-place moves in DataTable and Index #107

Merged
pienter merged 3 commits from feature/PUI-28-implement-manual-order-and-nesting-in-index into main 2026-09-21 13:53:00 +00:00
Owner

Implements the Ordered, nested Index Goal per ADR 0011 (#106). Releases a minor version: afa93b0 is a feat touching packages/ui, with its entry under ## Unreleased in packages/ui/CHANGELOG.md.

Library (afa93b0)

  • DataTable: parentKey turns rows into a two-level tree; typed columns level (hierarchy, other columns stay aligned) and move (click-to-place). Placing state with labelled destination buttons, a ghost preview of the row on hover or focus, Escape/Cancel, focus return, live-region announcements. Emits move as an intent and never reorders rows.
  • Index / useIndexQuery: loadTree serves the index at rest, pagination hides there, flat list otherwise. move async prop with optimistic apply, rollback and error Alert, reload on success. canMove, canParent, rowLabel, moveLabels.
  • utils/tree: treeItems, moveTo, applyMove, default labels. Table gains an after slot.
  • Tests: tests/tree.test.ts (8) and a loadTree lifecycle test. Audits updated.

Playground and Storybook (cb08c99)

  • Pages have parent_id; the Pages index is the menu editor; fixture API has a tree and a move operation (Contact refuses children, stale order detected). Removes the PUI-26 prototype. DataTable Tree story.

Verified: lint, format check, package typecheck, example type-check, 171 tests, build:vue; in Chrome on the playground: tree at rest, placing, ghost preview, a saved move surviving reload, a rejected move rolling back with the Alert, keyboard focus return, search falling back to the flat paginated list, light and dark theme. Not verified: the Storybook story in a browser, a real screen reader, touch.

Refs: PUI-28

Implements the Ordered, nested Index Goal per ADR 0011 (#106). Releases a **minor** version: `afa93b0` is a `feat` touching `packages/ui`, with its entry under `## Unreleased` in `packages/ui/CHANGELOG.md`. **Library (`afa93b0`)** - `DataTable`: `parentKey` turns rows into a two-level tree; typed columns `level` (hierarchy, other columns stay aligned) and `move` (click-to-place). Placing state with labelled destination buttons, a ghost preview of the row on hover or focus, Escape/Cancel, focus return, live-region announcements. Emits `move` as an intent and never reorders `rows`. - `Index` / `useIndexQuery`: `loadTree` serves the index at rest, pagination hides there, flat list otherwise. `move` async prop with optimistic apply, rollback and error Alert, reload on success. `canMove`, `canParent`, `rowLabel`, `moveLabels`. - `utils/tree`: `treeItems`, `moveTo`, `applyMove`, default labels. `Table` gains an `after` slot. - Tests: `tests/tree.test.ts` (8) and a `loadTree` lifecycle test. Audits updated. **Playground and Storybook (`cb08c99`)** - Pages have `parent_id`; the Pages index is the menu editor; fixture API has a tree and a move operation (Contact refuses children, stale order detected). Removes the PUI-26 prototype. `DataTable` Tree story. **Verified**: lint, format check, package typecheck, example type-check, 171 tests, `build:vue`; in Chrome on the playground: tree at rest, placing, ghost preview, a saved move surviving reload, a rejected move rolling back with the Alert, keyboard focus return, search falling back to the flat paginated list, light and dark theme. **Not verified**: the Storybook story in a browser, a real screen reader, touch. Refs: PUI-28
DataTable renders rows that carry a parent as a two-level tree through
two typed columns the project adds: `level` draws the hierarchy so every
other column stays aligned, `move` opens a placing state in which every
legal destination is a labelled button and a hovered or focused one
previews the row in place. No drag and drop. The move is reported as an
intent; `applyMove` in utils/tree is the optional default.

Index loads the full tree through `loadTree` while no search, filter or
sort is active, hides pagination there, and owns the move lifecycle:
optimistic apply, rollback with the error shown and announced, reload on
success.

ADR 0011.

Refs: PUI-28
feat(examples): make the Pages index the menu editor
All checks were successful
ci / typecheck (pull_request) Successful in 34s
ci / lint (pull_request) Successful in 36s
ci / format (pull_request) Successful in 39s
ci / release (pull_request) Has been skipped
cb08c99410
Pages carry a parent and a manual order, the index loads the tree at
rest and moves pages through the package's level and move columns, and
the fixture API gains a tree and a move operation that refuses children
under Contact and answers a stale sibling list. Removes the PUI-26
prototype and adds a DataTable Tree story.

Refs: PUI-28
chore(tracker): track work in Windshift
All checks were successful
ci / typecheck (pull_request) Successful in 32s
ci / lint (pull_request) Successful in 35s
ci / format (pull_request) Successful in 37s
ci / release (pull_request) Has been skipped
3b25e1c991
Replaces the Obsidian tracker mapping with the Windshift workspace: the
agent doc describes the PUI workspace, Goals as milestones with a Goal
page, statuses, routing and blocker links; `ws.toml` holds the workspace
key and the generated, token-specific WINDSHIFT.md is ignored.

Refs: PUI-28
pienter deleted branch feature/PUI-28-implement-manual-order-and-nesting-in-index 2026-09-21 13:53:00 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
pienter/ui!107
No description provided.