Resizable sidebar width #99

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

Context

The sidebar is fixed at 16rem (--sidebar-width); long page titles truncate and wide screens waste space. Users want to drag it to their liking.

Scope

A drag handle on the sidebar's right edge resizes it with the mouse (pointer events; also keyboard-adjustable for accessibility). Clamp to a sane range (e.g. 12–32rem). Persist the chosen width per browser via the existing usePersistentState mechanism (like ui.sidebar.collapsed). Resizing must play nicely with the existing collapse toggle (Ctrl/Cmd+, hamburger) and the editor's force-hide (useForceSidebarHidden): collapse animates from/to the chosen width, not the default.

Acceptance criteria

  • dragging the handle resizes the sidebar live; the width survives a reload (persisted)
  • the width is clamped to the documented min/max; double-click on the handle resets to the default 16rem
  • collapse/expand and the editor's force-hide keep working at any custom width
  • the handle is keyboard-operable (focusable, arrow keys adjust) and carries a localized accessible name (de+en)

Technical notes

  • --sidebar-width token (apps/web/src/styles/tokens.css), .sidebar and .sidebar--collapsed (base.css — the collapse uses margin-left: calc(-1 * var(--sidebar-width)), which follows a custom width automatically if the token is set as inline style on .app-body).
  • Layout: .app-body flexbox in apps/web/src/layout/AppLayout.tsx; persistence helper usePersistentState is already there.

Dependencies

None.

Size: ~0.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 The sidebar is fixed at 16rem (`--sidebar-width`); long page titles truncate and wide screens waste space. Users want to drag it to their liking. ## Scope A drag handle on the sidebar's right edge resizes it with the mouse (pointer events; also keyboard-adjustable for accessibility). Clamp to a sane range (e.g. 12–32rem). Persist the chosen width per browser via the existing `usePersistentState` mechanism (like `ui.sidebar.collapsed`). Resizing must play nicely with the existing collapse toggle (Ctrl/Cmd+\, hamburger) and the editor's force-hide (`useForceSidebarHidden`): collapse animates from/to the chosen width, not the default. ## Acceptance criteria - [ ] dragging the handle resizes the sidebar live; the width survives a reload (persisted) - [ ] the width is clamped to the documented min/max; double-click on the handle resets to the default 16rem - [ ] collapse/expand and the editor's force-hide keep working at any custom width - [ ] the handle is keyboard-operable (focusable, arrow keys adjust) and carries a localized accessible name (de+en) ## Technical notes - `--sidebar-width` token (apps/web/src/styles/tokens.css), `.sidebar` and `.sidebar--collapsed` (base.css — the collapse uses `margin-left: calc(-1 * var(--sidebar-width))`, which follows a custom width automatically if the token is set as inline style on `.app-body`). - Layout: `.app-body` flexbox in `apps/web/src/layout/AppLayout.tsx`; persistence helper `usePersistentState` is already there. ## Dependencies None. **Size**: ~0.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:17 +02:00
fable-5 added the
frontend
label 2026-07-12 04:03:17 +02:00
Author
Collaborator

Umgesetzt in 6c4f37e (CI grün; die späteren Statusmeldungen „failure" auf diesem Commit sind von Folge-Pushes überholte, abgebrochene Runs — der HEAD-Lauf e740ea6 mit allen M10-Änderungen ist komplett grün).

Was drin ist

  • apps/web/src/layout/SidebarResizer.tsx: Drag-Handle an der rechten Sidebar-Kante (role=separator, aria-valuenow/min/max), Pointer-Drag mit setPointerCapture, Tastatur: Pfeiltasten (±1rem) + Home/End, Doppelklick = Reset auf 16rem.
  • Clamp 12–32rem (auch beim Lesen des persistierten Werts — Alt-Werte außerhalb der Grenzen werden eingefangen).
  • Persistenz via usePersistentState('ui.sidebar.width'), wie ui.sidebar.collapsed.
  • AppLayout setzt --sidebar-width als Inline-Style auf .app-body — dadurch animieren Collapse (Ctrl/Cmd+\, Hamburger) und der Editor-Force-Hide automatisch von/zur gewählten Breite (margin-left: calc(-1 * var(--sidebar-width))). Bei eingeklappter Sidebar wird der Handle nicht gerendert.
  • Lokalisierter Accessible Name layout.sidebar.resize (de+en).

Verifiziert im Browser gegen einen frischen lokalen Stack: Drag live, Breite überlebt Reload, Clamp beidseitig (End→32rem, weiter rechts bleibt 32; Home→12rem), Doppelklick-Reset, Collapse/Expand bei 24rem Custom-Breite (margin-left exakt -384px), Tastaturbedienung über den fokussierten Handle.

Umgesetzt in `6c4f37e` (CI grün; die späteren Statusmeldungen „failure" auf diesem Commit sind von Folge-Pushes überholte, abgebrochene Runs — der HEAD-Lauf `e740ea6` mit allen M10-Änderungen ist komplett grün). **Was drin ist** - `apps/web/src/layout/SidebarResizer.tsx`: Drag-Handle an der rechten Sidebar-Kante (`role=separator`, `aria-valuenow/min/max`), Pointer-Drag mit `setPointerCapture`, Tastatur: Pfeiltasten (±1rem) + Home/End, Doppelklick = Reset auf 16rem. - Clamp 12–32rem (auch beim Lesen des persistierten Werts — Alt-Werte außerhalb der Grenzen werden eingefangen). - Persistenz via `usePersistentState('ui.sidebar.width')`, wie `ui.sidebar.collapsed`. - `AppLayout` setzt `--sidebar-width` als Inline-Style auf `.app-body` — dadurch animieren Collapse (Ctrl/Cmd+\\, Hamburger) und der Editor-Force-Hide automatisch von/zur gewählten Breite (`margin-left: calc(-1 * var(--sidebar-width))`). Bei eingeklappter Sidebar wird der Handle nicht gerendert. - Lokalisierter Accessible Name `layout.sidebar.resize` (de+en). **Verifiziert** im Browser gegen einen frischen lokalen Stack: Drag live, Breite überlebt Reload, Clamp beidseitig (End→32rem, weiter rechts bleibt 32; Home→12rem), Doppelklick-Reset, Collapse/Expand bei 24rem Custom-Breite (margin-left exakt -384px), Tastaturbedienung über den fokussierten Handle.
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#99
No description provided.