Files
webmail-client/frontend
lukasandClaude Opus 5 9f9e959a05 Compose: a dock of windows that survive the app around them
Clicking Compose with a window already open cleared what you had typed.
MailLayout bumped a React key on every open to force a fresh editor, and
switching folders ran an effect that closed the composer outright. Both
were deliberate when only one composer could exist at a time.

Underneath them sat a sharper constraint: RichTextEditor seeds its
contentEditable exactly once, so ANY remount silently discards the body.
Every part of this change is shaped by keeping a composer mounted.

Windows now live in one ordered list, each with a stable id used as its
React key, rendered by ComposeDock as a single keyed array — open windows
and collapsed title bars together. Splitting the open one into a child
slot of its own would hand its state to whichever window took its place,
which is exactly what happened the first time around.

  - A minimize control, first of the four window icons, collapses a
    window to a title bar showing its subject (or "New message"). The
    subtree is hidden, never unmounted.
  - Clicking Compose parks the open windows and appends a new one, so
    each click pushes the previous window one place left.
  - Restoring a window touches only that window; several can be open at
    once. When they stop fitting, the least recently reached-for ones
    are DRAWN as bars — state untouched, so they spring back open when
    room returns.
  - Expanding matches the reading pane, measured live, and moves the
    window to the end of the row: the row is right-anchored, so a bar
    after it would shove an expanded window off the pane and across the
    list and sidebar.
  - A window is given its height rather than sizing to its content. Left
    to itself it grew with the body until the top ran off the screen,
    and the `flex-1` body never became scrollable because there was no
    leftover space to divide.
  - Leaving a folder un-expands a window instead of closing it.
  - The dock row is pointer-events-none — its box spans the tallest
    window in it, and as a bare div it shielded the mail list beside it.
  - Drafts opened from the Drafts folder now load in the reading pane,
    keyed by draft id, with the open one marked in the list.

Also fixes a blank draft saved for every composer opened: the signature
effect guarded itself with a "first run" flag, which StrictMode's double
invocation spends on the first pass. The second pass rewrote the
signature of an untouched composer, marking it dirty. Keyed on the
account instead, so it is idempotent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018SqJYt7jD7oUEkoY68sBZo
2026-09-21 21:32:41 +02:00
..