UI componentsdocs/ui/components/people.md

People & social

Users, accounts and conversations: avatars, profiles, comments and reactions.

← Component reference

Avatar #

Avatars, stacks and presence.

Avatar #

Picture or initials.

AL
<Avatar name="Ada Lovelace" />

Slots: root fallback image

PropTypeRequiredDefaultDescription
altstringImage alt text (default: name).
namestring"Avatar"Person's name: used for initials and as the accessible name.
size"sm" | "md" | "lg""md"Avatar size.
srcstringImage URL; falls back to initials from name when missing or broken.

AvatarGroup #

Overlapping avatars with a "+N" overflow chip.

ALGHAT+1
<AvatarGroup
    max={3}
    names={["Ada Lovelace", "Grace Hopper", "Alan Turing", "Linus Torvalds"]}
/>

Slots: root avatar more

PropTypeRequiredDefaultDescription
namesstring[]yesPeople to show (initials come from each name).
maxnumber4Avatars shown before collapsing the rest into a +N counter.
size"sm" | "md" | "lg""md"Avatar size.

PresenceAvatar #

Avatar with a presence dot.

AL
<PresenceAvatar name="Ada Lovelace" status="success" />

Slots: root avatar dot

PropTypeRequiredDefaultDescription
namestringyesPerson's name (initials and accessible name).
size"sm" | "md" | "lg"Avatar size.
srcstringAvatar image URL.
status"accent" | "warning" | "success" | "danger" | "neutral""success"Colour of the presence dot (e.g. success for online).

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.

Account switchers #

The signed-in user and organisation.

UserButton #

Button showing a user's avatar, name and email.

Interact with the example: callbacks show up here.
<UserButton name="Ada Lovelace" email="[email protected]" onClick={() => {}} />

Slots: root avatar chevron email name text

PropTypeRequiredDefaultDescription
namestringyesUser's name (also used for the avatar initials).
emailstringSecondary line under the name.
endcontentTrailing content (default chevron); null hides it.
onClick(e: MouseEvent) => voidCalled when the button is pressed, e.g. to open an account menu.
srcstringAvatar image URL.

OrgSwitcher #

Workspace switcher button.

Interact with the example: callbacks show up here.
<OrgSwitcher
    org={{ id: "acme", name: "Acme Inc.", plan: "Pro" }}
    onClick={() => {}}
/>

Slots: root avatar chevron meta name plan

PropTypeRequiredDefaultDescription
orgOrgOptionyesThe current organisation.
onClick() => voidCalled when pressed, e.g. to open an organisation menu.

OrgOption

FieldTypeRequiredDescription
idstringyesOrganisation id.
namestringyesOrganisation name.
planstringPlan shown under the name.

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.

Profiles & members #

Profile headers, member rows and invites.

ProfileHeader #

Profile header with cover, avatar, name, handle, bio and actions.

AL

Ada Lovelace

@ada

Analyst of engines. Writes the first programs.

Interact with the example: callbacks show up here.
<ProfileHeader
    name="Ada Lovelace"
    handle="ada"
    bio="Analyst of engines. Writes the first programs."
    actions={
        <Button variant="outline" onClick={() => {}}>
            Follow
        </Button>
    }
/>

Slots: root actions avatar bio cover handle main meta name

PropTypeRequiredDefaultDescription
namestringyesDisplay name.
actionscontentButtons at the end, e.g. Follow.
biostringShort bio.
coverstringCover image URL (a gradient when unset).
handlestringUsername, shown with a leading @.
srcstringAvatar image URL.

MemberRow #

Team member row with avatar, email and remove action.

GH
Grace Hopper[email protected]
AT
function Example() {
    const members = signal([
        { name: "Grace Hopper", email: "[email protected]" },
        { name: "Alan Turing", email: "[email protected]" },
    ]);
    return (
        <Stack gap="0.25rem">
            <For each={members()}>
                {(member) => (
                    <MemberRow
                        name={member.name}
                        email={member.email}
                        onRemove={() => members.set(members().filter((m) => m !== member))}
                    />
                )}
            </For>
            <Show when={members().length === 0}>
                <Text muted>No members left.</Text>
            </Show>
        </Stack>
    );
}

Slots: root avatar email meta name remove

PropTypeRequiredDefaultDescription
namestringyesMember name.
emailstringEmail under the name.
onRemove() => voidShows a remove button; called when it is pressed.
rolestringTeam role shown as a {@link RoleBadge} (not the ARIA role).
srcstringAvatar image URL.

InviteCard #

Pending invitation with resend and revoke actions.

Invitation pending

function Example() {
    const status = signal("Invitation pending");
    return (
        <Stack gap="0.5rem">
            <InviteCard
                email="[email protected]"
                onResend={() => status.set("Invitation re-sent just now")}
                onRevoke={() => status.set("Invitation revoked")}
            />
            <Text muted>{status()}</Text>
        </Stack>
    );
}

Slots: root actions email meta

PropTypeRequiredDefaultDescription
emailstringyesInvited address.
onResend() => voidShows a resend button; called when it is pressed.
onRevoke() => voidShows a revoke button; called when it is pressed.
resendLabelstring"Resend"Resend button text.
revokeLabelstring"Revoke"Revoke button text.
rolestringTeam role shown as a {@link RoleBadge} (not the ARIA role).

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.

Comments & chat #

Conversations, mentions and reactions.

Comment #

Discussion entry.

AL
Ada Lovelace2h ago
Looks great — can we add a reduced-motion variant?
<Comment author="Ada Lovelace" meta="2h ago">
    Looks great — can we add a reduced-motion variant?
</Comment>

Slots: root actions author avatar body content head meta

PropTypeRequiredDefaultDescription
authorstringyesAuthor name.
actionscontentButtons under the comment, e.g. Reply.
avatarstringAvatar image URL (initials from author when unset).
childrencontentComment text or content.
metastringSmall line next to the author, e.g. the time.

ChatBubble #

Chat message bubble, aligned by sender.

Grace09:41
Is the deploy done?
09:42
Yes — live on production.
<Stack gap="0.5rem">
    <ChatBubble from="them" author="Grace" meta="09:41">
        Is the deploy done?
    </ChatBubble>
    <ChatBubble from="me" meta="09:42">
        Yes — live on production.
    </ChatBubble>
</Stack>

Slots: root author body meta

PropTypeRequiredDefaultDescription
from"me" | "them"yesWho sent it: me (aligned right, accent) or them.
authorstringSender name above the bubble.
childrencontentMessage content.
metastringSmall line under the bubble, e.g. the time.

Mention #

Inline

Thanks , merging now.

Interact with the example: callbacks show up here.
<Text>
    Thanks <Mention name="ada" onClick={() => {}} />, merging now.
</Text>
PropTypeRequiredDefaultDescription
namestringyesUsername (shown with a leading @).
onClick() => voidMakes the mention a button, e.g. to open the profile.

ReactionBar #

Emoji reaction toggles.

function Example() {
    const reactions = signal([
        { emoji: "👍", count: 12, active: true },
        { emoji: "🎉", count: 4, active: false },
        { emoji: "👀", count: 2, active: false },
    ]);
    const toggle = (emoji: string) =>
        reactions.set(
            reactions().map((r) =>
                r.emoji === emoji ? { ...r, active: !r.active, count: r.count + (r.active ? -1 : 1) } : r,
            ),
        );
    return <ReactionBar reactions={reactions()} onToggle={toggle} />;
}

Slots: root reaction

PropTypeRequiredDefaultDescription
reactionsReaction[]yesReactions, in order.
onToggle(emoji: string) => voidCalled with the emoji the user toggles; update counts yourself.

Reaction

FieldTypeRequiredDescription
emojistringyesThe reaction emoji.
countnumberyesNumber of people who reacted.
activebooleanWhether the current user reacted (pressed state).

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.

Activity & inbox #

Feed and inbox items.

ActivityItem #

Activity feed entry with icon, title, meta and content.

Ada pushed 3 commits to main
12 minutes ago
<ActivityItem icon="git" title="Ada pushed 3 commits to main" meta="12 minutes ago" />

Slots: root body content icon meta title

PropTypeRequiredDefaultDescription
titlestringyesWhat happened.
childrencontentExtra detail below the title.
iconIconName"bell"Built-in icon name, or pass any node via iconNode.
iconNodecontentCustom leading content instead of icon.
metacontentSmall line, e.g. the time.

IconName — Material Design Icons path names used by <Icon />.

type IconName = | "check" | "x" | "plus" | "minus" | "search" | "user" | "users" | "settings" | "menu" | "home" | "heart" | "star" | "bell" | "mail" | "calendar" | "clock" | "edit" | "trash" | "copy" | "download" | "upload" | "link" | "external" | "info" | "warning" | "error" | "success" | "chevron-down" | "chevron-up" | "chevron-left" | "chevron-right" | "arrow-left" | "arrow-right" | "eye" | "eye-off" | "eye-outline" | "lock" | "unlock" | "filter" | "more" | "close" | "spinner" | "sun" | "moon" | "play" | "pause" | "refresh" | "share" | "image" | "file" | "folder" | "zap" | "phone" | "git" | "code";

InboxItem #

Notification row.

Interact with the example: callbacks show up here.
<InboxItem
    icon="git"
    title="Grace requested your review"
    body="#421 Toast: pause on hover"
    time="5m"
    unread
    onClick={() => {}}
/>

Slots: root body icon text time title

PropTypeRequiredDefaultDescription
titlestringyesWhat the notification is about.
bodycontentSecondary text.
iconIconName"bell"Leading icon.
onClick() => voidMakes the item a button, e.g. to open it.
timecontentWhen it arrived.
unreadbooleanShow the unread dot and bold title.

IconName — Material Design Icons path names used by <Icon />.

type IconName = | "check" | "x" | "plus" | "minus" | "search" | "user" | "users" | "settings" | "menu" | "home" | "heart" | "star" | "bell" | "mail" | "calendar" | "clock" | "edit" | "trash" | "copy" | "download" | "upload" | "link" | "external" | "info" | "warning" | "error" | "success" | "chevron-down" | "chevron-up" | "chevron-left" | "chevron-right" | "arrow-left" | "arrow-right" | "eye" | "eye-off" | "eye-outline" | "lock" | "unlock" | "filter" | "more" | "close" | "spinner" | "sun" | "moon" | "play" | "pause" | "refresh" | "share" | "image" | "file" | "folder" | "zap" | "phone" | "git" | "code";

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.

Testimonials & reviews #

Quotes and star reviews from customers.

Testimonial #

Customer quote.

We replaced three component libraries with one and our bundle got smaller.
GHGrace HopperStaff engineer, Navy Labs
<Testimonial
    quote="We replaced three component libraries with one and our bundle got smaller."
    author="Grace Hopper"
    role="Staff engineer, Navy Labs"
/>

Slots: root author avatar name quote role

PropTypeRequiredDefaultDescription
authorstringyesWho said it.
quotecontentyesThe testimonial text.
avatarstringAuthor avatar URL.
rolestringAuthor's job title (consumed here; not forwarded as an ARIA role).

ReviewCard #

Star-rated review.

Solid mug

Keeps coffee warm, survives the dishwasher.

Linus T.

<ReviewCard order={3} rating={4} title="Solid mug" author="Linus T.">
    Keeps coffee warm, survives the dishwasher.
</ReviewCard>

Slots: root author body star stars title

PropTypeRequiredDefaultDescription
ratingnumberyesStars out of 5.
authorcontentReviewer name.
childrencontentReview text.
orderHeadingLevel4Heading level of the title, to fit the page outline. Default 4.
titlestringReview headline.

HeadingLevel

type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.

Row of icon links.

<SocialLinks
    items={[
        { icon: "git", label: "GitHub", href: "https://github.com" },
        { icon: "mail", label: "Email", href: "mailto:[email protected]" },
    ]}
/>

Slots: root link

PropTypeRequiredDefaultDescription
itemsSocialLink[]yesLinks, in order.

SocialLink

FieldTypeRequiredDescription
iconIconNameyesNetwork icon.
labelstringyesNetwork name (accessible name).
hrefstringRenders a real link (opens in a new tab) when set.
onClick() => voidClick handler (renders a button when there is no href).

IconName — Material Design Icons path names used by <Icon />.

type IconName = | "check" | "x" | "plus" | "minus" | "search" | "user" | "users" | "settings" | "menu" | "home" | "heart" | "star" | "bell" | "mail" | "calendar" | "clock" | "edit" | "trash" | "copy" | "download" | "upload" | "link" | "external" | "info" | "warning" | "error" | "success" | "chevron-down" | "chevron-up" | "chevron-left" | "chevron-right" | "arrow-left" | "arrow-right" | "eye" | "eye-off" | "eye-outline" | "lock" | "unlock" | "filter" | "more" | "close" | "spinner" | "sun" | "moon" | "play" | "pause" | "refresh" | "share" | "image" | "file" | "folder" | "zap" | "phone" | "git" | "code";

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.