import type { ReactNode } from 'react' import { cn } from '../../lib/cn' import type { IconComponent } from '../../lib/types' import { Avatar } from '../Avatar' import { Surface } from '../Surface' import { Text } from '../Text' export interface ProfileCardStat { /** What is being counted — "Followers". */ label: string /** The figure, already formatted — "12.4k". */ value: ReactNode } export interface ProfileCardLink { /** Network or destination — "GitHub". The accessible name when the link shows only its icon. */ label: string href: string /** Glyph for the link. With one, the link shows the icon alone. */ icon?: IconComponent } export type ProfileCardVariant = 'full' | 'compact' export interface ProfileCardProps { /** Full name. Drives the avatar initials and the heading. */ name: string /** Job title, team or handle, under the name. */ role?: ReactNode /** Portrait URL. Without one the avatar shows initials. */ avatarSrc?: string /** Banner image URL across the top of the full card. Omitted, a soft accent band is drawn instead. */ coverSrc?: string /** A sentence or two about the person. Full variant only. */ bio?: ReactNode /** Counts in a row under the bio — posts, followers, projects. Full variant only. */ stats?: ProfileCardStat[] /** Social and web links. */ links?: ProfileCardLink[] /** The main action — Follow, Message. Usually a Button. */ primaryAction?: ReactNode /** The lesser action beside it. */ secondaryAction?: ReactNode /** full is the standalone card with cover, bio and stats; compact is a single row for lists. */ variant?: ProfileCardVariant /** Heading level for the name, so the card fits the page outline. */ headingLevel?: 'h2' | 'h3' | 'h4' /** Merged last, so it wins. */ className?: string } /** * A person, summarised: who they are, what they do, and what you can do next. * * The name is a real heading and the stats are a description list, because a * screen-reader user skimming a grid of people moves by heading and needs * "Followers, 12.4k" read as a pair rather than as two loose numbers. Links with * an icon show only the icon but keep the network name as their label. * * Compact drops the cover, bio and stats rather than shrinking them: in a list * the reader is choosing a person, and that needs a face, a name and an action. */ export function ProfileCard({ name, role, avatarSrc, coverSrc, bio, stats, links, primaryAction, secondaryAction, variant = 'full', headingLevel: Heading = 'h3', className, }: ProfileCardProps) { const actions = (primaryAction || secondaryAction) && (