refactor(desktop): feedback is a standard dialog, not the notch-era slot composer

Merged
DA
10d ago
+1287-1886

Settings ▸ General's Send feedback and Suggest a feature (and the new Help-menu items) now open a standard centred dialog, instead of the notch-era slot composer that dropped a half-clipped shape from the top of the window.

Send feedback
Suggest a feature, with words and two screenshots
Thanks — sent

The dialog

  • renderer/feedback-dialog.tsx: a modal on ConfirmDialog's pattern and classes (dimmed backdrop, card, Tab kept in the card via the now-shared trappedTab, focus back to whatever opened it, role="dialog", motion and spacing tokens), 520px wide.
  • The title follows the kind: "Send feedback" / "Suggest a feature". That second name is user-facing copy only; the wire's FEEDBACK_KIND.PROMPT is unchanged.
  • One auto-growing textarea (field-sizing: content) with the kind's placeholder, focused on open.
  • Screenshots come in three ways: the "Attach screenshot" icon button, paste into the field, or a drop anywhere over the dialog. They show as small removable thumbnails. FEEDBACK_LIMITS and the old refusal wording stay; the button disables once 3 are attached.
  • The signature is one quiet line: an Include my name and email checkbox (on by default) and "Sending as Name · email". Signed out there is no line, and the note goes unsigned.
  • The submission keeps the same shape: { kind, message, name?, email?, images }. Name and email are sent only while the box is ticked. The only account data that goes is the signed-in name and email; no credential is included.
  • Buttons use only #1929's shared classes: attach is icon-button, Cancel is toolbar-button, Send is primary-button, and the Settings offers are toolbar-button.
  • Footer: Cancel, then Send (primary, ⌘↩). Send stays disabled until there are words. While sending, the button reads "Sending…" and the controls are disabled. A refused send keeps the dialog open and shows the reason inline.
  • When a send is delivered, the dialog closes and a small "Thanks — sent" toast shows at the bottom of the window for 3s. Its timer is an Effect.sleep atom on the renderer runtime, so there's no raw setTimeout. The Luke swoop/landing is gone.

Draft rule: each kind keeps its own draft. Cancel and a delivered send discard it. Escape or a click on the dimmed window just closes the dialog and keeps the words and screenshots for the next opening of that kind. If there are no words yet, it discards instead. A screenshot still being read when its draft is discarded or sent lands nowhere.

Entry points

  • The two buttons in Settings' Feedback section.
  • Help ▸ Send Feedback… and Help ▸ Suggest a Feature…. These are two menu-only commands in the shortcut table (MENU_COMMAND_LABELS), with no new key. To keep that type-safe, APP_SHORTCUTS is now typed over KeyedCommand, i.e. every command except the menu-only ones.

Deleted (notch-era)

  • feedback-slot.tsx, use-feedback-composer.ts, feedback-entry.ts, feedback-confirmation.ts and their tests.
  • PANEL_PRESENTATION.FEEDBACK and use-panel-entry.ts (only the composer used them after #1926 and #1927).
  • App's presentation is now a constant PANEL. The final notch purge, which the sign-in workspace is landing after this PR, removes it along with data-presentation and the notch CSS.
  • SURFACE_PROPERTY.FEEDBACK_HEIGHT and the now-unused SurfaceProperty type, STILL_MS/parseMilliseconds, about 450 lines of slot/landing CSS, and two rawAsyncPrimitives allowlist rows.
  • I coordinated with the sign-in redesign workspace, which owns sign-in-slot and the rest of the presentation plumbing.

Privacy

The whole dialog card is ph-no-capture, so the screen recording leaves out the words, the thumbnails and the signature. session-replay.ts, PRIVACY.md, packages/feedback's doc and docs/DESIGN.md are updated to match.

Tests

feedback-dialog.test.ts drives the public components (Settings + dialog, wired as the app wires them). It covers:

  • opening from each Settings button and from the Help menu;
  • Send disabled until there are words;
  • ⌘↩ sends the signed payload, closes the dialog, shows the toast and returns focus;
  • unticking the box omits name and email, and a signed-out send is unsigned;
  • attach, remove and the 3-image limit refusal;
  • paste and drop;
  • Escape keeps the draft and never reaches the window, a backdrop click does the same, and Cancel discards;
  • a refused send shows its reason inline;
  • each kind keeps its own draft;
  • a screenshot still encoding when its draft is cancelled lands in no draft.

app-menu.test.ts covers the Help items.

Verification

  • ./scripts/check.sh exits 0 (Linux).
  • CI could not verify the Mac UI, and ./scripts/verify.sh was not run. This was built on a Linux cloud VM; LUKE-159 is the manual Mac pass.
  • The screenshots above are headless Chrome renders of the real DesktopSettings page and FeedbackDialog over the app's real stylesheet. They are not the Electron window.

🤖 Generated with Claude Code


Open workspace in Conductor


Devin Review