githubnext/chopinPublic

Let's compose rich plans together

Edit the document title in place in the header #343

MergedMaggieAppletonmerged 6 commits intomainfromrefs/pull/343/head
  1. MA

    ## Why

    New documents get random slug names ("eager-valley"), and the only way to name one was header chevron → Rename → modal. Nobody bothers, so the sidebar fills with names nobody chose.

    ## What changed

    - The header title is editable in place, like a Linear issue title. Click it, press F2 (or Enter/Space while it's focused), or choose **Rename** from the chevron menu. **Enter** or blur commits, **Escape** reverts, and an empty or unchanged value does nothing. - **Zero layout shift.** The field keeps the resting title's box, size, and ink (no min-width), so the text and chevron don't move. Editing shows only a selected-grey wash, a hairline petrol ring, and the caret. The ring geometry lives in `theme.css` beside the other focus rules. - At rest the title is plain text. On hover it gets the selected wash, which is more visible on the ground than the old hover wash. The chevron is its own button ("Actions for …") and darkens to secondary ink on header hover. - **New document:** from the click until the title field mounts, printable keys and Enter are held (`holdTyping` in `title-edit.ts`) instead of landing on the page or the editor. The field then mounts focused with the slug selected (placeholder "Untitled"), replays the held text in place of the slug, and commits if Enter was pressed. Nothing typed early becomes a partial name or reaches the document body. Enter or Escape then moves the caret into the body. The hold skips other inputs and textareas, and stops if creation fails or you navigate away. - **Rename is never a modal.** Sidebar row Rename opens that document and its inline title. `rename-document-dialog.tsx` is deleted. The request is held in `title-edit.ts` (the workspace claims it in its own lazy module) (expires after 15 s) and also signalled with a window event when the document is already open. - **Errors:** a 409 reads "A document with this title already exists. Try a different title." Other errors keep the server message. Leaving a rejected title reverts it and closes the field, without retrying. - The document icon no longer shrinks on phones with long titles. - Archived documents and read-only viewers get plain text. The child breadcrumb header is unchanged. - `DocumentRename` gains an `inline` variant that reuses the same request and validation. - No overlap with #297: it doesn't touch `Header`.

    ## Screenshots

    **Before:** header at rest, and renaming needs a modal

    ![before rest](https://github.com/user-attachments/assets/8a86273b-a11a-4667-b552-2e7158af57a2) ![before modal](https://github.com/user-attachments/assets/4308351c-4d25-461a-82f3-c8387c874b24)

    **After:** rest / hover / editing (same box, so no shift)

    ![after rest](https://github.com/user-attachments/assets/af28d61b-e626-4cb9-8e7a-f541e72f8a35) ![after hover](https://github.com/user-attachments/assets/c07ec302-1887-44e7-bb16-b7bd2bf77b48) ![after editing](https://github.com/user-attachments/assets/85897bb1-dd2a-43f3-8d21-f51d7f86a81d)

    **After:** right after New document (generated name selected)

    ![after new document](https://github.com/user-attachments/assets/314664ed-6f84-40e8-b097-8c7ec310d08c)

    **After:** duplicate title

    ![after error](https://github.com/user-attachments/assets/2b0142e1-2a4c-4c30-99d7-42733b882b11)

    **Phone:** rest / editing with a long title

    ![phone rest](https://github.com/user-attachments/assets/76f646c1-1122-48c6-bbaa-10b6b3c0126b) ![phone editing](https://github.com/user-attachments/assets/1f94c0dc-7e54-422d-9361-798f4c40d2ab)

    ## Testing

    - `bun run types`: pass. - `cd apps/web && bun test src/`: all pass. Under heavy machine load a few repo-walking tests time out at 5 s; they pass with `--timeout 60000`. `navigation-chrome.test.ts` covers the title button, the inline field, and the archived and viewer cases. - `bun scripts/check-design-record.ts`: pass. `bun run ci`: fails only on the pinned review hashes below. - Bundle budget: the container build passes (246,869 B raw / 78,772 B gzip, merged with current main). The typing hold adds about 130 B gzip to the initial chunk. - Checked in a real browser against a fake-GitHub server: - Under 4x CPU throttling, typing 16 characters plus Enter straight after clicking New document (0 ms and 10 ms delays, four runs) gave the full title every time, with nothing in the body. - Rest and editing boxes are identical (x 286, width 90.9, height 29.0), and the chevron x doesn't change. - Sidebar Rename of another document navigates there with the field focused and no dialog. - A 409 shows the new copy, and blur reverts with no second PATCH. - No horizontal overflow at 390px. - E2E in CI passes, with new tests: - typing 16 characters plus Enter straight after New document under 4x CPU throttling, at 0 ms and 10 ms delays - sidebar Rename opening another document inline - leaving a rejected title reverts without retrying - click, F2, Escape and blur in place

    The existing rename tests press Enter instead of clicking the removed Save button.

    ## Needs a design-contract review

    These files are pinned in `scripts/design-contract/exceptions/dynamic-web.json`: - `apps/web/src/document-rename.tsx`, new hash `c9df5d5496e382136786e52f65a0d7a096baecd1d9e42ac860579b1b2d7ddd25`. The existing `className` forwarding on the form variant is unchanged. The inline branch uses only static classes. - `apps/web/src/navigation-shell.tsx`, new hash `d081007f84589d21b71a0584a54d6487f9fcb53b5a06937e8b5a1f25b958deb7`. The rename dialog branch and its lazy import were removed, and Rename now navigates. No style or class logic changed.

    šŸ¤– Generated with [Claude Code](https://claude.com/claude-code)

  2. MA
    Author

    **Review:** Changes needed

    Checked in a real browser (headless Chromium, fake-GitHub server) at 1440x900 and 390x844. Keyboard, blur, New document flow, two-user rename, long titles, and menu Rename all work. The items below are polish and one real input-loss bug.

    **Must fix** 1. **Quick typing after New document is lost, and can leave a partial name.** Sequence is route change, then body focused, then the title field focused (`room-workspace.tsx` claims in a `useEffect`). Typing "Quick" right after the URL changes produced a title of `uick`: the first characters went to `body`, the rest replaced the selected slug. Fix: claim during the first render (initial `useState` value from `claimNewDocumentTitle(room)`) so the field mounts and focuses with the workspace, and/or focus the title before the editor takes focus. 2. **Layout shift at rest to editing.** Box/type match (same x, y, height 29px, 14.04px, 4px padding), but `.document-title-input { min-width: 12ch }` widens a short title: `calm-stone` goes 83px to 106px, so the chevron jumps right by 23px. Drop the `min-width` (or apply it to the rest button too). 3. **Error copy.** The alert shows the server string verbatim: "a document with this title already exists". Please map it (409) in `document-rename.tsx` to sentence case, e.g. "A document with this title already exists. Try a different title." Also at 1440 the alert floats over the Chat panel header; fine, but it has no dismiss other than typing. 4. **Blur after a failed rename.** Clicking away leaves the field open (focus elsewhere), the alert stays, and the blur re-fires the failing request. Suggest: on blur with an error, revert and close (or at least don't resubmit).

    **Should fix** 5. **Editing state is heavier than a Linear title.** Rest has no box; editing has a white fill plus a 2px teal ring and the text darkens from tertiary to primary. Consider a 1px ring or the hover wash plus caret, keeping the text colour. The rest hover wash (`--color-hover`) is very faint on this background. 6. **Phone.** With a long title (rest and editing) the document icon squeezes to a dot: add `flex-shrink: 0` to it. Under `(pointer: coarse)` the field becomes 16px (theme.css:858) while rest is ~13.4-14px, so text jumps on focus; acceptable for iOS zoom, but worth knowing. No horizontal overflow (scrollWidth = 390). 7. **Sidebar Rename consistency.** The PR body says it still opens the modal. Observed: for the document that is open, row Rename already focuses the inline title (no dialog); for any other document it opens the modal. Suggest navigating there and claiming an inline edit (reuse the claim from `use-document-creation.ts`) so Rename is never a modal. Update the PR body either way. 8. **Chevron discoverability.** It is a separate 22px button with tooltip "Document actions", aria "Actions for ...", and a hover wash. Reasonable, but it is faint (tertiary) now that the title no longer looks like a menu trigger. Optional: bump to secondary colour on header hover.

    **Notes (no action needed)** - Two users renaming: no draft clobbering; last write wins, titles propagate to the other user's header and sidebar. Silent overwrite is acceptable for v1. - F2, Enter, Space on the button, Escape (focus returns to the title), Tab out, blur commit, and an empty or unchanged value all behave. Tab from a brand-new unchanged title returns focus to the title button, not the body; fine. - `untitled` Set in `use-document-creation.ts` is never cleared if the workspace never mounts (tiny leak); StrictMode double effects would consume the claim once (dev only). - Budget: local build passes; the container job fails the gzip budget by 11 B (documented; a headroom PR will absorb it). `bun run ci` fails only on the pinned review hash for `document-rename.tsx`, which is acceptable here.

    Screenshots (local): `.design-orchestrator/audit-2026-10-07/shots/review-343/`.

  3. MA
    Author

    Thanks. All eight items, plus the minor one, are addressed in a9b6a10b and 60946140:

    1. **Quick typing:** the workspace now claims the edit in its initial `useState`, so the field mounts focused with the workspace. In the browser, typing right after the URL changed kept every character. New e2e: "typing straight after New document names it without losing a character". 2. **Layout shift:** `min-width` is gone. Rest and editing boxes are identical (x 286, w 90.9, h 29.0), and the chevron doesn't move. 3. **409 copy:** now "A document with this title already exists. Try a different title." This also covers the e2e for item 4. 4. **Blur after a failure:** the field reverts and closes with no second PATCH. New e2e: "leaving a rejected title reverts it without retrying". 5. **Lighter editing:** same ink as rest, a selected-grey wash, a hairline petrol ring, and the caret. The ring geometry is in `theme.css` next to the other focus rules, which `focus.test.ts` requires. The rest hover now uses the selected wash, which shows up on the ground. - Note: the resting title is tertiary ink, not primary, so editing stays tertiary to keep zero change between states. If you want both primary, it's a one-line change. 6. **Phone:** the document icon is `shrink-0`. 7. **Sidebar Rename:** it never opens a modal now. It navigates to the document and opens the inline title through the same claim (`title-edit.ts`). If the document is already open, a window event triggers it. `rename-document-dialog.tsx` is deleted. New e2e: "sidebar Rename opens that document with its title ready to edit". 8. **Chevron:** it darkens to secondary ink on header hover. - **Minor:** pending title-edit requests expire after 15 s.

    CI: e2e and container pass. The container bundle is now 81,472 B gzip, under budget. `bun run ci` fails only on the pinned review hashes for `document-rename.tsx` and `navigation-shell.tsx`; both are listed in the PR body. Screenshots in the body are updated.

  4. MA
    Author

    **Review:** Changes needed (one item left)

    Re-verified at 60946140 in a fresh worktree (headless Chromium, 1440x900 and 390x844, fake-GitHub on 8843).

    **Fixed** - Zero rest to editing shift: trigger and field both x=286, y=10.5, h=29.05, 14.04px; chevron stays at x=360.9 in both states. - 409 copy: "A document with this title already exists. Try a different title." - Blur after a failed rename: field closes, title reverts, alert gone, 0 non-GET requests fired. - Editing state: selected wash, 1px ring, same ink as rest. Looks quiet now. - Sidebar Rename never opens a modal: for a non-open doc it navigates and focuses the inline field; for the open doc it focuses it directly; Escape returns focus to the title. - Chevron darkens on header hover. - Phone long title: icon stays 14px, no horizontal overflow (scrollWidth 390), ellipsis at rest.

    **Still broken: immediate typing after New document** Typing right after the URL changes still loses leading characters. 16 chars at 10ms delay gave `CDEFGHIJKLMNOP`, at 30ms `BCDEFGHIJKLMNOP`; `document.activeElement` is `BODY` for a window after the route changes, then the field mounts and selects its slug. Both runs happened on a heavily loaded machine, which widens the gap, but the window is structural. Suggest closing it rather than shrinking it: either buffer keystrokes while the claim is pending and replay them into the field, or focus a hidden/placeholder title input in the same commit as the route change. At minimum, make sure keys typed before the field is ready never become a partial name (the `uick` case from the first review).

    `gh pr checks 343` is reported separately by the reviewer.

  5. MA
    Author

    Fixed structurally in 61dad1fb.

    From the moment New document is clicked, `holdTyping` holds printable keys and Enter in a capture-phase listener, and prevents them from reaching the page. Nothing lands on `body` or in the editor. When the inline title mounts, it focuses, takes the held text in the same task (so no key slips between the hold and the field), replaces the selected slug with it, and commits if Enter was held. The hold: - skips other inputs and textareas - stops if creation fails or you navigate away

    **E2E:** the test now uses `Emulation.setCPUThrottlingRate` at 4. It clicks New document, immediately types 16 characters plus Enter at 0 ms and at 10 ms delays, and asserts the full title and that the body doesn't contain the text. Locally, under the same throttling, four runs all gave the full 16-character title.

    **Known edge:** at 0 ms with a held Enter, the commit can finish before the editor mounts, so focus falls back to the title button instead of the body.

    **CI:** e2e and container pass (initial JS 246,869 B / 78,772 B gzip on the merge with main). `bun run ci` fails only on the two pinned review hashes. The `document-rename.tsx` hash is updated in the PR body to `c9df5d54…`.

  6. MaggieAppletonhead-ref-force-pushed 1390265a6994last month on GitHub

  7. MaggieAppletonmerged 0656783419aalast month on GitHub

  8. MaggieAppletonclosedlast month on GitHub

  9. MaggieAppletonhead-ref-deletedlast month on GitHub