Team Grid
betaA grid of people for an About page, each with an avatar, name, role, a line about them, and icon links, with an optional cell for open roles.
Built from Avatar, Button Variants, and Tooltip.
Preview
under a headline
The team
The people who build and run the product.
twelve people, no open roles
names and roles only
Priya Raman
Founder
Tomás Okafor
Engineering lead
Elin Sato
Design lead
Marcus Bell
Head of operations
long names and roles
one person, with open roles
narrow container: one column
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the website component. It also adds every component it uses. Its own files go in your
componentsfolder, and they are yours to edit.npx shadcn@latest add @txbrendan/team-grid
Use it for
- The team section of an About page, under a Headline.
- Give each person a `role` and, if you like, a one-line `bio`. Keep every bio about the same length, so the tiles line up.
- Add `links` for a profile, a site, or an email. Each one is an icon button, and its `label` shows in a tooltip.
- Set `openRoles` to end the grid with a cell that links to your careers page.
- Pass your router's link through `renderLink`, like next/link, so links stay client-side.
- Pass a photo URL as `avatar`. Without one, the initials show in a tint the name picks.
Avoid it for
- A list of people inside an app, like members or invites. Use a table or Avatar Stack.
- Long bios. Keep it to one line, and link to a full profile.
- Quotes from people. Use Testimonial Wall.
- More than about sixteen people. Show the leads, and link to the rest.
Props
- people
The people, in the order to show them. Two people may share a name. avatar is a photo URL. Each link's label shows in its tooltip, and screen readers hear it with the person's name.
{ name: string; role?: ReactNode; bio?: ReactNode; avatar?: string; links?: { href: string; label: string; icon: ReactNode }[] }[] · default []
- openRoles
Adds a last cell with a button to your open roles. title defaults to "We're hiring", and label, the button's words, to "See open roles".
{ href: string; title?: ReactNode; description?: ReactNode; label?: string }
- renderLink
Draws each link. Spread the props onto your router's link: (props) => <Link {...props} />. Return the element itself, so its tooltip can attach.
(props: TeamGridLinkProps) => ReactNode · default a plain <a>
- className
Extra classes on the root, which holds the container query. One column when narrow, two from 28rem, three from 36rem, four from 56rem. A count like six, which fills rows of three but not four, stays at three.
string
| Prop | Type | Default | What it does |
|---|---|---|---|
| people | { name: string; role?: ReactNode; bio?: ReactNode; avatar?: string; links?: { href: string; label: string; icon: ReactNode }[] }[] | [] | The people, in the order to show them. Two people may share a name. avatar is a photo URL. Each link's label shows in its tooltip, and screen readers hear it with the person's name. |
| openRoles | { href: string; title?: ReactNode; description?: ReactNode; label?: string } | - | Adds a last cell with a button to your open roles. title defaults to "We're hiring", and label, the button's words, to "See open roles". |
| renderLink | (props: TeamGridLinkProps) => ReactNode | a plain <a> | Draws each link. Spread the props onto your router's link: (props) => <Link {...props} />. Return the element itself, so its tooltip can attach. |
| className | string | - | Extra classes on the root, which holds the container query. One column when narrow, two from 28rem, three from 36rem, four from 56rem. A count like six, which fills rows of three but not four, stays at three. |
Accessibility
- The people are a list. Each name is an h3, so put the grid under an h2, like a Headline.
- The avatar is hidden from screen readers, since the name is written beside it.
- Each icon link is named by its label and the person, like "Website, Priya Raman". Its tooltip shows the label on hover and on focus.
- Icon links grow to 44px on touch screens.
- In forced colors each tile gets a border, since its fill is painted away.
Examples
People with links, and a cell for open roles
<TeamGrid
people={[
{
name: "Priya Raman",
role: "Founder",
bio: "Leads product and design.",
links: [
{ href: "/team/priya", label: "Profile", icon: <UserRound /> },
{ href: "mailto:priya@example.com", label: "Email", icon: <Mail /> },
],
},
{ name: "Tomás Okafor", role: "Engineering lead", bio: "Runs the platform team." },
{ name: "Elin Sato", role: "Support lead" },
]}
openRoles={{ href: "/careers", description: "Design, support, and engineering." }}
/>Under a headline, with next/link
<section className="flex flex-col gap-12">
<Headline title="The team" description="The people who build and run the product." />
<TeamGrid
people={[{ name: "Priya Raman", role: "Founder" }, { name: "Tomás Okafor", role: "Engineering lead" }]}
renderLink={(props) => <Link {...props} />}
/>
</section>