feat(web): unified two-row TYPO3-style docheader across page/edit/media/view modules #76

Merged
dominik.polakovics merged 1 commit from afk/74 into main 2026-07-17 17:18:36 +02:00

Replaces the four bespoke module headers — .page-docheader, .edit-pane__header, .media-toolbar, .preview-pane__head — with one shared two-row, TYPO3-style Docheader component (web/src/components/Docheader.tsx), migrating all four modules onto it end-to-end per the decision record in the issue.

What's in here

  • Shared component: Docheader shell (buttons-left / reserved buttons-right / context-left / context-right slots; row 2 collapses when empty) plus DocheaderButton (icon + text, single green primary per bar), DocheaderToggle (joined-border segmented control, aria-pressed), and crumb primitives. One .docheader CSS family consuming the #72 design tokens; all four legacy header CSS families deleted.
  • Page: row 1 Publish (green) / Properties / Undo / Discard… / View; props mode swaps the left group to Close / Save (green) with the Saved note moving to row 2 right, no disabled leftovers. Row 2 shows the file path as crumbs — directory segments resolving to real ancestor pages are clickable and navigate like the tree (synthesized sections stay static) — with title + git-state badge right.
  • Edit: Close / Save (green) / Save & Close; element icon + label + Saved note in row 2 right; the docheader is now pinned above the scrolling form body.
  • Media: New folder / Upload (green); the folder crumbs moved into row 2 keeping their exact navigation; hidden upload input unchanged.
  • View: Desktop/Mobile segmented toggle in the left button group; row 2 fully collapsed.
  • All existing data-testids survive verbatim; the reserved right button group renders (empty) in every module.

Verification

  • tsc --noEmit clean; web suite 36 files / 736 tests green (baseline 726 + 10 new: docheader primitives unit tests and page-crumb navigation tests); vite build OK; go test ./... all green.
  • Real-browser click-through (headless Chromium against harness serve on a git-initialized copy of testdata/site): page normal + props mode incl. Saved note, crumb navigation to an ancestor section, full publish flow (badge flip, Publish/Discard removal, real commit), edit save/close flows, media new-folder dialog + upload, viewport toggle with mobile class — all pass, no console errors.

scaffold/site/AGENTS.md is unaffected (admin-UI-only change).

Closes #74

🤖 Generated with Claude Code

Replaces the four bespoke module headers — `.page-docheader`, `.edit-pane__header`, `.media-toolbar`, `.preview-pane__head` — with one shared two-row, TYPO3-style `Docheader` component (`web/src/components/Docheader.tsx`), migrating all four modules onto it end-to-end per the decision record in the issue. ## What's in here - **Shared component**: `Docheader` shell (buttons-left / reserved buttons-right / context-left / context-right slots; row 2 collapses when empty) plus `DocheaderButton` (icon + text, single green primary per bar), `DocheaderToggle` (joined-border segmented control, `aria-pressed`), and crumb primitives. One `.docheader` CSS family consuming the #72 design tokens; all four legacy header CSS families deleted. - **Page**: row 1 `Publish (green) / Properties / Undo / Discard… / View`; props mode swaps the left group to `Close / Save (green)` with the Saved note moving to row 2 right, no disabled leftovers. Row 2 shows the file path as crumbs — directory segments resolving to real ancestor pages are clickable and navigate like the tree (synthesized sections stay static) — with title + git-state badge right. - **Edit**: `Close / Save (green) / Save & Close`; element icon + label + Saved note in row 2 right; the docheader is now pinned above the scrolling form body. - **Media**: `New folder / Upload (green)`; the folder crumbs moved into row 2 keeping their exact navigation; hidden upload input unchanged. - **View**: Desktop/Mobile segmented toggle in the left button group; row 2 fully collapsed. - All existing `data-testid`s survive verbatim; the reserved right button group renders (empty) in every module. ## Verification - `tsc --noEmit` clean; web suite **36 files / 736 tests** green (baseline 726 + 10 new: docheader primitives unit tests and page-crumb navigation tests); `vite build` OK; `go test ./...` all green. - Real-browser click-through (headless Chromium against `harness serve` on a git-initialized copy of `testdata/site`): page normal + props mode incl. Saved note, crumb navigation to an ancestor section, full publish flow (badge flip, Publish/Discard removal, real commit), edit save/close flows, media new-folder dialog + upload, viewport toggle with mobile class — all pass, no console errors. `scaffold/site/AGENTS.md` is unaffected (admin-UI-only change). Closes #74 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(web): unified two-row TYPO3-style docheader across all four modules
All checks were successful
ci / build-and-test (pull_request) Successful in 5m9s
3b4cf41ef0
Replace the four bespoke module headers (.page-docheader, .edit-pane__header,
.media-toolbar, .preview-pane__head) with one shared two-row Docheader
component: row 1 holds the document's action buttons (left group, icon+text,
exactly one green primary per bar) plus a reserved empty right group for
future system tools; row 2 holds location crumbs (left) and identity/state
(right), collapsing entirely when a module has nothing to show.

- Page: Publish / Properties / Undo / Discard / View; props mode swaps the
  left group to Close / Save with the Saved note moving to row 2. The file
  path becomes breadcrumbs whose directory segments navigate to real
  ancestor pages via the tree.
- Edit: Close moves from last to first, Save is the green primary; element
  icon + label + Saved note sit in row 2 right.
- Media: New folder / Upload (primary); folder crumbs keep their navigation
  in row 2 left.
- View: Desktop/Mobile segmented toggle in the left group, no row 2.

All existing data-testids survive; the legacy header CSS families are gone.

Closes #74

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author
Owner

This was generated by AI while landing a PR.

Land-PR audit — verdict: PASS

  • CI (vouching signal): ci / build-and-test (pull_request)success (5m9s). Not re-run.
  • Mergeable: main is already an ancestor of afk/74 — merges cleanly, no conflict.
  • Conventions: title is Conventional Commits (feat(web): …); AFK contract satisfied — body carries a working Closes #74.
  • Diff vs issue #74 intent:
    • Shared Docheader shell + DocheaderButton / DocheaderToggle / crumb primitives; row 2 collapses when empty; reserved (empty) right button group present in every module.
    • Page: normal-mode order Publish(green) / Properties / Undo / Discard… / View; props-mode swaps left to Close / Save(green) with the Saved note relocated to row 2 right. Row-2 crumbs navigate only to real ancestor pages (ancestorChain/nodeDir); synthesized sections stay static.
    • Edit: Close / Save(green) / Save & Close; icon+label+Saved in row 2 right. Media: New folder / Upload(green); folder crumbs preserved. View: Desktop/Mobile segmented toggle, row 2 collapsed.
    • All four legacy header class families (.page-docheader, .edit-pane__header, .media-toolbar, .preview-pane__head) removed from styles.css and JSX; existing data-testids preserved verbatim.
  • Nit (non-blocking): Docheader.tsxs top comment still reads no module has been migrated onto it yet — stale after this PR migrates all four
> *This was generated by AI while landing a PR.* **Land-PR audit — verdict: PASS** - **CI (vouching signal):** `ci / build-and-test (pull_request)` — **success** (5m9s). Not re-run. - **Mergeable:** `main` is already an ancestor of `afk/74` — merges cleanly, no conflict. - **Conventions:** title is Conventional Commits (`feat(web): …`); AFK contract satisfied — body carries a working `Closes #74`. - **Diff vs issue #74 intent:** - Shared `Docheader` shell + `DocheaderButton` / `DocheaderToggle` / crumb primitives; row 2 collapses when empty; reserved (empty) right button group present in every module. - Page: normal-mode order `Publish(green) / Properties / Undo / Discard… / View`; props-mode swaps left to `Close / Save(green)` with the Saved note relocated to row 2 right. Row-2 crumbs navigate only to real ancestor pages (`ancestorChain`/`nodeDir`); synthesized sections stay static. - Edit: `Close / Save(green) / Save & Close`; icon+label+Saved in row 2 right. Media: `New folder / Upload(green)`; folder crumbs preserved. View: Desktop/Mobile segmented toggle, row 2 collapsed. - All four legacy header class families (`.page-docheader`, `.edit-pane__header`, `.media-toolbar`, `.preview-pane__head`) removed from styles.css and JSX; existing `data-testid`s preserved verbatim. - **Nit (non-blocking):** `Docheader.tsx`s top comment still reads no module has been migrated onto it yet — stale after this PR migrates all four
Author
Owner

This was generated by AI while landing a PR.

Land-PR audit — verdict: PASS

  • CI (vouching signal): ci / build-and-test (pull_request)success (5m9s). Not re-run.
  • Mergeable: main is already an ancestor of afk/74 — merges cleanly, no conflict.
  • Conventions: title is Conventional Commits (feat(web): …); AFK contract satisfied — body carries a working Closes #74.
  • Diff vs issue #74 intent:
    • Shared Docheader shell + DocheaderButton / DocheaderToggle / crumb primitives; row 2 collapses when empty; reserved (empty) right button group present in every module.
    • Page: normal-mode order Publish(green) / Properties / Undo / Discard… / View; props-mode swaps left to Close / Save(green) with the Saved note relocated to row 2 right. Row-2 crumbs navigate only to real ancestor pages (ancestorChain/nodeDir); synthesized sections stay static.
    • Edit: Close / Save(green) / Save & Close; icon+label+Saved in row 2 right. Media: New folder / Upload(green); folder crumbs preserved. View: Desktop/Mobile segmented toggle, row 2 collapsed.
    • All four legacy header class families (.page-docheader, .edit-pane__header, .media-toolbar, .preview-pane__head) removed from styles.css and JSX; existing data-testids preserved verbatim.
  • Nit (non-blocking): the top comment in Docheader.tsx still reads "no module has been migrated onto it yet" — stale after this PR migrates all four; worth a one-line follow-up but not a blocker.

No blockers found. Awaiting the human's free-text go-ahead to merge.

> *This was generated by AI while landing a PR.* **Land-PR audit — verdict: PASS** - **CI (vouching signal):** `ci / build-and-test (pull_request)` — **success** (5m9s). Not re-run. - **Mergeable:** `main` is already an ancestor of `afk/74` — merges cleanly, no conflict. - **Conventions:** title is Conventional Commits (`feat(web): …`); AFK contract satisfied — body carries a working `Closes #74`. - **Diff vs issue #74 intent:** - Shared `Docheader` shell + `DocheaderButton` / `DocheaderToggle` / crumb primitives; row 2 collapses when empty; reserved (empty) right button group present in every module. - Page: normal-mode order `Publish(green) / Properties / Undo / Discard… / View`; props-mode swaps left to `Close / Save(green)` with the Saved note relocated to row 2 right. Row-2 crumbs navigate only to real ancestor pages (`ancestorChain`/`nodeDir`); synthesized sections stay static. - Edit: `Close / Save(green) / Save & Close`; icon+label+Saved in row 2 right. Media: `New folder / Upload(green)`; folder crumbs preserved. View: Desktop/Mobile segmented toggle, row 2 collapsed. - All four legacy header class families (`.page-docheader`, `.edit-pane__header`, `.media-toolbar`, `.preview-pane__head`) removed from styles.css and JSX; existing `data-testid`s preserved verbatim. - **Nit (non-blocking):** the top comment in `Docheader.tsx` still reads "no module has been migrated onto it yet" — stale after this PR migrates all four; worth a one-line follow-up but not a blocker. No blockers found. Awaiting the human's free-text go-ahead to merge.
Sign in to join this conversation.
No reviewers
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
Cloonar/deckle!76
No description provided.