Skip to content

Components · Identity

MemberRow

One member of a workspace or space: avatar, name, email, role, status (invited, active, suspended) and confirmed actions.

@rookcom/monarch-react/patternsComponent

Members with editable roles

Usage examples

Invited, suspended and read-only

Purpose

The same member row everywhere people are listed with a role: workspace and space members, channel members, project and team members. The product passes the person, the roles allowed and callbacks; who may change what stays in the product. Import from @rookcom/monarch-react/patterns.

Use when

  • A list of people with a role that some viewers may change.
  • Pending invitations shown alongside members, with resend and revoke.

Avoid when

  • Choosing people to add: use EntityPicker or AssigneePicker.
  • Dense tables with many columns per person: use DataTable with Avatar cells.

Design principles

  • Identity first: avatar, name and email read as one unit; everything else is secondary.
  • Only what differs is marked: invited and suspended get a badge, active members do not, so a long list stays quiet.
  • Every control is named after the person (“Role for Jonas Weber”, “Remove Jonas Weber”), so a list of identical buttons is still clear to screen-reader users.
  • Destructive actions are confirmed in a ConfirmDialog that can show what will happen.
  • Async by default: role changes and resends show a busy state; failures are explained in the row and roll back.

API reference

import { MemberList, MemberRow } from '@rookcom/monarch-react/patterns';
ExportKindRenderingRoot class
MemberListcomponentclient.mn-member-row
MemberRowcomponentclient.mn-member-row

MemberRow renders an <li> (ref) by default, or a <div> with as="div"; MemberList is the <ul> that holds rows.

The member’s role is memberRole / defaultMemberRole / onMemberRoleChange (not the ARIA role), chosen from roleOptions.

onMemberRoleChange, onResend and onRemove may return promises; a rejected role change restores the previous role.

Data attributes: data-status (invited, active, suspended) and data-self.

Generated from the TypeScript declarations of packages/react/src/components/identity/member-row.

Properties

MemberList

The list that holds MemberRows, so screen readers announce "list, 12 items".

PropTypeDescription
childrenReactNode
classNamestring
idstring

MemberRow

One member of a workspace, space or channel: avatar, name, email, role, status (invited, active, suspended) and actions. Role changes, resends and removals go through product callbacks; removal is confirmed first. Use inside `MemberList`.

PropTypeDescription
name requiredstringDisplay name. Also seeds the avatar initials and colour.
actionsReactNodeMore trailing actions, such as a DropdownMenu. Name them after the member.
as"div" | "li"Element to render. Default `li`, for use inside `MemberList`.
avatarUrlstring | nullAvatar image URL; initials are shown without it or when it fails.
badgesReactNodeExtra markers after the name, such as a Guest badge.
canChangeRolebooleanShow the role select. Default: when `onMemberRoleChange` is given and it is not your own row.
canRemovebooleanShow Remove. Default: when `onRemove` is given and it is not your own row.
classNamestring
defaultMemberRolestringInitial member role (uncontrolled).
disabledbooleanDisable every control in the row.
emailReactNodeEmail or handle, shown under the name.
idstring
isSelfbooleanThe row is the signed-in person: shows "You" and hides Remove.
memberRolestringThe member's role (controlled), one of `roleOptions`' values. Not the ARIA `role`.
messagesPartial<MemberRowMessages>Override visible and announced strings.
metaReactNodeA line of extra detail under the email: joined date, invite expiry, availability.
onMemberRoleChange((role: string) => unknown)Makes the role a select. Return a promise to show it busy; reject to restore the previous role and show the error in the row.
onRemove(() => unknown)Remove the member (or revoke the invitation), after a confirmation dialog. Return a promise to keep the dialog pending; reject to show the error there.
onResend(() => unknown)Resend an invitation. Shown for `status="invited"`.
presenceAvatarStatusPresence dot on the avatar.
removeConsequencesReactNode[]Consequences listed in the remove dialog ("3 assigned tickets go back to the queue").
roleOptionsreadonly NativeSelectOption[]The roles the product allows here. Their labels also show for read-only roles.
statusMemberStatusDefault `active`. `invited` and `suspended` show a badge and change the actions.

Variants

PropValuesDescription
status'active''invited''suspended'invited shows an Invited badge, Resend and Revoke; suspended a Suspended badge and a muted name.
as'li''div'li (default) inside MemberList; div for a single row in a card or popover.

States

StateExposed asBehaviour
Activedata-status="active"No status badge.
Inviteddata-status="invited"Info badge; Resend invite; Remove becomes Revoke invite.
Suspendeddata-status="suspended"Warning badge and a muted name.
Selfdata-self“(You)” after the name; role select and Remove hidden by default.
Role read-only–Without onMemberRoleChange (or with canChangeRole={false}) the role label is text.
Busyaria-busy on the select or buttonWhile a role change or resend runs.
Errorrole="alert" in the rowA failed role change or resend, in the product’s words.
Disabled–Every control in the row disabled.

Interaction behaviour

  • Changing the role calls onMemberRoleChange. Uncontrolled, the select updates at once and rolls back if the promise rejects; controlled, it waits for the product’s new memberRole.
  • Resend calls onResend and announces “Invite sent again.”
  • Remove opens a danger ConfirmDialog (title, description and optional consequences) and calls onRemove; errors stay in the dialog so the person can retry.
  • Extra actions (for example a DropdownMenu) go in actions, before Remove.

Keyboard support

KeysAction
TabMoves between the role select, Resend, extra actions and Remove.
Arrow keysChange the role in the native select.
Enter / SpaceActivates Resend or Remove.
EscapeCloses the remove confirmation.

Accessibility

Role
listitem (in MemberList, a list)
Accessible name
Rows are named by their text; controls are labelled after the member.
  • MemberList is a real <ul>, so screen readers announce “list, n items”.
  • The avatar is decorative next to the visible name; presence is read as hidden text after the name (“Online”).
  • Role select: “Role for {name}”. Remove: “Remove {name}” or “Revoke invite for {name}”. Resend: “Resend invite, {name}”.
  • Resend success is a polite status; failures are role="alert".
  • Verified with axe in jsdom and in Chromium, Firefox and WebKit on /components/member-row.

Responsive behaviour

  • Name and email truncate with an ellipsis instead of pushing the controls off screen.
  • When the row is narrower than 26rem (container query), the controls move under the name, aligned with the text.
  • Buttons keep their touch size at every width.

Theme support

  • Monarch tokens only: names in --mn-color-text-default, emails in --mn-color-text-muted, row separators --mn-color-border-subtle.
  • Badges use the info and warning tones; follows light, dark and high-contrast themes.

Do and don't

Do

  • Pass only the roles the viewer may assign in roleOptions; enforce the same rule on the server.
  • Add removeConsequences when removing someone affects their work (“3 open tickets go back to the queue”).
  • Use meta for one useful fact: joined date, invite expiry or availability.

Don't

  • Do not let people remove themselves from this row; offer “Leave” elsewhere.
  • Do not put the role in a menu when there are only a few roles; the native select is faster.
  • Do not show “Active” on every row; it is the default.
  • Avatar: The avatar used here; on its own for compact people chips.
  • AssigneePicker: Choose people to assign or add.
  • DataTable: Many columns per person, sorting and bulk actions.
  • ConfirmDialog: The removal confirmation.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsButton, Badge, Field, ConfirmDialog, Avatar

Testing coverage

  • Identity, presence text, badges, email, meta and read-only role in a list; self row; axe.
  • Labelled role select changes the role (uncontrolled); axe.
  • A rejected role change restores the previous role and shows the error.
  • Controlled role waits for the product and is busy meanwhile.
  • Own row hides role select and Remove by default.
  • Resend calls onResend and announces success; axe.
  • Remove by keyboard opens a confirm dialog with consequences, focus on Cancel; rejection shown in the dialog, retry succeeds.
  • Invited rows revoke; suspended rows are marked.
  • Disabled, as="div" and translated messages; renders on the server.
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesVisual baselines: /__gallery/member-row; Cross-browser axe: /components/member-row

Tests: packages/react/src/components/identity/member-row