Editorial

Person

Credit for a person built on Item, Avatar and Media: row, stack or profile layouts with an avatar or portrait, name, role and bio. Byline density credits one person; dense suits member lists.

The source comes with full access.

One payment of $149 ($49 for now) opens the source right here and lets the CLI install every paid component, with lifetime updates.

Installation

pnpm dlx shadcn add @01orbital/person
npx shadcn add @01orbital/person
yarn shadcn add @01orbital/person
bunx --bun shadcn add @01orbital/person

Part of the 01orbital library. With a license, put ORBITAL_TOKEN in .env.local and the same command installs it (licensed install, pricing).

It lands at components/editorial/person.tsx, as source you own and edit.

Usage

import {
  Person,
  PersonAvatar,
  PersonBio,
  PersonContent,
  PersonName,
  PersonPortrait,
  PersonRole,
} from "@/components/editorial/person"
import { AvatarImage } from "@/components/ui/avatar"

const PEOPLE = [
  {
    name: "Mara Castellanos",
    role: "Co-founder, CEO",
    image: "https://01orbital.dev/art/kit/celestograph-61495-roan-6b.png",
  },
  {
    name: "Priya Raman",
    role: "Head of design",
    image: "https://01orbital.dev/art/kit/celestograph-9963-bloom-1b.png",
  },
  {
    name: "Teodor Lindqvist",
    role: "Co-founder, CTO",
    bio: "Builds the tools our team uses every day, from the first prototype to the components we ship.",
    image: "https://01orbital.dev/art/kit/celestograph-61495-gesso-6b.png",
  },
] as const

export default function PersonDemo() {
  return (
    <div className="grid w-full max-w-3xl items-start gap-10 sm:grid-cols-2">
      <Person>
        <PersonAvatar>
          <AvatarImage src={PEOPLE[0].image} alt="" />
        </PersonAvatar>
        <PersonContent>
          <PersonName>{PEOPLE[0].name}</PersonName>
          <PersonRole>{PEOPLE[0].role}</PersonRole>
        </PersonContent>
      </Person>
      <Person variant="stack">
        <PersonPortrait shape="circle" className="size-40">
          <img src={PEOPLE[1].image} alt="" loading="lazy" />
        </PersonPortrait>
        <PersonContent>
          <PersonName>{PEOPLE[1].name}</PersonName>
          <PersonRole>{PEOPLE[1].role}</PersonRole>
        </PersonContent>
      </Person>
      <Person variant="profile" className="sm:col-span-2">
        <PersonPortrait className="w-52">
          <img src={PEOPLE[2].image} alt="" loading="lazy" />
        </PersonPortrait>
        <PersonContent>
          <PersonName>{PEOPLE[2].name}</PersonName>
          <PersonRole>{PEOPLE[2].role}</PersonRole>
          <PersonBio>{PEOPLE[2].bio}</PersonBio>
        </PersonContent>
      </Person>
    </div>
  )
}

Anatomy

Person is built from 7 parts. In the example they nest like this:

Person
├─ PersonAvatar
├─ PersonContent
│  ├─ PersonName
│  ├─ PersonRole
│  └─ PersonBio
└─ PersonPortrait
  • Person: A person's picture, name and role, for a byline under a quote, a team card or a staff list. Put a PersonAvatar or PersonPortrait and a PersonContent inside. It renders a <div>; pass render={<li />} when it sits in a list.
  • PersonAvatar: The round picture frame in Person: 56px, or 40px in a dense person. Put an AvatarImage or artwork inside and let it fill the frame, which clips it to the circle. The frame sets the size, so change it with className.
  • PersonContent: The person's text: put a PersonName, a PersonRole and an optional PersonBio inside. In a profile person it wraps below the portrait when less than 16rem is left beside it.
  • PersonName: The person's name, in semibold text. A long name wraps, not cut off.
  • PersonRole: The person's role or job title, in muted text below PersonName.
  • PersonBio: A short paragraph about the person, in muted text, set a little apart below PersonRole. It shows in full, never cut off.
  • PersonPortrait: A larger picture of the person, for team cards and profiles. It is as wide as its container, in a 3:4 frame with a hairline outline. An <img> placed directly inside fills and crops to the frame.

API reference

Person

A person's picture, name and role, for a byline under a quote, a team card or a staff list. Put a PersonAvatar or PersonPortrait and a PersonContent inside. It renders a <div>; pass render={<li />} when it sits in a list.

row sets the picture beside the text and stack centers the text below it. profile sets the text beside a PersonPortrait when both fit and below it when they don't. The portrait is full width unless you give it a width, so by default the text sits below it. byline density (the default) gives a 56px avatar and 28px lines; dense gives a 40px avatar and 20px lines for compact lists. Person adds no space around itself; set the gap on the list that holds it.

Prop

Type

It also accepts the props of the Base UI part it wraps, and the HTML attributes of the element it renders.

PersonAvatar

The round picture frame in Person: 56px, or 40px in a dense person. Put an AvatarImage or artwork inside and let it fill the frame, which clips it to the circle. The frame sets the size, so change it with className.

It accepts the props of the Base UI part it wraps, and the HTML attributes of the element it renders.

PersonContent

The person's text: put a PersonName, a PersonRole and an optional PersonBio inside. In a profile person it wraps below the portrait when less than 16rem is left beside it.

It accepts the HTML attributes of the element it renders.

PersonName

The person's name, in semibold text. A long name wraps, not cut off.

It accepts the HTML attributes of the element it renders.

PersonRole

The person's role or job title, in muted text below PersonName.

It accepts the HTML attributes of the element it renders.

PersonBio

A short paragraph about the person, in muted text, set a little apart below PersonRole. It shows in full, never cut off.

It accepts the HTML attributes of the element it renders.

PersonPortrait

A larger picture of the person, for team cards and profiles. It is as wide as its container, in a 3:4 frame with a hairline outline. An <img> placed directly inside fills and crops to the frame.

Prop

Type

It also accepts the props of the Base UI part it wraps, and the HTML attributes of the element it renders.

Dependencies

npm: class-variance-authority, cn. The CLI installs them for you.

Registry pieces it installs with it: