fix: profile bio

This commit is contained in:
gosangam
2026-08-08 00:49:39 +05:30
parent 9b7758da99
commit ce373e3e03
2 changed files with 90 additions and 74 deletions
+60 -72
View File
@@ -1,14 +1,9 @@
"use client";
/**
* ProfileHeader — the header at the top of /u/me and /u/[handle].
*
* Layout is two stacked blocks:
* 1. An identity ROW — avatar on the left, with display name, @handle, and
* the posts/followers/following stat line stacked to its right.
* 2. Full-width rows beneath it — the bio, then the action row. Both span the
* avatar's width too, so a 200-character bio gets the whole column rather
* than the narrow gutter beside the avatar.
* ProfileHeader — Instagram-style centered header used at the top of
* /u/me and /u/[handle]. Avatar, display name, @handle, a single stat
* line, and an action row.
*
* The action row hosts:
* • "Edit profile" link — only on the owner's own profile (via the
@@ -95,8 +90,8 @@ export function ProfileHeader({
* on the avatar; tapping it explains the mark. */
isDirectDisciple?: boolean;
/** The profile's bio. Plain text — `@handle` mentions are linkified on
* render. Rendered left-aligned across the full column below the centred
* identity block; omitted entirely when empty. */
* render. Sits between the stat line and the action buttons, centred like
* the rest of the header. Omitted entirely when empty. */
bio?: string | null;
}) {
// Owner affordances ride on `editHref`; the follow-action row rides on
@@ -127,77 +122,70 @@ export function ProfileHeader({
return (
<>
<header className="flex flex-col gap-4 pt-4 pb-6 sm:pt-6 sm:pb-8">
{/* Identity row — avatar on the left, name + handle + stats stacked to
its right. The bio and action row sit below at full width, so long
prose gets the whole column instead of a narrow gutter. */}
<div className="flex items-center gap-4 sm:gap-6">
{/* Avatar, with Śrīla Prabhupāda's portrait tucked into the
lower-right for his direct disciples (verification-tick
placement). */}
<div className="relative shrink-0">
<UserAvatar
src={avatarURL}
name={name}
className="size-20 sm:size-28"
textClassName="text-3xl"
interactive
onClick={avatarURL ? () => setZoomOpen(true) : undefined}
ariaLabel={`View ${name}'s profile picture`}
/>
{isDirectDisciple ? (
<DiscipleBadge className="absolute -bottom-0.5 -right-0.5" />
) : null}
</div>
{/* min-w-0 lets the long-name truncation actually kick in — without
it the flex child refuses to shrink below its content width. */}
<div className="min-w-0 flex-1">
<h1 className="font-(family-name:--font-title) font-semibold text-xl sm:text-2xl text-foreground leading-tight truncate">
<header className="flex flex-col items-center text-center gap-4 pt-4 pb-6 sm:pt-6 sm:pb-8">
{/* Avatar, with Śrīla Prabhupāda's portrait tucked into the lower-right
for his direct disciples (verification-tick placement). */}
<div className="relative">
<UserAvatar
src={avatarURL}
name={name}
className="size-24 sm:size-28"
textClassName="text-3xl"
interactive
onClick={avatarURL ? () => setZoomOpen(true) : undefined}
ariaLabel={`View ${name}'s profile picture`}
/>
{isDirectDisciple ? (
<DiscipleBadge className="absolute -bottom-0.5 -right-0.5" />
) : null}
</div>
<div className="space-y-2">
<div className="space-y-1">
<h1 className="font-(family-name:--font-title) font-semibold text-xl sm:text-2xl text-foreground leading-tight">
{name}
</h1>
<p className="mt-0.5 text-sm text-muted-foreground truncate">
@{handle}
</p>
<p className="text-sm text-muted-foreground">@{handle}</p>
</div>
{/* Stat line: posts · followers · following */}
<div className="mt-3 flex items-center gap-5 sm:gap-7">
{typeof postCount === "number" ? (
<Stat n={postCount} label={postCount === 1 ? "post" : "posts"} />
) : null}
{showCounts ? (
<>
<Stat
n={followers}
label="followers"
onClick={
interactiveCounts
? () => setFollowList("followers")
: undefined
}
/>
<Stat
n={following}
label="following"
onClick={
interactiveCounts
? () => setFollowList("following")
: undefined
}
/>
</>
) : null}
</div>
{/* Stat line: posts · followers · following */}
<div className="flex items-center justify-center gap-5 sm:gap-7 pt-1 my-4">
{typeof postCount === "number" ? (
<Stat n={postCount} label={postCount === 1 ? "post" : "posts"} />
) : null}
{showCounts ? (
<>
<Stat
n={followers}
label="followers"
onClick={
interactiveCounts
? () => setFollowList("followers")
: undefined
}
/>
<Stat
n={following}
label="following"
onClick={
interactiveCounts
? () => setFollowList("following")
: undefined
}
/>
</>
) : null}
</div>
</div>
{/* Bio — spans the full column beneath the avatar AND the name/stats
block, so a 200-character bio wraps across the whole width instead
of being squeezed into the column beside the avatar. */}
{/* Bio — between the stats and the action buttons, centred to match the
rest of the header. `self-stretch` overrides the header's
`items-center` so the text box spans the full column and each
wrapped line centres against the same axis as the name and stats
(without it the box would shrink to its content and centre oddly). */}
{bio?.trim() ? (
<MentionText
text={bio.trim()}
className="text-sm sm:text-[15px] leading-relaxed text-foreground"
className="self-stretch text-center text-sm sm:text-[15px] leading-relaxed text-foreground"
/>
) : null}