Build / Molecules
MemberRow
One person on the team: who they are, where their invitation stands, what they can do, and what you can do about it.
Invited and active are the same row on purpose. A seat is spent the moment an invitation goes out, so a pending teammate belongs in the roster they are already being counted in — not in a separate list below it that makes the seat maths look wrong.
isYou is a guard as much as a label: the row you must not remove is the
one worth marking.
import { MemberRow } from '@meetcard/deck'Example
<MemberRow name="Sam Oyelaran" email="sam@meetcard.io" status="active" role={<Select label="Role" hideLabel size="sm" options={roles} />} />Stories
Source
const Default = () => <Card style={{ maxWidth: 620 }}>
<MemberRow
name="Sam Oyelaran"
email="sam@meetcard.io"
status="active"
role={roleSelect('Sam Oyelaran', 'member')} />
</Card>;The row you must not remove is the one worth marking.
Source
const You = () => <Card style={{ maxWidth: 620 }}>
<MemberRow
name="Ben Ackles"
email="ben@meetcard.io"
status="active"
isYou
role={roleSelect('Ben Ackles', 'owner')} />
</Card>;An invitation nobody has accepted. The email is all the team knows, so it stands in for the name — and the row stays in the roster, because the seat is already spent.
Source
const Invited = () => <Card style={{ maxWidth: 620 }}>
<MemberRow
name="dana@meetcard.io"
email="Invitation pending"
status="invited"
actions={(<>
<Button size="sm" variant="ghost">
Resend
</Button>
<Button size="sm" variant="ghost">
Revoke
</Button>
</>)} />
</Card>;Suspended — still in the roster, with the action that brings them back.
Source
const Suspended = () => <Card style={{ maxWidth: 620 }}>
<MemberRow
name="Marcus Lee"
email="marcus@meetcard.io"
status="suspended"
actions={(<Button size="sm" variant="secondary">Reactivate
</Button>)} />
</Card>;The whole roster, active and pending in one list, as the seat count sees it.
Source
const Roster = () => (
<Card style={{ maxWidth: 620 }}>
<MemberRow
name="Ben Ackles"
email="ben@meetcard.io"
isYou
role={roleSelect('Ben Ackles', 'owner')}
/>
<MemberRow
name="Sam Oyelaran"
email="sam@meetcard.io"
role={roleSelect('Sam Oyelaran', 'admin')}
/>
<MemberRow
name="Prisha Nair"
email="prisha@meetcard.io"
role={roleSelect('Prisha Nair', 'member')}
/>
<MemberRow
name="dana@meetcard.io"
email="Invitation pending"
status="invited"
actions={
<Button size="sm" variant="ghost">
Revoke
</Button>
}
/>
</Card>
);Props
| Prop | Type | Default | Description |
|---|---|---|---|
namerequired | string | — | The person. For an invitation nobody has accepted yet this is the email address, because that is genuinely all the team knows about them. |
actions | ReactNode | — | Resend, revoke, remove — whatever this row can do. |
avatarSrc | string | — | — |
email | ReactNode | — | — |
isYou | boolean | — | Marks the signed-in person, so nobody removes their own seat by mistake. |
role | ReactNode | — | The role: a Select where it can be changed, a Badge where it can't. |
status | 'active' | 'invited' | 'suspended' | 'active' | — |
Also accepts everything from Omit, so id, data-* and event handlers pass straight through.