Icon actions in the top navigation replace the green page buttons #101

Closed
opened 2026-07-12 04:03:18 +02:00 by fable-5 · 1 comment
Collaborator

Context

Every page action is a solid green text button (.button): mode toggle, watch, copy/download markdown, docx/odt/pdf export, labels, history, delete in the page header, plus attachments/comments toggles in the editor shell. Together they crowd the page. They should become compact icons in the top navigation (TopBar).

Scope

Introduce a small, SELF-HOSTED, compiled-in SVG icon set (e.g. lucide — MIT, tree-shakeable; ADR 0016's zero-external-requests rule applies: no icon fonts, no CDNs). Move the page actions into the TopBar as icon buttons, shown only while a page route is active (a page-actions slot the page registers into): edit/view toggle, watch, comments (with the unread badge), attachments, labels, history, an overflow "…" menu for copy/download markdown + docx/odt/pdf export + delete, and the plugin page tools where present. Every icon button needs a localized tooltip + aria-label (de+en). The page header keeps only the title; the green .button style remains for forms/dialogs elsewhere.

Acceptance criteria

  • all former page-header and editor-shell action buttons are reachable as icons in the top navigation on page routes, and are absent on non-page routes
  • destructive delete sits behind the overflow menu with its existing confirm; the comments icon keeps the unread badge
  • icons are self-hosted SVGs bundled at build time (no external requests — verify like the fonts pack does), with aria-labels and tooltips in de+en
  • keyboard navigation and focus order across the TopBar actions work; the existing e2e packs (comments, system, content) still pass with updated selectors

Technical notes

  • Inventory & sources: .editor-page__header (PageEditorPage.tsx:427ff, WatchToggle, mode toggle, PageMenu → export/DocumentExportMenu.tsx) and .editor-shell__tools (attachments/comments/page-tools toggles).
  • TopBar: apps/web/src/layout/TopBar.tsx (hamburger ☰, search 🔍, NotificationsBell 🔔 — the existing .icon-button class is the styling hook; TopBar.tsx:57 already anticipates "replaced by an icon set later"). Sidebar/search/bell glyphs should adopt the same icon set.
  • A React context/slot ("page actions") is the likely wiring so TopBar stays page-agnostic.

Dependencies

None (but do this before moving presence into the TopBar — next issue).

Size: ~1.5 days


Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add de and en), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.

## Context Every page action is a solid green text button (`.button`): mode toggle, watch, copy/download markdown, docx/odt/pdf export, labels, history, delete in the page header, plus attachments/comments toggles in the editor shell. Together they crowd the page. They should become compact icons in the top navigation (TopBar). ## Scope Introduce a small, SELF-HOSTED, compiled-in SVG icon set (e.g. lucide — MIT, tree-shakeable; ADR 0016's zero-external-requests rule applies: no icon fonts, no CDNs). Move the page actions into the TopBar as icon buttons, shown only while a page route is active (a page-actions slot the page registers into): edit/view toggle, watch, comments (with the unread badge), attachments, labels, history, an overflow "…" menu for copy/download markdown + docx/odt/pdf export + delete, and the plugin page tools where present. Every icon button needs a localized tooltip + aria-label (de+en). The page header keeps only the title; the green `.button` style remains for forms/dialogs elsewhere. ## Acceptance criteria - [ ] all former page-header and editor-shell action buttons are reachable as icons in the top navigation on page routes, and are absent on non-page routes - [ ] destructive delete sits behind the overflow menu with its existing confirm; the comments icon keeps the unread badge - [ ] icons are self-hosted SVGs bundled at build time (no external requests — verify like the fonts pack does), with aria-labels and tooltips in de+en - [ ] keyboard navigation and focus order across the TopBar actions work; the existing e2e packs (comments, system, content) still pass with updated selectors ## Technical notes - Inventory & sources: `.editor-page__header` (PageEditorPage.tsx:427ff, WatchToggle, mode toggle, PageMenu → export/DocumentExportMenu.tsx) and `.editor-shell__tools` (attachments/comments/page-tools toggles). - TopBar: apps/web/src/layout/TopBar.tsx (hamburger ☰, search 🔍, NotificationsBell 🔔 — the existing `.icon-button` class is the styling hook; TopBar.tsx:57 already anticipates "replaced by an icon set later"). Sidebar/search/bell glyphs should adopt the same icon set. - A React context/slot ("page actions") is the likely wiring so TopBar stays page-agnostic. ## Dependencies None (but do this before moving presence into the TopBar — next issue). **Size**: ~1.5 days --- *Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add `de` **and** `en`), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.*
fable-5 added this to the M10 — UI polish milestone 2026-07-12 04:03:18 +02:00
fable-5 added the
frontend
label 2026-07-12 04:03:18 +02:00
Author
Collaborator

Umgesetzt in 65f30a5 (CI grün, HEAD-Lauf e740ea6 komplett grün; die „failure"-Status auf dem Commit selbst sind vom Folge-Push abgebrochene, überholte Runs).

Icon-Set: lucide-react (MIT) als Build-Dependency — die SVGs werden tree-shaken in das Bundle kompiliert, zur Laufzeit gibt es keinerlei externe Requests. Die bestehende Off-Origin-Assertion im fonts-Pack (page.on('request') auf einer Seitenroute) pinnt das mit, wie in den Acceptance-Kriterien gefordert.

Page-Actions-Slot: apps/web/src/layout/page-actions.tsx — die TopBar registriert ein DOM-Element im Context (nur für eingeloggte Nutzer gerendert), die aktive Seite portalt PageActions hinein (createPortal). Die TopBar bleibt page-agnostisch; auf Nicht-Seiten-Routen ist der Slot leer.

In der TopBar auf Seitenrouten: Bearbeiten/Lesen-Toggle, Beobachten (WatchToggle variant="icon", aria-pressed), Kommentare (Unread-Badge als Zahl, Count zusätzlich im aria-label), Anhänge, Plugin-Seitenwerkzeuge (nur wenn vorhanden), Labels, Verlauf — alle als .icon-button mit lokalisiertem aria-label + title (de+en, überwiegend bestehende Keys; neu nur editor:page.moreActions). Overflow-„…"-Menü (role=menu): Markdown kopieren/herunterladen, Word/.odt/PDF-Export (weiter über useDocumentExport), destruktives Löschen in Rot mit bestehendem confirm(). Der Seiten-Header trägt nur noch den Titel; die editor-shell__tools-Zeile ist weg; Hamburger/Suche/Glocke nutzen dasselbe Icon-Set.

e2e: Die Klassen-Hooks (editor-page__mode-toggle, editor-shell__comments-toggle, editor-shell__attachments-toggle, editor-shell__page-tools-toggle, editor-page__labels-toggle, editor-page__export) leben auf den Icon-Buttons weiter, und aria-label = Accessible Name hält getByRole('button', {name:/edit|bearbeiten/i}) intakt — angepasst werden mussten nur content.spec (Overflow öffnen, getByRole('menuitem') für Löschen) und export.spec (Overflow öffnen). Lokal grün gelaufen: content, editor, comments, attachments, labels, backlinks; im CI der komplette Satz inkl. Auth-Pack.

Verifiziert im Browser: Icons + Tooltips de, Accessibility-Tree zeigt alle Aktionen als benannte Buttons in der TopBar-Fokusreihenfolge, Overflow-Menü, Kommentar-Panel-Toggle, Mode-Wechsel (Label flippt auf „Lesen", Editor wird editierbar, Sidebar force-hidden), leerer Slot auf /.

Umgesetzt in `65f30a5` (CI grün, HEAD-Lauf `e740ea6` komplett grün; die „failure"-Status auf dem Commit selbst sind vom Folge-Push abgebrochene, überholte Runs). **Icon-Set:** `lucide-react` (MIT) als Build-Dependency — die SVGs werden tree-shaken in das Bundle kompiliert, zur Laufzeit gibt es keinerlei externe Requests. Die bestehende Off-Origin-Assertion im fonts-Pack (`page.on('request')` auf einer Seitenroute) pinnt das mit, wie in den Acceptance-Kriterien gefordert. **Page-Actions-Slot:** `apps/web/src/layout/page-actions.tsx` — die TopBar registriert ein DOM-Element im Context (nur für eingeloggte Nutzer gerendert), die aktive Seite portalt `PageActions` hinein (`createPortal`). Die TopBar bleibt page-agnostisch; auf Nicht-Seiten-Routen ist der Slot leer. **In der TopBar auf Seitenrouten:** Bearbeiten/Lesen-Toggle, Beobachten (`WatchToggle variant="icon"`, aria-pressed), Kommentare (Unread-Badge als Zahl, Count zusätzlich im aria-label), Anhänge, Plugin-Seitenwerkzeuge (nur wenn vorhanden), Labels, Verlauf — alle als `.icon-button` mit lokalisiertem `aria-label` + `title` (de+en, überwiegend bestehende Keys; neu nur `editor:page.moreActions`). Overflow-„…"-Menü (`role=menu`): Markdown kopieren/herunterladen, Word/.odt/PDF-Export (weiter über `useDocumentExport`), destruktives Löschen in Rot mit bestehendem `confirm()`. Der Seiten-Header trägt nur noch den Titel; die `editor-shell__tools`-Zeile ist weg; Hamburger/Suche/Glocke nutzen dasselbe Icon-Set. **e2e:** Die Klassen-Hooks (`editor-page__mode-toggle`, `editor-shell__comments-toggle`, `editor-shell__attachments-toggle`, `editor-shell__page-tools-toggle`, `editor-page__labels-toggle`, `editor-page__export`) leben auf den Icon-Buttons weiter, und `aria-label` = Accessible Name hält `getByRole('button', {name:/edit|bearbeiten/i})` intakt — angepasst werden mussten nur content.spec (Overflow öffnen, `getByRole('menuitem')` für Löschen) und export.spec (Overflow öffnen). Lokal grün gelaufen: content, editor, comments, attachments, labels, backlinks; im CI der komplette Satz inkl. Auth-Pack. **Verifiziert** im Browser: Icons + Tooltips de, Accessibility-Tree zeigt alle Aktionen als benannte Buttons in der TopBar-Fokusreihenfolge, Overflow-Menü, Kommentar-Panel-Toggle, Mode-Wechsel (Label flippt auf „Lesen", Editor wird editierbar, Sidebar force-hidden), leerer Slot auf `/`.
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
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: stwaidele/dorfteich#101
No description provided.