feat(desktop): copy a file's path from its header, fold it from anywhere on its row, and fold every file with ⌥

Merged
DA
2d ago
+190-42

Summary

Part of the stage-cli features the developer chose for Files changed: header actions, modelled on stage-cli's components/chapter/file-header.tsx. Stacked on #3794 (the design pass).

  • Copy the path. Pressing the path in a file's header copies the full path, shows the "Path copied" toast, and the hint reads "Copy path".
    • A renamed file shows two buttons: Copy old path and Copy new path.
    • Each is a real @luke/ui TextButton with an accessible name such as "Copy path: src/seats.ts".
  • Fold from the row. A press anywhere else on the header row folds or unfolds the file. The fold arrow, the path buttons, Viewed and the other controls keep their own presses. The fold arrow stays the row's keyboard control, and ; still folds the file stood on.
  • ⌥-click the fold arrow folds every file the filter keeps, or unfolds them all, the same as ⇧;. The hint reads "Collapse file · ⌥-click for all files ;".
  • toggleAll now reads the latest folds through a ref, as toggle does. That keeps it a stable prop, so passing it to every header doesn't redraw every file.
  • The header hints still mount lazily (#3733). Their arrival handling now covers the path buttons too: a pointer resting on a path, or keyboard focus on it, still gets its hint, and focus is restored.

Screenshots

Harness: the real Pull request tab on PR #2908, Chromium.

lightdark
path hint
fold hint, with ⌥

Evidence

  • tsc --noEmit for panel and desktop: clean.
  • ./scripts/oxlint.sh: 0 errors.
  • pnpm knip: clean.
  • ./scripts/repository-checks.sh: passed.
  • biome check: no errors.
  • vitest run --project panel --project desktop: 231 files, 2366 tests passed.
  • New tests in agent-changes-tab.test.ts:
    • The header copies src/seats.ts, src/old/plan.ts and src/plan.ts from the three buttons, and a copy folds nothing.
    • A press on a header's row folds that file alone.
    • ⌥ with a press on the fold folds every file, and a second one unfolds them all.

Invariants

  • Checks green locally, as listed above.
  • JSON Schema goldens unchanged.
  • Behaviour tested.
  • No new as.
  • No raw async primitives.
  • Test count +2.
  • Deps unchanged.

Made with Luke