Author Card
alphav0.2.0Person identity card — avatar, name, role, optional bio, optionally clickable.
Context
Surfaces authorship context next to a piece of content: news article sidebars, blog post bylines, doc page authors, team listings, comment headers, contributor cards. Sized for sidebars (works at ~280px and up). Avatar is image-or-icon-fallback; the whole card optionally renders as a link via polymorphic root + href. Same visual rhythm as newsletter-signup / category-cloud / filter-bar — composes cleanly in the same sidebar.
Installation
pnpm dlx shadcn@latest initpnpm dlx shadcn@latest add @ilinxa/author-cardAdd -fixtures for dummy data:
pnpm dlx shadcn@latest add @ilinxa/author-card-fixturesCLI can't resolve @ilinxa? The namespace is listed in the official shadcn registry directory, so current CLIs need no configuration. If yours can't resolve it (older or pinned versions, self-hosted mirrors), register it manually in components.json:
"registries": {
"@ilinxa": "https://ui.ilinxa.com/r/{name}.json"
}Preview
About the author
Anonymous Contributor
Guest Writer
Writes occasionally about local environmental stories.
Demo source
"use client"; import { Users } from "lucide-react";import { Tabs, TabsContent, TabsTrigger } from "@/components/ui/tabs";import { SwipeTabsList } from "@/components/site/swipe-tabs-list";import { AuthorCard } from "./author-card";import { AUTHOR_CARD_DUMMY } from "./dummy-data"; export default function AuthorCardDemo() { return ( <Tabs defaultValue="default" className="w-full"> <SwipeTabsList> <TabsTrigger value="default">Default</TabsTrigger> <TabsTrigger value="with-image">With image</TabsTrigger> <TabsTrigger value="clickable">Clickable</TabsTrigger> <TabsTrigger value="muted">Muted tone</TabsTrigger> <TabsTrigger value="i18n">Turkish content</TabsTrigger> </SwipeTabsList> <TabsContent value="default" className="mt-6 max-w-md"> <AuthorCard {...AUTHOR_CARD_DUMMY.withoutImage} /> </TabsContent> <TabsContent value="with-image" className="mt-6 max-w-md"> <AuthorCard {...AUTHOR_CARD_DUMMY.withImage} /> </TabsContent> <TabsContent value="clickable" className="mt-6 max-w-md"> <AuthorCard {...AUTHOR_CARD_DUMMY.clickable} /> <p className="mt-3 text-xs text-muted-foreground"> Hover the card or focus it with the keyboard — the whole surface is a link to <code>/team/daniel-park</code>. </p> </TabsContent> <TabsContent value="muted" className="mt-6 max-w-md"> <AuthorCard {...AUTHOR_CARD_DUMMY.collective} tone="muted" fallbackIcon={Users} /> </TabsContent> <TabsContent value="i18n" className="mt-6 max-w-md"> <AuthorCard {...AUTHOR_CARD_DUMMY.turkish} /> </TabsContent> </Tabs> );} Usage
When to use
A small "person identity" block — avatar, name, role, optional bio — to surface authorship context next to a piece of content. Reach for it on news article sidebars, blog post bylines, doc page authors, team listings, comment headers, contributor cards.
It's a single card, not a list. Sized for sidebars (works at ~280px and up). Optionally clickable as a whole — pass href+ your router's link component to make the entire surface navigate.
Basic example
import { AuthorCard } from "@/components/author-card"
export function Example() {
return (
<AuthorCard
name="Maya Chen"
role="Senior Editor"
bio="Specializes in sustainable urbanism and environmental journalism."
imageSrc="/authors/maya.jpg"
imageAlt="Maya Chen"
/>
)
}Clickable card
Pass href to make the whole surface navigate. By default the root renders as a native <a>; pass linkComponent for router-aware links.
import Link from "next/link"
import { AuthorCard } from "@/components/author-card"
<AuthorCard
name="Daniel Park"
role="Product Designer"
bio="Currently designing onboarding flows."
imageSrc="/team/daniel.jpg"
href="/team/daniel-park"
linkComponent={Link}
/>No image — fallback icon
When imageSrc is omitted, a tinted circle with a Lucide User icon renders. Override the icon via fallbackIcon for non-person bylines (e.g. Users for collectives).
import { Users } from "lucide-react"
<AuthorCard
name="The Editorial Team"
role="Collective"
bio="Reporting from across the newsroom."
fallbackIcon={Users}
tone="muted"
/>i18n
All visible chrome strings live in labels; English defaults ship in AUTHOR_CARD_DEFAULT_LABELS. The card text content (name, role, bio) is consumer data — pass localized strings directly.
<AuthorCard
name="Aylin Demir"
role="Kıdemli Editör"
bio="Sürdürülebilir şehircilik ve çevre konularında uzmanlaşmış."
labels={{ heading: "Yazar Hakkında" }}
/>Notes
- The component is exported as
React.memo. For memoization to hold, pass stable references forlinkComponent/fallbackIcon(don't create them inline on every render). - The avatar image uses
loading="lazy". Brokensrcshows the browser's default broken-image icon — ensure URLs are valid (consumer responsibility). - When the card is clickable, the accessible name is the author's name (via
aria-labelledby). The heading text reads as a decorative label. - Use
headingAsto fit the card under your page's landmark structure — most sidebars wanth3(the default).
Features
- Image-or-icon-fallback avatar
- 3 tones (primary / accent / muted)
- Polymorphic root — pass href + linkComponent to make the whole card a link
- Custom fallback icon via fallbackIcon prop (e.g. Users for collectives)
- Configurable heading level (h2 / h3 / h4)
- i18n via labels prop with English defaults
- Memoized; SSR-safe; lazy-loaded image