Founder Avatar
atroui/founder-avatarFreeComponent
Circular founder portrait with editable CONTENT src.
Install it
npx shadcn@latest add https://atroui.com/r/founder-avatar.jsonSource
1import Image from "next/image"23import { getBrand } from "@/lib/brand"4import { cn } from "@/lib/utils"56/** Edit CONTENT to point at your founder portrait in /public. */7const CONTENT = {8 /** Path under public/, or absolute URL. Empty falls back to initials. */9 src: "",10 initials: "",11}1213const sizeClass = {14 sm: "size-8 text-[10px]",15 md: "size-9 text-[11px]",16 lg: "size-11 text-xs",17} as const1819export type FounderAvatarSize = keyof typeof sizeClass2021type FounderAvatarProps = {22 size?: FounderAvatarSize23 className?: string24 src?: string25 initials?: string26}2728function resolveSrc(src?: string): string {29 if (src?.trim()) return src.trim()30 if (CONTENT.src.trim()) return CONTENT.src.trim()31 if (typeof process !== "undefined" && process.env) {32 const fromEnv = process.env.NEXT_PUBLIC_FOUNDER_AVATAR?.trim()33 if (fromEnv) return fromEnv34 }35 return ""36}3738function resolveInitials(initials?: string): string {39 if (initials?.trim()) return initials.trim().slice(0, 2).toUpperCase()40 if (CONTENT.initials.trim()) return CONTENT.initials.trim().slice(0, 2).toUpperCase()41 const name = getBrand().name.trim()42 const parts = name.split(/\s+/).filter(Boolean)43 if (parts.length >= 2) {44 return `${parts[0]![0] ?? ""}${parts[1]![0] ?? ""}`.toUpperCase()45 }46 return (name.slice(0, 2) || "A").toUpperCase()47}4849/**50 * Circular founder portrait for signature rows.51 * Decorative - adjacent text carries the name.52 */53export function FounderAvatar({54 size = "sm",55 className,56 src,57 initials,58}: FounderAvatarProps) {59 const image = resolveSrc(src)60 const label = resolveInitials(initials)6162 return (63 <span64 aria-hidden65 className={cn(66 "relative inline-flex shrink-0 overflow-hidden rounded-full ring-1 ring-black/10 dark:ring-white/15",67 sizeClass[size],68 className69 )}70 >71 {image ? (72 <Image73 src={image}74 alt=""75 width={176}76 height={176}77 className="size-full object-cover object-[center_25%]"78 sizes="44px"79 />80 ) : (81 <span className="flex size-full items-center justify-center bg-brand/20 font-semibold tracking-wide text-brand">82 {label}83 </span>84 )}85 </span>86 )87}
What it pulls in
npm packages
Other registry items
Files it writes
More from atroui
All 82 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Breadcrumbsbreadcrumbs | atroui | Components | Free | 2 deps | |
| Buttonbutton | atroui | Components | Free | 2 deps | |
| Cardcard | atroui | Components | Free | no deps | |
| Fade Infade-in | atroui | Components | Free | 1 dep | |
| Form Selectform-select | atroui | Components | Free | 2 deps | |
| Logologo | atroui | Components | Free | no deps | |
| Mockup Framemockup-frame | atroui | Components | Free | no deps | |
| Proseprose | atroui | Components | Free | no deps |
