4126cf698424
make create-vault an explicit onboarding choice and guard final-card click from silently creating
- time
- 2026-08-18 04:16 UTC · 2 months ago
- machine
- koh2
- agent
- deepseek-v4-flash-free
- session
- onboarding create-vault choice
- parent
- 7a2a18dfa865
↓ peach-browser-4126cf69.tar.gzatlas at this save
files changed3 files
src/popup/styles/popup.css+10 −0src/popup/views/AdoptVaultView.test.tsx+20 −0src/popup/views/Onboarding.tsx+22 −1src/popup/styles/popup.css+10 −0
@@ -7124,6 +7124,16 @@71247124 background: color-mix(in srgb, var(--peach-accent) 13%, transparent);71257125 }71267126 7127+.peach-onboarding-choice--create {7128+ border-color: var(--peach-accent);7129+ background: var(--peach-accent);7130+ color: rgba(0, 0, 0, 0.92);7131+}7132+7133+.peach-onboarding-choice--create .peach-onboarding-choice-detail {7134+ color: rgba(0, 0, 0, 0.72);7135+}7136+71277137 .peach-adopt-vault {71287138 position: relative;71297139 min-height: 100%;src/popup/views/AdoptVaultView.test.tsx+20 −0
@@ -69,6 +69,26 @@6969 expect(onAdopt).toHaveBeenCalledTimes(1);7070 });7171 72+ it("T-A21b: create-vault is an explicit choice; a final-card tap does not silently create", () => {73+ vi.useFakeTimers();74+ const onComplete = vi.fn();75+ const view = mounted(() => <Onboarding onComplete={onComplete} onRestore={() => {}} onAdopt={() => {}} />);76+77+ button(view.container, "next").click();78+ vi.advanceTimersByTime(220);79+ button(view.container, "next").click();80+ vi.advanceTimersByTime(220);81+82+ expect(view.container.textContent).toContain("Create a new vault");83+84+ (view.container.querySelector(".peach-onboarding-card") as HTMLElement).click();85+ expect(onComplete).not.toHaveBeenCalled();86+87+ button(view.container, "Create a new vault").click();88+ vi.advanceTimersByTime(250);89+ expect(onComplete).toHaveBeenCalledTimes(1);90+ });91+7292 it("T-A22: password screen uses the same minimum-length gate as create-vault", () => {7393 const view = mounted(() => <AdoptVaultView onCancel={() => {}} onDone={() => {}} />);7494 const continueButton = button(view.container, "Continue");src/popup/views/Onboarding.tsx+22 −1
@@ -95,11 +95,17 @@9595 <div9696 class="peach-onboarding-card"9797 classList={{ "is-exiting": exiting() }}98- onClick={advance}98+ onClick={() => {99+ // Final card: creation is an explicit choice; a stray card-body tap100+ // must not silently start vault creation.101+ if (card() === CARDS.length - 1) return;102+ advance();103+ }}99104 role="button"100105 tabIndex={0}101106 onKeyDown={(e) => {102107 if (e.key === "Enter" || e.key === " ") {108+ if (card() === CARDS.length - 1) return;103109 e.preventDefault();104110 advance();105111 }@@ -119,6 +125,21 @@119125 </p>120126 </Show>121127 <Show when={card() === CARDS.length - 1}>128+ <div class="peach-onboarding-choice-row">129+ <button130+ type="button"131+ class="peach-onboarding-choice peach-onboarding-choice--create"132+ onClick={(e) => {133+ e.stopPropagation();134+ void advance();135+ }}136+ >137+ <span class="peach-onboarding-choice-label">Create a new vault</span>138+ <span class="peach-onboarding-choice-detail">139+ Set your master password and start saving.140+ </span>141+ </button>142+ </div>122143 <p class="peach-onboarding-choice-heading">Already using Peach?</p>123144 <div class="peach-onboarding-choice-row">124145 <button