mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Polish community profile onboarding UI (#2088)
Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
@@ -26,6 +26,7 @@ import { relayClient } from "@/shared/api/relayClient";
|
||||
import type { AgentPersona } from "@/shared/api/types";
|
||||
import { cn } from "@/shared/lib/cn";
|
||||
import { Button } from "@/shared/ui/button";
|
||||
import { Input } from "@/shared/ui/input";
|
||||
import { MembershipDenied } from "./MembershipDenied";
|
||||
import { StartupWindowDragRegion } from "@/shared/ui/StartupWindowDragRegion";
|
||||
import {
|
||||
@@ -33,11 +34,7 @@ import {
|
||||
OnboardingChrome,
|
||||
} from "./OnboardingChrome";
|
||||
import { OnboardingFooter, OnboardingFooterProvider } from "./OnboardingFooter";
|
||||
import {
|
||||
ONBOARDING_KEY_FRAME_CLASS,
|
||||
ONBOARDING_KEY_ROW_CLASS,
|
||||
ONBOARDING_KEY_TEXT_CLASS,
|
||||
} from "./NsecMaskedDisplay";
|
||||
import { ONBOARDING_KEY_FRAME_CLASS } from "./NsecMaskedDisplay";
|
||||
|
||||
function isRelayMembershipDeniedError(error: unknown): boolean {
|
||||
if (!(error instanceof Error)) return false;
|
||||
@@ -92,7 +89,7 @@ function AvatarCircle({
|
||||
>
|
||||
{emojiAvatar ? (
|
||||
<span
|
||||
className="flex h-28 w-28 items-center justify-center overflow-hidden rounded-full text-5xl shadow-xs"
|
||||
className="flex h-36 w-36 items-center justify-center overflow-hidden rounded-full text-5xl shadow-xs"
|
||||
style={{ backgroundColor: emojiAvatar.color }}
|
||||
>
|
||||
{emojiAvatar.emoji}
|
||||
@@ -100,12 +97,12 @@ function AvatarCircle({
|
||||
) : hasAvatar ? (
|
||||
<ProfileAvatar
|
||||
avatarUrl={avatarUrl}
|
||||
className="h-28 w-28 rounded-full text-3xl"
|
||||
className="h-36 w-36 rounded-full text-4xl"
|
||||
label={previewName}
|
||||
/>
|
||||
) : (
|
||||
<span className="flex h-28 w-28 items-center justify-center rounded-full text-[var(--buzz-onboarding-backup-ink)] transition-colors group-hover:bg-white/25">
|
||||
<Plus className="h-8 w-8" aria-hidden="true" />
|
||||
<span className="flex h-36 w-36 items-center justify-center rounded-full bg-white/30 text-[var(--buzz-onboarding-backup-ink)] transition-colors group-hover:bg-white/40">
|
||||
<Plus className="h-7 w-7" aria-hidden="true" />
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
@@ -342,14 +339,11 @@ export function CommunityOnboardingFlow({
|
||||
<div
|
||||
className={cn(
|
||||
"relative w-full text-center",
|
||||
isProfileStage || isTeamStage
|
||||
? "buzz-onboarding-step-frame flex flex-col justify-center"
|
||||
: "flex min-h-dvh flex-col justify-center py-8",
|
||||
isProfileStage
|
||||
? "max-w-4xl"
|
||||
? "buzz-onboarding-step-frame flex max-w-[500px] flex-col justify-center"
|
||||
: isTeamStage
|
||||
? "max-w-[760px]"
|
||||
: "max-w-[560px]",
|
||||
? "buzz-onboarding-step-frame flex max-w-[760px] flex-col justify-center"
|
||||
: "flex min-h-dvh max-w-[560px] flex-col justify-center py-8",
|
||||
)}
|
||||
data-testid="community-onboarding-body"
|
||||
>
|
||||
@@ -417,46 +411,36 @@ export function CommunityOnboardingFlow({
|
||||
Add a name and avatar. They’ll show up on your messages,
|
||||
reactions, and agent handoffs.
|
||||
</p>
|
||||
<div className="mt-10 w-full max-w-4xl">
|
||||
<div
|
||||
className={ONBOARDING_KEY_FRAME_CLASS}
|
||||
data-testid="community-profile-key-frame"
|
||||
<div className="mt-8 flex w-full flex-col items-center">
|
||||
<AvatarCircle
|
||||
avatarUrl={avatarUrl}
|
||||
onClick={() => setIsAvatarEditorOpen(true)}
|
||||
previewName={displayName.trim() || "Your profile"}
|
||||
/>
|
||||
<label
|
||||
className="mt-7 block w-full max-w-[412px] text-left"
|
||||
htmlFor="community-display-name"
|
||||
>
|
||||
<div className={ONBOARDING_KEY_ROW_CLASS}>
|
||||
<AvatarCircle
|
||||
avatarUrl={avatarUrl}
|
||||
onClick={() => setIsAvatarEditorOpen(true)}
|
||||
previewName={displayName.trim() || "Your profile"}
|
||||
/>
|
||||
<label
|
||||
className="min-w-0 flex-1"
|
||||
htmlFor="community-display-name"
|
||||
>
|
||||
<span className="sr-only">Your name</span>
|
||||
<input
|
||||
aria-label="Community display name"
|
||||
autoCapitalize="words"
|
||||
autoComplete="name"
|
||||
autoCorrect="off"
|
||||
className={cn(
|
||||
ONBOARDING_KEY_TEXT_CLASS,
|
||||
"border-0 bg-transparent p-0 shadow-none outline-none placeholder:text-[var(--buzz-onboarding-backup-ink)] placeholder:opacity-40 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
||||
)}
|
||||
data-testid="community-profile-name-key"
|
||||
disabled={isPending || isUploadingAvatar}
|
||||
id="community-display-name"
|
||||
onChange={(event) =>
|
||||
setDisplayName(event.target.value)
|
||||
}
|
||||
placeholder="First and last name"
|
||||
ref={nameInputRef}
|
||||
spellCheck={false}
|
||||
type="text"
|
||||
value={displayName}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<span className="mb-2 block pl-4 text-sm text-foreground">
|
||||
Your name
|
||||
</span>
|
||||
<Input
|
||||
aria-label="Community display name"
|
||||
autoCapitalize="words"
|
||||
autoComplete="name"
|
||||
autoCorrect="off"
|
||||
className="h-14 rounded-2xl border-[color:rgb(113_113_6_/_0.28)] bg-white/95 px-5 text-sm shadow-none placeholder:text-muted-foreground/60 focus-visible:ring-1 focus-visible:ring-[var(--buzz-onboarding-backup-ink)] md:text-sm"
|
||||
data-testid="community-profile-name-key"
|
||||
disabled={isPending || isUploadingAvatar}
|
||||
id="community-display-name"
|
||||
onChange={(event) => setDisplayName(event.target.value)}
|
||||
placeholder="First and last name"
|
||||
ref={nameInputRef}
|
||||
spellCheck={false}
|
||||
type="text"
|
||||
value={displayName}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
{transaction.error ? (
|
||||
<p className="mt-4 text-sm text-destructive">
|
||||
|
||||
@@ -997,43 +997,30 @@ test("connected first-community profile step cannot discard resumable onboarding
|
||||
const centeredInUsableLaneY =
|
||||
chromeOffset + (viewport.height - chromeOffset - footerOffset) / 2;
|
||||
expect(Math.abs(profileMainCenterY - centeredInUsableLaneY)).toBeLessThan(32);
|
||||
const keyFrame = page.getByTestId("community-profile-key-frame");
|
||||
const nameKey = page.getByTestId("community-profile-name-key");
|
||||
await expect(keyFrame).toBeVisible();
|
||||
const avatarButton = page.getByTestId("community-avatar-open");
|
||||
await expect(nameKey).toBeVisible();
|
||||
const keyFrameBox = await keyFrame.boundingBox();
|
||||
expect(keyFrameBox?.width).toBeGreaterThan(700);
|
||||
const keyFrameStyles = await keyFrame.evaluate((element) => {
|
||||
await expect(avatarButton).toBeVisible();
|
||||
const nameKeyBox = await nameKey.boundingBox();
|
||||
const avatarButtonBox = await avatarButton.boundingBox();
|
||||
expect(nameKeyBox?.width).toBeGreaterThan(380);
|
||||
expect(avatarButtonBox?.width).toBe(144);
|
||||
const nameKeyStyles = await nameKey.evaluate((element) => {
|
||||
const styles = window.getComputedStyle(element);
|
||||
return {
|
||||
backgroundColor: styles.backgroundColor,
|
||||
borderRadius: styles.borderRadius,
|
||||
fontSize: styles.fontSize,
|
||||
};
|
||||
});
|
||||
expect(keyFrameStyles.backgroundColor).toMatch(/(0\.5\)|\/ 0\.5\))/);
|
||||
expect(keyFrameStyles.borderRadius).toBe("12px");
|
||||
await expect
|
||||
.poll(() =>
|
||||
nameKey.evaluate((element) => {
|
||||
const styles = window.getComputedStyle(element);
|
||||
return {
|
||||
color: styles.color,
|
||||
fontFamily: styles.fontFamily,
|
||||
fontSize: styles.fontSize,
|
||||
};
|
||||
}),
|
||||
)
|
||||
.toMatchObject({
|
||||
color: "rgb(113, 113, 6)",
|
||||
fontSize: "36px",
|
||||
});
|
||||
expect(
|
||||
(
|
||||
await nameKey.evaluate((element) =>
|
||||
window.getComputedStyle(element).fontFamily.toLowerCase(),
|
||||
)
|
||||
).includes("mono"),
|
||||
).toBe(true);
|
||||
expect(nameKeyStyles.backgroundColor).toMatch(
|
||||
/^(rgba\(255, 255, 255, 0\.95\)|oklab\(.+ \/ 0\.95\))$/,
|
||||
);
|
||||
expect(nameKeyStyles).toMatchObject({
|
||||
borderRadius: "16px",
|
||||
fontSize: "14px",
|
||||
});
|
||||
await expect(page.getByText("Your name", { exact: true })).toBeVisible();
|
||||
await expect(page.getByTestId("community-profile-next")).toHaveText("Next");
|
||||
await expect(page.getByTestId("community-profile-next")).toBeDisabled();
|
||||
await expect(page.getByTestId("community-profile-back")).toHaveCount(0);
|
||||
|
||||
Reference in New Issue
Block a user