From 43bd104de577c3df79c38913fe923ca0c84bf593 Mon Sep 17 00:00:00 2001 From: cynfria Date: Thu, 16 Jul 2026 20:34:30 -0700 Subject: [PATCH] =?UTF-8?q?feat(desktop):=20onboarding=20polish=20?= =?UTF-8?q?=E2=80=94=20docked=20CTAs,=20backup=20key=20card,=20dot=20grid?= =?UTF-8?q?=20(#2008)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Wes Co-authored-by: Claude Opus 4.8 Co-authored-by: Wes Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co> --- desktop/playwright.config.ts | 1 + .../features/communities/ui/WelcomeSetup.tsx | 14 +- .../src/features/onboarding/ui/AvatarStep.tsx | 198 ++++++----- .../src/features/onboarding/ui/BackupStep.tsx | 19 +- .../onboarding/ui/CommunityOnboardingFlow.tsx | 312 +++++++++--------- .../onboarding/ui/DefaultConfigStep.tsx | 14 +- .../onboarding/ui/MachineOnboardingFlow.tsx | 195 ++++++----- .../onboarding/ui/NostrKeyImportForm.tsx | 33 +- .../onboarding/ui/NsecMaskedDisplay.tsx | 74 +++-- .../onboarding/ui/OnboardingChrome.tsx | 65 ++++ .../features/onboarding/ui/OnboardingFlow.tsx | 248 +++++++------- .../onboarding/ui/OnboardingFooter.tsx | 84 +++++ .../onboarding/ui/OnboardingStepDots.tsx | 40 --- .../features/onboarding/ui/ProfileStep.tsx | 12 +- .../src/features/onboarding/ui/SetupStep.tsx | 14 +- .../src/shared/styles/globals/components.css | 44 ++- desktop/tailwind.config.js | 4 + desktop/tests/e2e/identity-lost.spec.ts | 6 +- .../tests/e2e/onboarding-avatar-skip.spec.ts | 7 +- desktop/tests/e2e/onboarding-backup.spec.ts | 8 +- .../onboarding-docked-cta-screenshots.spec.ts | 70 ++++ 21 files changed, 859 insertions(+), 603 deletions(-) create mode 100644 desktop/src/features/onboarding/ui/OnboardingChrome.tsx create mode 100644 desktop/src/features/onboarding/ui/OnboardingFooter.tsx delete mode 100644 desktop/src/features/onboarding/ui/OnboardingStepDots.tsx create mode 100644 desktop/tests/e2e/onboarding-docked-cta-screenshots.spec.ts diff --git a/desktop/playwright.config.ts b/desktop/playwright.config.ts index fa6f9ae19f..b6296f0f3a 100644 --- a/desktop/playwright.config.ts +++ b/desktop/playwright.config.ts @@ -20,6 +20,7 @@ export default defineConfig({ name: "smoke", testMatch: [ "**/smoke.spec.ts", + "**/onboarding-docked-cta-screenshots.spec.ts", "**/navigation.spec.ts", "**/channels.spec.ts", "**/channel-shared-header-backdrop.spec.ts", diff --git a/desktop/src/features/communities/ui/WelcomeSetup.tsx b/desktop/src/features/communities/ui/WelcomeSetup.tsx index 988a87eb87..d6a6888426 100644 --- a/desktop/src/features/communities/ui/WelcomeSetup.tsx +++ b/desktop/src/features/communities/ui/WelcomeSetup.tsx @@ -13,7 +13,7 @@ import { pubkeyToNpub } from "@/shared/lib/nostrUtils"; import { Button } from "@/shared/ui/button"; import { StartupWindowDragRegion } from "@/shared/ui/StartupWindowDragRegion"; import { useSystemColorScheme } from "@/shared/theme/useSystemColorScheme"; -import { OnboardingStepDots } from "@/features/onboarding/ui/OnboardingStepDots"; +import { OnboardingChrome } from "@/features/onboarding/ui/OnboardingChrome"; type WelcomeSetupPage = "welcome" | "join" | "invite"; type WelcomeTransitionMode = "initial" | OnboardingTransitionDirection; @@ -95,7 +95,7 @@ export function WelcomeSetup({ data-system-color-scheme={systemColorScheme} > - +
{page === "welcome" ? (
-

+

Join or create a community

@@ -152,9 +152,7 @@ export function WelcomeSetup({ transitionKey={`join-${transitionDirection}`} >

-

- Join a community -

+

Join a community

Send your public key to a community owner. Keep Buzz open; once they add you, their invite link will continue setup here. @@ -211,9 +209,7 @@ export function WelcomeSetup({ transitionKey={`invite-${transitionDirection}`} >

-

- I have an invite link -

+

I have an invite link

Keep this page open, then click the invite link you received. Buzz will continue automatically. You can also paste it below. diff --git a/desktop/src/features/onboarding/ui/AvatarStep.tsx b/desktop/src/features/onboarding/ui/AvatarStep.tsx index 20fa8b4586..7333bea5c9 100644 --- a/desktop/src/features/onboarding/ui/AvatarStep.tsx +++ b/desktop/src/features/onboarding/ui/AvatarStep.tsx @@ -8,7 +8,8 @@ import { Plus } from "lucide-react"; import { cn } from "@/shared/lib/cn"; import { Button } from "@/shared/ui/button"; import { Spinner } from "@/shared/ui/spinner"; -import { StepProgress } from "@/shared/ui/step-progress"; +import { ONBOARDING_PRIMARY_CTA_CLASS } from "./OnboardingChrome"; +import { OnboardingFooter } from "./OnboardingFooter"; import { AnimatePresence, motion } from "motion/react"; import * as React from "react"; import { @@ -26,8 +27,6 @@ type AvatarStepProps = { submit: ProfileStepActions["submit"]; updateAvatarUrl: ProfileStepActions["updateAvatarUrl"]; }; - /** Step number for the compact progress bar (mobile layout). */ - currentStep: number; direction: OnboardingTransitionDirection; /** When true, a ghost "Skip for now" button is always visible (not just on error). */ showAlwaysSkip?: boolean; @@ -35,8 +34,6 @@ type AvatarStepProps = { ProfileStepState, "avatar" | "isSaving" | "isUploadingAvatar" | "name" | "saveRecovery" >; - /** Total steps for the compact progress bar (mobile layout). */ - totalSteps?: number; }; function ErrorBanner({ message }: { message: string | null }) { @@ -125,7 +122,6 @@ function AvatarPreview({ function AvatarStepActions({ canSubmit, - currentStep, hidden, isSaving, isUploadingAvatar, @@ -135,10 +131,8 @@ function AvatarStepActions({ onSubmit, saveRecovery, showAlwaysSkip, - totalSteps, }: { canSubmit: boolean; - currentStep: number; hidden: boolean; isSaving: boolean; isUploadingAvatar: boolean; @@ -148,118 +142,108 @@ function AvatarStepActions({ onSubmit: () => void; saveRecovery: ProfileStepState["saveRecovery"]; showAlwaysSkip: boolean; - totalSteps?: number; }) { const areNavigationActionsDisabled = isSaving || isUploadingAvatar; return ( - - {hidden ? null : ( - - - - {saveRecovery.canSkipForNow ? ( - // Error-recovery path: exits onboarding entirely when there is no - // saved display name to fall back on. + + {saveRecovery.canSkipForNow ? ( + // Error-recovery path: exits onboarding entirely when there is no + // saved display name to fall back on. + + ) : showAlwaysSkip && !saveRecovery.errorMessage ? ( + // Normal path: advances to the theme step without saving an avatar. + + ) : null} + + {saveRecovery.canAdvanceWithoutSaving ? ( + + ) : null} + + - ) : showAlwaysSkip && !saveRecovery.errorMessage ? ( - // Normal path: advances to the theme step without saving an avatar. - - ) : null} - - {saveRecovery.canAdvanceWithoutSaving ? ( - - ) : null} - - - - - - )} - + + )} + + ); } export function AvatarStep({ actions, - currentStep, direction, showAlwaysSkip = false, state, - totalSteps, }: AvatarStepProps) { const { advanceWithoutSaving, @@ -328,7 +312,11 @@ export function AvatarStep({ return (

-

+

Next, add a display image

-

+

Choose an image or emoji as your avatar

@@ -411,7 +399,6 @@ export function AvatarStep({