refactor(onboarding): align V3 card presentation

Signed-off-by: kenny lopez <klopez4212@gmail.com>
This commit is contained in:
kenny lopez
2026-08-29 12:26:47 +01:00
parent 1a57547e18
commit 857e26e4e0
9 changed files with 114 additions and 41 deletions

View File

@@ -455,7 +455,7 @@ export function AgentCreationPreview({
className={cn(
"w-[400px] p-3",
isOnboarding &&
"buzz-onboarding-neutral-theme bg-white text-foreground",
"buzz-onboarding-neutral-theme bg-white text-foreground [--buzz-onboarding-cta-label:#fff]",
)}
data-system-color-scheme={isOnboarding ? "light" : undefined}
side="bottom"

View File

@@ -15,6 +15,7 @@ export type OnboardingPreviewPage =
| "sign-in-key"
| "forgot-password"
| "backup-options"
| "identity-key-help"
| "backup-password"
| "setup"
| "config"

View File

@@ -66,6 +66,7 @@ type BackupStepProps = {
direction: OnboardingTransitionDirection;
identityStorage?: IdentityStorage;
onNext: () => void;
onOpenIdentityKeyHelp?: () => void;
onOpenPasswordBackup: () => void;
onShowOptions: () => void;
optionsExpanded: boolean;
@@ -85,6 +86,7 @@ export function BackupStep({
direction,
identityStorage,
onNext,
onOpenIdentityKeyHelp,
onOpenPasswordBackup,
onShowOptions,
optionsExpanded,
@@ -225,13 +227,17 @@ export function BackupStep({
{previewMode ? "Create a private identity key" : "Backup options"}
</h1>
{previewMode ? (
<div className="mt-5">
<div className={cardLayout ? "mt-2" : "mt-5"}>
<p className="text-sm leading-6 text-foreground/75">
This key will be how you log into Buzz. You can use it across
Buzz communities and other platforms.
</p>
<div className="mt-2">
<IdentityKeyHelpDialog inline previewMode />
<IdentityKeyHelpDialog
inline
onPreviewOpen={onOpenIdentityKeyHelp}
previewMode
/>
</div>
</div>
) : (

View File

@@ -36,9 +36,11 @@ function rememberIdentityKeyHelpSeen() {
export function IdentityKeyHelpDialog({
inline = false,
onPreviewOpen,
previewMode = false,
}: {
inline?: boolean;
onPreviewOpen?: () => void;
previewMode?: boolean;
}) {
const [isVisible, setIsVisible] = React.useState(
@@ -56,29 +58,38 @@ export function IdentityKeyHelpDialog({
return () => window.clearTimeout(timeout);
}, [isVisible, previewMode]);
const trigger = (
<DialogTrigger asChild>
<Button
className={cn(
previewMode
? "text-foreground underline decoration-foreground/45 underline-offset-4 hover:decoration-foreground"
: "text-foreground/70 hover:text-foreground",
"transition-opacity duration-300 motion-reduce:transition-none",
inline && "h-auto justify-start p-0 text-left",
isVisible ? "opacity-100" : "pointer-events-none opacity-0",
)}
data-testid="identity-key-help-trigger"
tabIndex={isVisible ? 0 : -1}
type="button"
variant="link"
>
{previewMode
? "Learn how identity keys work"
: "What’s an identity key?"}
</Button>
</DialogTrigger>
const triggerButton = (
<Button
className={cn(
previewMode
? "text-foreground underline decoration-foreground/45 underline-offset-4 hover:decoration-foreground"
: "text-foreground/70 hover:text-foreground",
"transition-opacity duration-300 motion-reduce:transition-none",
inline && "h-auto justify-start p-0 text-left",
isVisible ? "opacity-100" : "pointer-events-none opacity-0",
)}
data-testid="identity-key-help-trigger"
onClick={previewMode ? onPreviewOpen : undefined}
tabIndex={isVisible ? 0 : -1}
type="button"
variant="link"
>
{previewMode ? "Learn how identity keys work" : "What’s an identity key?"}
</Button>
);
if (previewMode && onPreviewOpen) {
return inline ? (
triggerButton
) : (
<OnboardingFooter className="max-w-none">
{triggerButton}
</OnboardingFooter>
);
}
const trigger = <DialogTrigger asChild>{triggerButton}</DialogTrigger>;
return (
<Dialog>
{inline ? (
@@ -103,17 +114,7 @@ export function IdentityKeyHelpDialog({
className="mt-6 space-y-4 text-pretty text-base leading-7 text-[color:var(--buzz-onboarding-backup-ink)]"
>
<div>
<p>
Buzz will create a Nostr identity with two parts: a private key
that signs you in and a public key you can safely share. You can
find your public identity anytime in Buzz settings.
</p>
<p>
This identity belongs to you, not Buzz, and can move with you to
another device or compatible Nostr app. Because only you control
the private key, Buzz can’t reset or recover it. Keep a backup
somewhere safe, and never share it.
</p>
<IdentityKeyHelpBody />
</div>
</DialogDescription>
</div>
@@ -121,3 +122,35 @@ export function IdentityKeyHelpDialog({
</Dialog>
);
}
function IdentityKeyHelpBody() {
return (
<>
<p>
Buzz will create a Nostr identity with two parts: a private key that
signs you in and a public key you can safely share. You can find your
public identity anytime in Buzz settings.
</p>
<p>
This identity belongs to you, not Buzz, and can move with you to another
device or compatible Nostr app. Because only you control the private
key, Buzz can’t reset or recover it. Keep a backup somewhere safe, and
never share it.
</p>
</>
);
}
/** Production identity-key explainer content in the V3 onboarding card treatment. */
export function IdentityKeyHelpPreviewContent() {
return (
<>
<h1 className="text-title font-normal text-foreground">
What’s an identity key?
</h1>
<div className="mt-2 max-w-[500px] space-y-4 text-pretty text-base leading-7 text-foreground/80">
<IdentityKeyHelpBody />
</div>
</>
);
}

View File

@@ -82,7 +82,12 @@ export function KeySignInPreview({
<h1 className="text-title font-normal text-foreground">
Enter your private key
</h1>
<div className="mt-5 max-w-[440px] text-sm leading-6 text-foreground/80">
<div
className={cn(
"max-w-[440px] text-sm leading-6 text-foreground/80",
cardLayout ? "mt-2" : "mt-5",
)}
>
<p>
Paste your private key to sign in to Buzz. You can also use a{" "}
<button

View File

@@ -19,6 +19,7 @@ import {
} from "./EncryptedBackupCreator";
import { JoinPolicyNotice } from "./JoinPolicyNotice";
import { KeySignInPreview } from "./KeySignInPreview";
import { IdentityKeyHelpPreviewContent } from "./IdentityKeyHelpDialog";
import { LandingBees } from "./LandingBees";
import {
ONBOARDING_LANDING_CTA_CLASS,
@@ -760,6 +761,7 @@ export function OnboardingPreviewApp() {
direction="forward"
lockedBackupCreated={backupSession.created}
onNext={() => setPage("identity-key")}
onOpenIdentityKeyHelp={() => setPage("identity-key-help")}
onOpenPasswordBackup={() => setPage("backup-password")}
onShowOptions={() => setPage("backup-options")}
optionsExpanded
@@ -768,6 +770,21 @@ export function OnboardingPreviewApp() {
/>
</OnboardingPreviewStep>
);
} else if (page === "identity-key-help") {
content = (
<OnboardingPreviewStep
onBack={() => setPage("backup-options")}
testId="onboarding-preview-identity-key-help"
total={journey.totalSteps}
>
<OnboardingSlideTransition
className="flex min-h-0 w-full max-w-[560px] flex-col items-stretch justify-start text-left"
transitionKey="preview-identity-key-help"
>
<IdentityKeyHelpPreviewContent />
</OnboardingSlideTransition>
</OnboardingPreviewStep>
);
} else if (page === "backup-password") {
content = (
<BackupPasswordPreview

View File

@@ -20,7 +20,8 @@ export function OnboardingPreviewControls({
}) {
return (
<aside
className="fixed right-4 top-4 z-[100] flex w-[320px] max-w-[calc(100vw-2rem)] flex-col gap-3 rounded-2xl border border-foreground/15 bg-background/95 px-4 py-3 text-left shadow-lg backdrop-blur"
className="buzz-onboarding-neutral-theme fixed right-4 top-4 z-[100] flex w-[320px] max-w-[calc(100vw-2rem)] flex-col gap-3 rounded-2xl border border-foreground/15 bg-background/95 px-4 py-3 text-left shadow-lg backdrop-blur"
data-system-color-scheme="light"
data-testid="onboarding-preview-banner"
>
<div className="flex items-center gap-3">
@@ -35,7 +36,7 @@ export function OnboardingPreviewControls({
</div>
<Button
aria-label="Restart onboarding preview"
className="h-8 w-8 shrink-0"
className="h-8 w-8 shrink-0 text-foreground hover:text-foreground"
data-testid="onboarding-preview-restart"
onClick={onRestart}
size="icon"

View File

@@ -320,7 +320,12 @@ export function CommunityChoicePreview({
? "Join or create a community"
: "Buzz happens in communities"}
</h1>
<p className="mt-3 text-sm leading-6 text-foreground/80">
<p
className={cn(
"text-sm leading-6 text-foreground/80",
cardLayout ? "mt-2" : "mt-3",
)}
>
{includeExistingCommunity
? "Join with an invite, create your own community, or reconnect one you already have."
: "Communities are shared spaces where people and agents work together."}
@@ -420,7 +425,12 @@ export function CommunityEntryPreview({
>
<div className="w-full max-w-[620px]">
<h1 className="text-title font-normal">{heading}</h1>
<p className="mt-3 text-sm leading-6 text-foreground/80">
<p
className={cn(
"text-sm leading-6 text-foreground/80",
cardLayout ? "mt-2" : "mt-3",
)}
>
{route === "existing"
? "Enter the community URL or an invite link. Your role will be restored when you connect."
: previewVariant === "v3"

View File

@@ -75,7 +75,7 @@ export function OnboardingPreviewStep({
{cardLayout ? (
<Card
className={cn(
"flex h-[min(41.5rem,calc(100dvh-3rem))] w-full max-w-[47rem] flex-col overflow-hidden rounded-[2rem] bg-white px-6 pb-6 pt-[4.5rem] text-left shadow-lg sm:px-[7.5rem] [&_.buzz-onboarding-transition-content]:!text-left [&_.buzz-onboarding-transition-line]:justify-start [&_h1+p]:!mx-0 [&_h1+p]:!mt-2 [&_h1+p]:!text-left [&_h1+p]:!text-base [&_h1+p]:!leading-6 [&_h1]:!text-left [&_h1]:!text-2xl [&_h1]:!leading-8 [&_h1]:!text-foreground",
"flex h-[min(41.5rem,calc(100dvh-3rem))] w-full max-w-[47rem] flex-col overflow-hidden rounded-[2rem] bg-white px-6 pb-6 pt-[4.5rem] text-left shadow-lg [--buzz-onboarding-cta-label:#fff] sm:px-[7.5rem] [&_.buzz-onboarding-transition-content]:!text-left [&_.buzz-onboarding-transition-line]:justify-start [&_h1+p]:!mx-0 [&_h1+p]:!mt-2 [&_h1+p]:!text-left [&_h1+p]:!text-base [&_h1+p]:!leading-6 [&_h1]:!text-left [&_h1]:!text-2xl [&_h1]:!leading-8 [&_h1]:!text-foreground",
)}
data-testid="onboarding-preview-content-card"
ref={cardRef}