Unified two-row TYPO3-style docheader across page/view/media/edit modules #73

Closed
opened 2026-07-17 12:37:32 +02:00 by dominik.polakovics · 1 comment

PR 2 of 2. Blocked by #72 (app-wide design tokens) — build on those tokens.

Problem

Every module header is bespoke inline JSX with its own class family and button style: .page-docheader (PagePane.tsx ~1753), .edit-pane__header (EditPane.tsx ~216), .media-toolbar (MediaModule.tsx ~1482), .preview-pane__head (PreviewPane.tsx ~236). Root elements, button radii/padding/icon conventions, and left/right placement all differ.

Agreed design (full decision record)

Structure — two-row, TYPO3-faithful docheader:

  • Row 1: button bar with a left group and a right group.
  • Row 2: context row — location (crumbs) left, identity + state right. Collapses entirely when a module has nothing to show (view module).

Button split — TYPO3-literal: left group holds ALL document actions including View and the viewport toggle. Right group is reserved for future system-level tools (shortcuts, refresh, help) and is empty everywhere today — it must still exist in the component.

Button presentation: icon (lucide) + text label on every button. Not icon-only.

Ordering convention (left group): Close/back leftmost → primary action (Save/Publish) → secondary saves → Properties → Undo → destructive (Discard) → View last.

Emphasis: exactly one green primary per bar; all other buttons flat gray. Page: Publish. Edit: Save. Media: Upload. View: none.

Per-module row 1 (approved):

  • Page (normal): [☁ Publish] [⚙ Properties] [↶ Undo] [↺ Discard] [↗ View]
  • Page (props mode): left group swaps to [⬅ Close] [💾 Save]; row 2 unchanged; the "Saved" note moves to row 2 right. No disabled leftovers.
  • Edit: [⬅ Close] [💾 Save] [💾 Save & Close] (Close moves from last to first)
  • Media: [📁 New folder] [⬆ Upload]
  • View: Desktop/Mobile segmented control in the left group.

Per-module row 2 (approved):

  • Page: path as crumb segments left (e.g. / products / widgets) — each segment resolving to a real ancestor page is clickable and navigates like the tree; title + git-state badge right.
  • Media: existing folder crumbs left (keep navigation behavior); right empty.
  • Edit: left empty; element icon + label + "Saved" indicator right.
  • View: row 2 collapsed.

Viewport toggle: stays a segmented control (joined borders, aria-pressed), restyled with shared tokens, as a second docheader primitive — not two pressed action buttons.

Implementation

  • New shared Solid component web/src/components/Docheader.tsx with four slot props (buttons-left, buttons-right, context-left, context-right) + DocheaderButton primitive (icon, label, primary flag, disabled, title) + segmented-toggle primitive.
  • One .docheader CSS family consuming the tokens from #72; delete .page-docheader, .media-toolbar, .preview-pane__head header rules, and .edit-pane__header/.btn-save-in-header usage.
  • Migrate all four modules onto the component. Out of scope: global .app-header, tree pane pane__title, inner panel headers (media detail aside, layout-cell heads, element toolbars).
  • Keep existing data-testids stable (page-docheader, publish-page, edit-header, edit-save, edit-save-close, edit-close, media-toolbar, …) so tests don't churn; update tests only where ordering/DOM structure assertions break.
  • Verification: manual click-through of all four modules incl. page props mode, publish flow, media upload/new-folder, edit save flows, viewport toggle.

Dev notes

  • Toolchains via nix: nix shell nixpkgs#go --command ...; web/dist needed for go test ./....
  • scaffold/site/AGENTS.md unaffected (admin-UI-only change).
PR 2 of 2. **Blocked by #72** (app-wide design tokens) — build on those tokens. ## Problem Every module header is bespoke inline JSX with its own class family and button style: `.page-docheader` (PagePane.tsx ~1753), `.edit-pane__header` (EditPane.tsx ~216), `.media-toolbar` (MediaModule.tsx ~1482), `.preview-pane__head` (PreviewPane.tsx ~236). Root elements, button radii/padding/icon conventions, and left/right placement all differ. ## Agreed design (full decision record) **Structure — two-row, TYPO3-faithful docheader:** - Row 1: button bar with a left group and a right group. - Row 2: context row — location (crumbs) left, identity + state right. Collapses entirely when a module has nothing to show (view module). **Button split — TYPO3-literal:** left group holds ALL document actions including View and the viewport toggle. Right group is reserved for future system-level tools (shortcuts, refresh, help) and is empty everywhere today — it must still exist in the component. **Button presentation:** icon (lucide) + text label on every button. Not icon-only. **Ordering convention (left group):** Close/back leftmost → primary action (Save/Publish) → secondary saves → Properties → Undo → destructive (Discard) → View last. **Emphasis:** exactly one green primary per bar; all other buttons flat gray. Page: Publish. Edit: Save. Media: Upload. View: none. **Per-module row 1 (approved):** - Page (normal): `[☁ Publish] [⚙ Properties] [↶ Undo] [↺ Discard] [↗ View]` - Page (props mode): left group swaps to `[⬅ Close] [💾 Save]`; row 2 unchanged; the "Saved" note moves to row 2 right. No disabled leftovers. - Edit: `[⬅ Close] [💾 Save] [💾 Save & Close]` (Close moves from last to first) - Media: `[📁 New folder] [⬆ Upload]` - View: Desktop/Mobile segmented control in the left group. **Per-module row 2 (approved):** - Page: path as crumb segments left (e.g. `/ products / widgets`) — **each segment resolving to a real ancestor page is clickable** and navigates like the tree; title + git-state badge right. - Media: existing folder crumbs left (keep navigation behavior); right empty. - Edit: left empty; element icon + label + "Saved" indicator right. - View: row 2 collapsed. **Viewport toggle:** stays a segmented control (joined borders, `aria-pressed`), restyled with shared tokens, as a second docheader primitive — not two pressed action buttons. ## Implementation - New shared Solid component `web/src/components/Docheader.tsx` with four slot props (buttons-left, buttons-right, context-left, context-right) + `DocheaderButton` primitive (icon, label, primary flag, disabled, title) + segmented-toggle primitive. - One `.docheader` CSS family consuming the tokens from #72; delete `.page-docheader`, `.media-toolbar`, `.preview-pane__head` header rules, and `.edit-pane__header`/`.btn-save`-in-header usage. - Migrate all four modules onto the component. Out of scope: global `.app-header`, tree pane `pane__title`, inner panel headers (media detail aside, layout-cell heads, element toolbars). - Keep existing `data-testid`s stable (`page-docheader`, `publish-page`, `edit-header`, `edit-save`, `edit-save-close`, `edit-close`, `media-toolbar`, …) so tests don't churn; update tests only where ordering/DOM structure assertions break. - Verification: manual click-through of all four modules incl. page props mode, publish flow, media upload/new-folder, edit save flows, viewport toggle. ## Dev notes - Toolchains via nix: `nix shell nixpkgs#go --command ...`; `web/dist` needed for `go test ./...`. - `scaffold/site/AGENTS.md` unaffected (admin-UI-only change).
Author
Owner

Superseded by #74. This issue's "Blocked by #72" was inline prose, not a machine-readable ## Blocked by section, so the AFK scheduler would have treated it as unblocked and could have started it before #72 (design tokens) lands. labctl has no issue-edit command, so #74 refiles the same content in the to-issues template shape with a proper ## Blocked by section.

Superseded by #74. This issue's "Blocked by #72" was inline prose, not a machine-readable `## Blocked by` section, so the AFK scheduler would have treated it as unblocked and could have started it before #72 (design tokens) lands. labctl has no issue-edit command, so #74 refiles the same content in the to-issues template shape with a proper `## Blocked by` section.
Sign in to join this conversation.
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#73
No description provided.