From 9add305a101ff8f1f839f76f922ceddcf8ac7f22 Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Fri, 24 Apr 2026 23:06:56 -0400 Subject: [PATCH] =?UTF-8?q?docs(spec):=20generator=20UX=20redesign=20?= =?UTF-8?q?=E2=80=94=20inline=20panel=20+=20=E2=9C=A8=20trigger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the right-anchored popover (which clips off the popup edge) with an inline panel that injects into the form below the password row. Trigger becomes a ✨ icon button (gold-bg). "save default" demoted to secondary link; single gold "use" CTA. Bundles label-casing polish (drop CAPS LOCK, gold required marker) since .label is shared. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...-04-24-relicario-gen-ux-redesign-design.md | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-24-relicario-gen-ux-redesign-design.md diff --git a/docs/superpowers/specs/2026-04-24-relicario-gen-ux-redesign-design.md b/docs/superpowers/specs/2026-04-24-relicario-gen-ux-redesign-design.md new file mode 100644 index 0000000..c6e654f --- /dev/null +++ b/docs/superpowers/specs/2026-04-24-relicario-gen-ux-redesign-design.md @@ -0,0 +1,142 @@ +# Generator UX redesign + adjacent popup polish — design + +**Date:** 2026-04-24 +**Scope:** Replace the right-anchored popover that opens from the password generator trigger with an inline panel that lives inside the form. Swap the "gen" text button for a ✨ icon button. Tighten the label/affordance treatment in the touched screens (login form + vault settings) along the way. Backgrounds, palette, and other unrelated UI stay untouched. + +## Goal + +The current popover (β₂, commit `8a16482`) positions itself by anchoring its left edge to the trigger button's left edge, but the trigger sits on the right side of the password input row. Combined with the popover's `min-width: 300px` inside a 360 px Chrome popup, the popover always overflows the popup boundary by ~180–220 px. In manual testing it appears as a clipped card with cut-off labels and inaccessible buttons. + +A surgical clamp-fix (~10 lines) would patch the symptom but leave the underlying UX awkward — even when fully visible, the popover floats over the form, hides what you were filling out, and crams two primary actions ("save default" + "use this value") next to each other. The user's feedback was explicit: "we may gotta plan some ui overhauls here, like an emoji instead of 'gen' and a cleaner UI approach for sure." This redesign replaces the popover pattern entirely instead of patching it. + +## Visual identity + +### Trigger button + +- **Icon:** ✨ (U+2728 sparkles emoji). Reads as "auto-generate / freshly minted." Visually rhymes with the sparkle dot on the new logo's gem (commit `a3f13fd`). +- **Color:** deep gold `#7c5719` background, `#fff3cf` text — matches primary-button styling from the palette refresh. +- **Hover state:** background `#aa812a` (mid gold). +- **Active state** (panel open): background `#aa812a` (visually distinct from idle so the user can tell at a glance whether the panel is open). +- **Layout:** stays in the existing `.inline-row` pattern next to the password input; replaces the current `` with ``. +- **Tooltip:** `title="generate password"` for hover. +- **Width:** ~38 px (single emoji glyph fits without padding noise). + +### Inline panel (replaces popover) + +When ✨ is clicked, a panel injects into the form's DOM **between the password row and the next form-group** (e.g., the totp-secret row). Other fields below shift down. The panel: + +- Lives at the form's full available width (no positioning math, no clipping). +- Has a subtle gold border (`1px solid #aa812a`) to feel attached to the trigger. +- Auto-generates a preview the moment it opens, using `VaultSettings.generator_defaults` as the initial knob state. + +Panel composition (top to bottom): + +1. **Kind toggle** — pill-style two-button switch: `random` / `passphrase`. Active button: gold-bg. +2. **Common knobs (always visible):** + - For `random`: length slider (8–48, default 20), four character-class checkboxes (a-z / A-Z / 0-9 / !@#). + - For `passphrase` (BIP39): word_count slider (3–10, default 4), separator text input (1 char), capitalization radio (lower / upper / title). +3. **Preview row** — generated value in monospace gold (`#f1cf6e`), with a `↻` regenerate button. +4. **`more ▾` disclosure** — when expanded, shows the rarely-used knobs: + - For `random`: symbol charset (`safe` / `full` toggle). + - For `passphrase`: nothing extra (separator and capitalization moved to common). + - For both: an empty placeholder when no advanced knobs apply (so the disclosure always renders for consistency, even if collapsed-only). +5. **Action row:** + - **`↑ save these as default`** — small underlined link, left-aligned, `#8b949e` color → `#d2ab43` on hover. Writes current knobs to `VaultSettings.generator_defaults` via the existing `update_vault_settings` message; shows a brief "saved" toast next to the link; panel stays open. **Demoted from primary button** because most of the time the user just wants this password, not to change global defaults. + - **`cancel`** — secondary button (transparent bg, gray border). + - **`use`** — primary CTA: gold bg `#7c5719`, `#fff3cf` text. Commits the current preview value into the password input and closes the panel. + +### Adjacent polish (scope B) + +Touched only in screens we're already modifying (login form + vault settings): + +- **Form labels:** `.label` class drops `text-transform: uppercase` and reduces `letter-spacing` from `0.5px` to `0.02em`. Lowercase labels match the panel's knob labels and feel less shouty. Font weight goes 600 → 500 for slightly less visual weight; color stays `#8b949e`. +- **Required marker:** the existing `*` next to required-field labels picks up gold (`#aa812a`) instead of inheriting label gray, so it actually reads as a marker. +- **Button styles:** primary form buttons (cancel/save at the bottom of the login form) already use the palette refresh; nothing to change there. + +These polish changes apply to ALL form labels in the login form and vault settings (not just the password row), since the `.label` class is shared. Other forms that use `.label` (SecureNote, Identity, Card, Key, Totp, Document-coming-soon) will pick up the lowercase treatment automatically — that's a deliberate choice, not a side effect: the CAPS LOCK feel was a project-wide rough edge that's worth fixing in this slice. + +## Behavior + +| Trigger | Action | +|---------|--------| +| click ✨ | toggle panel open/closed; auto-generate on first open using saved defaults | +| click ↻ | regenerate preview (no commit) | +| change a knob | debounced auto-regenerate (150 ms — same as existing) | +| click `use` | commit current preview into password field, close panel | +| click `cancel` | close panel without committing; password field unchanged | +| click `↑ save these as default` | write current knobs to `VaultSettings.generator_defaults`; show toast; panel stays open | +| press Escape (when panel open) | close panel without committing | +| click ✨ again while panel open | close panel (no commit) | + +The panel does NOT close on click-outside. The user might want to drag from the panel to verify the value or copy it before clicking `use`; closing on click-outside makes that fragile. Escape and explicit cancel/use are the dismissal paths. + +## Vault settings adaptation + +The vault settings screen currently has a `` next to a generator-summary text line. After redesign: + +- The "configure ▾" button becomes a ✨ button matching the login form trigger. +- When clicked, the same inline panel renders **inside the vault-settings "generator" section** (not as a popover). +- One difference from the login-form context: the action row drops the `cancel` and `use` buttons since there's no password input to fill — instead, the panel is purely for inspecting/configuring defaults. The `↑ save these as default` link becomes the only action in this context, and ✨ closes the panel just like in the login form. +- The generator preview text line (`generatorSummary(...)`) stays above the panel even when expanded — it serves as a "current default" reference. + +## Files affected + +### Modified + +- **`extension/src/popup/components/generator-popover.ts`** — major rewrite. Probably gets renamed to `generator-panel.ts` (cleaner semantics). Same module, different positioning (inline DOM injection vs absolute-positioned popover) and different action set per context. +- **`extension/src/popup/components/types/login.ts`** — replace `gen-btn` text content with ✨; update click handler to call the renamed module; drop the standalone close-on-blur logic if any. +- **`extension/src/popup/components/settings-vault.ts`** — replace `configure-gen` button content with ✨; update click handler; render the inline panel in place rather than calling the popover open. +- **`extension/src/popup/styles.css`** — add `.gen-trigger` rule (button styling); add `.gen-panel` and child rules (replacing `.generator-popover` rules). Modify `.label` rule to drop uppercase and tighten letter-spacing/weight; modify `.label .req` (or equivalent for the `*`) to gold. Remove the `.generator-popover` rules entirely once the new panel works (no need to keep old popover CSS around). + +### Renamed + +- `extension/src/popup/components/generator-popover.ts` → `extension/src/popup/components/generator-panel.ts`. Test file follows: `__tests__/generator-popover.test.ts` → `__tests__/generator-panel.test.ts`. Update imports in `login.ts`, `settings-vault.ts`, and the test file accordingly. Sequencing decision (git-mv first vs rewrite first) noted in open questions. + +### Updated tests + +- **`extension/src/popup/components/__tests__/generator-popover.test.ts`** (renamed): existing 7 tests cover knob → message-shape behavior. Most should survive verbatim — they're DOM-level, not positioning-level. Update test setup to mount the panel inline (in a parent container) rather than asserting on `document.body` children. Add 2–3 new tests: + - Panel opens via aria-expanded toggling on the trigger + - Panel auto-generates on first open + - Escape key closes the panel + +### Markup unchanged but new selectors + +- The `.inline-row` pattern in login form stays. Just the button content/styling changes. + +## Acceptance + +- [ ] Clicking ✨ on the login form opens an inline panel below the password row. +- [ ] Panel auto-generates a preview using current `VaultSettings.generator_defaults`. +- [ ] Knob changes debounce-regenerate; ↻ button forces a regenerate. +- [ ] `use` button commits preview into password input and closes panel. +- [ ] `cancel` button closes panel without committing. +- [ ] Escape key closes panel without committing. +- [ ] Clicking ✨ again while panel open closes it. +- [ ] `↑ save these as default` link writes to `VaultSettings.generator_defaults`; toast appears; panel stays open. +- [ ] Vault settings ✨ button opens the same panel inline (no popover); `↑ save these as default` is the only action; ✨ toggles closed. +- [ ] All form labels in login + vault settings are lowercase with reduced letter-spacing. +- [ ] Required-field `*` marker is gold (`#aa812a`). +- [ ] No element overflows the popup right edge in any state. +- [ ] `bun run test` passes (existing 7 generator tests survive the rename + 2-3 new tests added → ~9–10 generator-panel tests; total still around 124–127). +- [ ] `bunx tsc --noEmit` clean. +- [ ] `bun run build:all` clean (Chrome + Firefox). +- [ ] No new automated tests for the visual polish (label casing, gold `*`) — visually verified. +- [ ] Manual: walk through both contexts (login form + vault settings) on Chrome and Firefox. + +## Out of scope + +- The capture-prompt and ack-prompt content scripts (still use their own button styling — no change here). +- The setup tab's strength-bar / advice-block (touched in logo-refresh palette swap; nothing more to do). +- Other popup forms beyond their `.label` class picking up the lowercase treatment automatically (no per-type form rework). +- Generator output strength visualization (zxcvbn meter inside the panel) — could be a future polish but not now. +- Multi-preview / "show 3 candidates" pattern — keeping the single-preview + regenerate flow. +- Animation/transitions on panel open-close — purely instant for now (a fade or slide-down can be added later as polish without breaking anything). +- Click-outside-to-close — explicitly NOT included (see Behavior section reasoning). + +## Open questions deferred to plan + +- **Module rename ordering:** is it cleaner to (a) rewrite in-place keeping the `generator-popover.ts` filename then rename in a follow-up, or (b) git-mv first then rewrite? Plan ships (b) — git-mv preserves history, reviewers see "rename + edits" cleanly. +- **Test mounting strategy:** existing tests `document.body.appendChild(host)` then assert. New panel mounts inside a parent. Plan: tests create a parent div, pass it as the mount target to a new `openGeneratorPanel(opts)` signature that takes `{ parent, anchor, initial, onPicked, onCancel }`. The login-form caller passes the form element as `parent`. +- **The "more ▾" placeholder:** for passphrase mode, all knobs are common and there's nothing in advanced. Plan: render the disclosure with text "(no advanced options for passphrase)" when expanded, OR hide the disclosure entirely in passphrase mode. Plan ships the hide-when-empty option — less visual noise. +- **`save default` toast:** existing toast infrastructure in popup? If yes, reuse. If not, the smallest toast = a 1.5s fade-in/fade-out span next to the `↑ save these as default` link saying "✓ saved". Plan picks based on what already exists. +- **Vault-settings panel ✨ — when no defaults exist:** the very first time a vault is created, `VaultSettings.generator_defaults` should already be initialized (it is, per β₂). Confirm and document.