fix(desktop): restore the profile passport icon

Keep the ID-card control on the profile hero so agents, people, and self profiles can open the passport after the action-tile merge.

Signed-off-by: Thomas Petersen <thomasp@squareup.com>
This commit is contained in:
Thomas Petersen
2026-08-19 10:43:40 -04:00
parent 71b753075d
commit 4d4d218be9
2 changed files with 57 additions and 83 deletions

View File

@@ -1,5 +1,5 @@
import * as React from "react";
import { ChevronDown, ChevronUp, Pencil } from "lucide-react";
import { ChevronDown, ChevronUp, IdCard, Pencil } from "lucide-react";
import { useAgentWorking } from "@/features/agents/agentWorkingSignal";
import {
@@ -38,7 +38,6 @@ import { PassportDialog } from "@/features/profile/ui/PassportDialog";
import {
ProfilePersonaPrimaryActions,
ProfilePrimaryActions,
ProfileSelfPrimaryActions,
} from "@/features/profile/ui/UserProfilePrimaryActions";
import { StatusEmoji } from "@/features/user-status/ui/StatusEmoji";
import { BotIdenticon } from "@/features/messages/ui/BotIdenticon";
@@ -51,6 +50,7 @@ import { cn } from "@/shared/lib/cn";
import { observeElementBlockSize } from "@/shared/layout/observeElementBlockSize";
import { useMeasuredCssVariable } from "@/shared/layout/useMeasuredCssVariable";
import { Badge } from "@/shared/ui/badge";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/shared/ui/tooltip";
export { AgentInstructionsFocusedView } from "@/features/profile/ui/UserProfilePanelAgentDetails";
@@ -414,6 +414,7 @@ export function ProfileSummaryView({
displayName={displayName}
isBot={isBot}
onEditAgent={canEditAgent ? handleEditAgent : undefined}
onOpenPassport={onOpenPassport}
presenceStatus={avatarStatus}
profile={profile}
userStatus={userStatus}
@@ -434,7 +435,6 @@ export function ProfileSummaryView({
className={primaryActionsMotionClassName}
concealed={primaryActionsConcealed}
followMutation={followMutation}
onOpenPassport={onOpenPassport}
agentActionDisabled={isAgentActionPending}
agentActionLabel={
isOwner === true && managedAgent
@@ -468,13 +468,6 @@ export function ProfileSummaryView({
unfollowMutation={unfollowMutation}
wavePending={isWavePending}
/>
) : isSelf && onOpenPassport ? (
<ProfileSelfPrimaryActions
actionGroupRef={setPrimaryActionsElement}
className={primaryActionsMotionClassName}
concealed={primaryActionsConcealed}
onOpenPassport={onOpenPassport}
/>
) : null}
{/* Tab-independent restart badge — visible on every tab so the user
@@ -630,6 +623,7 @@ function ProfileHero({
displayName,
isBot,
onEditAgent,
onOpenPassport,
presenceStatus,
profile,
userStatus,
@@ -637,6 +631,7 @@ function ProfileHero({
displayName: string;
isBot: boolean;
onEditAgent?: () => void;
onOpenPassport?: () => void;
presenceStatus: "online" | "away" | "offline" | undefined;
profile: ProfileSummaryViewProps["profile"];
userStatus: ProfileSummaryViewProps["userStatus"];
@@ -686,37 +681,60 @@ function ProfileHero({
</MaskedAvatarBadgeFrame>
<div className="flex flex-col items-center gap-1">
{onEditAgent ? (
<h3 className="max-w-full" data-testid="user-profile-name-row">
<button
aria-label={`Edit ${displayName}`}
className="group relative flex max-w-full items-center justify-center gap-2 rounded-lg px-1 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
data-testid="user-profile-edit-agent"
onClick={onEditAgent}
type="button"
<div className="flex max-w-full items-center justify-center gap-1.5">
{onOpenPassport ? (
<Tooltip>
<TooltipTrigger asChild>
<button
aria-label="View passport"
className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-muted/60 text-foreground transition-colors hover:bg-muted/80 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
data-testid="user-profile-passport"
onClick={onOpenPassport}
type="button"
>
<IdCard className="h-3.5 w-3.5" />
</button>
</TooltipTrigger>
<TooltipContent align="center" side="top">
Passport
</TooltipContent>
</Tooltip>
) : null}
{onEditAgent ? (
<h3
className="min-w-0 max-w-full"
data-testid="user-profile-name-row"
>
<span className="truncate text-xl font-semibold tracking-tight">
{displayName}
</span>
{botIndicator}
<span
aria-hidden="true"
className="pointer-events-none absolute top-1/2 left-full ml-1 -translate-y-1/2 text-muted-foreground opacity-0 transition-[color,opacity] duration-150 ease-out group-hover:text-foreground group-hover:opacity-100 group-focus-visible:opacity-100"
data-testid="user-profile-edit-agent-icon"
<button
aria-label={`Edit ${displayName}`}
className="group relative flex max-w-full items-center justify-center gap-2 rounded-lg px-1 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
data-testid="user-profile-edit-agent"
onClick={onEditAgent}
type="button"
>
<Pencil className="h-4 w-4" />
</span>
</button>
</h3>
) : (
<h3
className="flex max-w-full items-center justify-center gap-2 text-xl font-semibold tracking-tight"
data-testid="user-profile-name-row"
>
<span className="truncate">{displayName}</span>
{botIndicator}
</h3>
)}
<span className="truncate text-xl font-semibold tracking-tight">
{displayName}
</span>
{botIndicator}
<span
aria-hidden="true"
className="pointer-events-none absolute top-1/2 left-full ml-1 -translate-y-1/2 text-muted-foreground opacity-0 transition-[color,opacity] duration-150 ease-out group-hover:text-foreground group-hover:opacity-100 group-focus-visible:opacity-100"
data-testid="user-profile-edit-agent-icon"
>
<Pencil className="h-4 w-4" />
</span>
</button>
</h3>
) : (
<h3
className="flex min-w-0 max-w-full items-center justify-center gap-2 text-xl font-semibold tracking-tight"
data-testid="user-profile-name-row"
>
<span className="truncate">{displayName}</span>
{botIndicator}
</h3>
)}
</div>
{profile?.about?.trim() ? (
<ProfileHeroDescription

View File

@@ -3,7 +3,6 @@ import type { ReactNode, Ref } from "react";
import {
Hand,
Headphones,
IdCard,
MessageSquare,
Play,
RefreshCw,
@@ -38,7 +37,6 @@ export function ProfilePrimaryActions({
onAgentRestart,
onHuddle,
onMessage,
onOpenPassport,
onWave,
pubkey,
unfollowMutation,
@@ -58,7 +56,6 @@ export function ProfilePrimaryActions({
onAgentRestart?: () => void;
onHuddle?: () => void;
onMessage?: () => void;
onOpenPassport?: () => void;
onWave?: () => void;
pubkey: string;
unfollowMutation: ReturnType<typeof useUnfollowMutation>;
@@ -81,7 +78,6 @@ export function ProfilePrimaryActions({
onWave !== undefined ||
onMessage !== undefined ||
onHuddle !== undefined ||
onOpenPassport !== undefined ||
(onAgentPrimaryAction !== undefined && agentActionLabel !== undefined) ||
onAgentRestart !== undefined;
@@ -144,14 +140,6 @@ export function ProfilePrimaryActions({
testId="user-profile-wave"
/>
) : null}
{onOpenPassport ? (
<ProfileActionTile
icon={IdCard}
label="Passport"
onClick={onOpenPassport}
testId="user-profile-passport"
/>
) : null}
{showFollowAction ? (
<ProfileActionTile
active={isFollowing}
@@ -196,38 +184,6 @@ export function ProfilePersonaPrimaryActions({
);
}
/**
* Actions when viewing your own profile — today just the Passport. A
* dedicated row so self profiles gain identity actions without the
* follow/message set meant for other people.
*/
export function ProfileSelfPrimaryActions({
actionGroupRef,
className,
concealed = false,
onOpenPassport,
}: {
actionGroupRef?: Ref<HTMLDivElement>;
className?: string;
concealed?: boolean;
onOpenPassport: () => void;
}) {
return (
<ProfileActionGroup
className={className}
concealed={concealed}
ref={actionGroupRef}
>
<ProfileActionTile
icon={IdCard}
label="Passport"
onClick={onOpenPassport}
testId="user-profile-passport"
/>
</ProfileActionGroup>
);
}
function ProfileActionGroup({
children,
className,