From 00521b6d87ebce88d5794ae295ae6e2b206c4642 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 25 Jul 2026 09:53:47 +0000 Subject: [PATCH] Fix verified badge wrapping over the handle in the profile header The profile header rendered `ProfileBadges` as an inline `View` inside the display name `Text`. On Android the space reserved for an inline view is converted with `PixelUtil.toPixelFromSP`, so the placeholder box is scaled by the device font scale on top of the scaling `ProfileBadges` already applies itself via `useNativeFontScale`. The reserved box therefore ends up larger than the badge it stands in for, which pushes the badge onto a line of its own and paints it below the name, over the start of the handle. The same conversion places the badge at `baseline - reservedHeight`, so it also floats above the text baseline. Render the badges as a sibling of the name in a baseline-aligned row instead, which is the pattern used everywhere else badges follow a name. Baseline alignment keeps the badge bottom on the name's baseline, matching how the inline view was positioned, and drops the iOS-only `marginTop` nudge that was compensating for the inline layout. Fixes #11238 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_0184o34rCfWuqtNWCJ9NeTrH --- src/screens/Profile/Header/DisplayName.tsx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/screens/Profile/Header/DisplayName.tsx b/src/screens/Profile/Header/DisplayName.tsx index 684a9fe53b..6bcf4a65a0 100644 --- a/src/screens/Profile/Header/DisplayName.tsx +++ b/src/screens/Profile/Header/DisplayName.tsx @@ -4,7 +4,7 @@ import {type AppBskyActorDefs, type ModerationDecision} from '@atproto/api' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' import {type Shadow} from '#/state/cache/types' -import {atoms as a, platform, useBreakpoints, useTheme} from '#/alf' +import {atoms as a, useBreakpoints, useTheme} from '#/alf' import {ProfileBadges} from '#/components/ProfileBadges' import {Text} from '#/components/Typography' @@ -18,15 +18,24 @@ export function ProfileHeaderDisplayName({ const t = useTheme() const {gtMobile} = useBreakpoints() + /* + * The badges are a sibling of the name rather than a child of it, because an + * inline view inside a `Text` is measured in SP on Android: the space + * reserved for it is multiplied by the device font scale a second time (once + * by `ProfileBadges` itself, then again by the platform), so the badge + * over-reserves, wraps onto a line of its own and gets painted over the + * handle below. Baseline alignment keeps the badge sitting on the name's + * baseline the way an inline view would. + */ return ( - + @@ -34,10 +43,8 @@ export function ProfileHeaderDisplayName({ profile.displayName || sanitizeHandle(profile.handle), moderation.ui('displayName'), )} - - - + ) }