Personal Hero
atroui/personal-heroFreeBlock
Narrow personal intro with status, lede links, and meta.
Install it
npx shadcn@latest add https://atroui.com/r/personal-hero.jsonSource
1const CONTENT = {2 name: "Your Name",3 tagline: "Designer-engineer building calm software.",4 location: "Somewhere on Earth",5 status: "shipping" as const,6 /** Set to your portrait path (e.g. `/me.jpg`) after install. */7 imageSrc: "",8 imageAlt: "",9 ledeLinks: [10 { label: "studio", href: "https://example.com" },11 { label: "writing", href: "/writing" },12 ],13 ledeBefore: "Shipping at ",14 ledeBetween: ", writing at ",15 ledeAfter: ".",16}1718type StatusKind = "shipping" | "working" | "dormant"1920const statusCopy: Record<StatusKind, string> = {21 shipping: "shipping",22 working: "working",23 dormant: "dormant",24}2526const statusDot: Record<StatusKind, string> = {27 shipping: "bg-emerald-500",28 working: "bg-muted-foreground",29 dormant: "bg-muted-foreground/50",30}3132export function PersonalHero({33 name = CONTENT.name,34 tagline = CONTENT.tagline,35 location = CONTENT.location,36 status = CONTENT.status,37 imageSrc = CONTENT.imageSrc,38 imageAlt = CONTENT.imageAlt,39 ledeLinks = CONTENT.ledeLinks,40 ledeBefore = CONTENT.ledeBefore,41 ledeBetween = CONTENT.ledeBetween,42 ledeAfter = CONTENT.ledeAfter,43 className,44}: {45 name?: string46 tagline?: string47 location?: string48 status?: StatusKind | null49 imageSrc?: string50 imageAlt?: string51 ledeLinks?: Array<{ label: string; href: string; external?: boolean }>52 ledeBefore?: string53 ledeBetween?: string54 ledeAfter?: string55 className?: string56} = {}) {57 const portrait = imageSrc.trim()5859 return (60 <section61 className={className ?? "mx-auto max-w-[640px] pt-14 sm:pt-20"}62 >63 <div className="flex items-start justify-between gap-4">64 <div className="flex min-w-0 items-start gap-4">65 {portrait ? (66 <img67 src={portrait}68 alt={imageAlt.trim() || name}69 width={72}70 height={72}71 className="mt-1 size-18 shrink-0 rounded-full border border-border-subtle bg-muted object-cover"72 />73 ) : null}74 <h1 className="min-w-0 pt-1 text-[2rem] font-medium tracking-tight text-foreground sm:text-[2.5rem]">75 {name}76 </h1>77 </div>78 {status ? <StatusDot status={status} /> : null}79 </div>8081 <p className="mt-5 max-w-[36ch] text-[15px] leading-[1.65] text-foreground">82 {tagline}83 </p>8485 {ledeLinks.length > 0 ? (86 <p className="mt-1.5 max-w-[42ch] text-[14px] leading-[1.65] text-muted-foreground">87 {ledeBefore}88// … truncated
Files it writes
More from atroui
All 82 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Analytics Provideranalytics-provider | atroui | Blocks | Free | 1 dep | |
| AR Portfolioar-portfolio | atroui | Blocks | Free | 1 dep | |
| Before / Afterbefore-after-slider | atroui | Blocks | Free | no deps | |
| Calendly Embedcalendly-embed | atroui | Blocks | Free | 1 dep | |
| Changelogchangelog | atroui | Blocks | Free | no deps | |
| Command Menucommand-menu | atroui | Blocks | Free | 4 deps | |
| Contact Formcontact-form | atroui | Blocks | Free | 2 deps | |
| Contextual CTAcontextual-cta | atroui | Blocks | Free | 2 deps |
