Skip to content

FRD: Team Management / Invite Recipe

FieldValue
IDFRD-045
OwnerDavid Holmes
StatusDraft
PriorityP1 — Recipes
SizeM (Recipe)
Target Releasev2.0.0
Last Updated2026-05-26
RelatedADR-027 (Default Tech Stack)

Document Summary

Create an MDX recipe in Storybook that teaches developers how to compose a Team Management page — the universal B2B admin surface for managing organization members. The recipe covers a member list with role display and actions, role change flows, pending invite management (resend/revoke), seat count tracking, and comprehensive loading/empty/error states. It provides copy-pasteable code for a realistic team administration experience.


Introduction

Overview

Every B2B SaaS product needs a team management page where admins can view members, change roles, invite new members, and manage pending invitations. This pattern recurs across virtually every multi-user application, yet developers rebuild it from scratch each time. The recipe codifies the canonical composition of design system components for this surface, including the tricky edge cases around invite states, seat limits, and role hierarchies.

Goals

  • Provide a single MDX recipe showing the complete Team Management page composition.
  • Show a member list using DataGrid with role badges, status indicators, and row actions (change role, remove).
  • Show an invite flow with email input, role selection, and confirmation.
  • Show pending invite management with resend and revoke actions.
  • Show seat count tracking with upgrade CTA when at limit.
  • Cover all states: loading (skeleton), empty (no members besides self), error (failed to load), pending invites section.

Non-Goals

  • Implementing RBAC (role-based access control) logic — the recipe shows the UI, not the authorization layer.
  • SSO/SAML integration details.
  • Audit log of team changes (separate pattern).
  • Multi-team or organization hierarchy (separate, more complex pattern).

Scope

In Scope

ItemDescription
MDX recipe pagesrc/docs/recipes/team-management.mdx with Storybook sidebar entry
Member listDataGrid showing name, email, role badge, status, last active, row actions
Invite flowDialog with email input (multi-email support), role selector, send button
Pending invitesSeparate section or tab showing invited-but-not-accepted members with resend/revoke
Role changeDropdownMenu or Select for changing a member’s role with confirmation
Remove memberAlertDialog confirmation for removing a team member
Seat countDisplay of “X of Y seats used” with progress indicator and upgrade CTA
State coverageLoading skeletons, empty state, error state for the member list
Overview page updateAdd Team Management recipe to src/docs/recipes/00-overview.mdx

Out of Scope

ItemReason
Authorization middlewareBackend concern; recipe shows the UI composition
Email delivery for invitationsBackend service; recipe shows the UI trigger
SSO/SAML configurationComplex identity provider integration, separate pattern
Organization switchingMulti-org support is a different page pattern

Users and Pain Points

UserPain Point
Application developerNo canonical pattern for member list + invite flow + pending invites composition
Application developerUnclear how to handle seat limits in the UI — when to block invites vs. show upgrade
Application developerRole change confirmation UX is inconsistent — some apps use inline, others use dialogs
Application developerPending invite states (sent, expired, revoked) need distinct visual treatment but no guide exists
Product managerInconsistent team management UX across products

Definitions

TermDefinition
SeatA billable unit representing one team member slot in the subscription plan
Pending inviteAn invitation that has been sent but not yet accepted by the recipient
RoleA permission level assigned to a team member (e.g., Owner, Admin, Member, Viewer)
ResendRe-sending an invitation email to a pending invitee
RevokeCanceling a pending invitation before it is accepted

Current State

  • No team management recipe exists in src/docs/recipes/.
  • Components available for composition: DataGrid, Dialog, AlertDialog, DropdownMenu, Select, TextField, Badge, Button, Toast, EmptyState, Skeleton, ProgressBar, Avatar.
  • The recipes overview does not list a team management recipe (it will need to be added).
  • Common patterns for team management exist across the industry but are not documented in this design system.

Proposed Solution

Create src/docs/recipes/team-management.mdx with the following structure:

  1. Introduction — What this recipe builds, when to use it, when not to use it.
  2. Component inventory — Table listing all components with links.
  3. Data model — TypeScript interfaces for TeamMember, PendingInvite, and TeamSeatInfo.
  4. Page layout — Overall structure with seat count header, member list, and pending invites section.
  5. Seat count header — Current seats used, total seats, progress indicator, upgrade CTA when at limit.
  6. Member list — DataGrid with columns: Avatar + Name, Email, Role (badge), Status, Last Active, Actions (dropdown menu).
  7. Invite dialog — Multi-email input (TokenInput or comma-separated TextField), role selector, send button, validation.
  8. Role change — DropdownMenu trigger on role badge, confirmation dialog for privilege escalation/demotion.
  9. Remove member — AlertDialog with member name, impact warning, confirm/cancel.
  10. Pending invites — List or table showing pending invites with status (Sent, Expired), sent date, resend/revoke actions.
  11. States — Loading skeletons for the member grid, empty state (new team with only the owner), error state (failed to fetch members).
  12. Full composition — Complete code block.

Requirements

IDRequirementPriority
REQ-01Recipe is a single MDX file in src/docs/recipes/Must
REQ-02Recipe shows member list with role badges and row actionsMust
REQ-03Recipe shows invite dialog with email input and role selectionMust
REQ-04Recipe shows pending invite management with resend/revokeMust
REQ-05Recipe shows seat count trackingMust
REQ-06Recipe shows loading, empty, and error statesMust
REQ-07All code blocks are copy-pasteable and self-containedMust
REQ-08Recipe shows role change with confirmation for privilege changesShould
REQ-09Recipe shows remove member with AlertDialog confirmationShould

Functional Requirements

IDDescriptionAcceptance
FR-01MDX file renders in Storybook without errorspnpm build-storybook succeeds
FR-02All code blocks compile when extractedManual verification
FR-03Invite dialog validates email formatCode example includes validation
FR-04Seat count prevents inviting when at limitCode example disables invite button at seat limit
FR-05Pending invite section distinguishes sent vs. expired invitesBadge or status indicator differentiates

Non-Functional Requirements

IDDescriptionTarget
NFR-01Recipe page load timeUnder 2 seconds
NFR-02Individual code block line countUnder 80 lines per block
NFR-03Full composition line countUnder 250 lines

API/Interface Requirements

InterfaceRequirement
MDX fileMust use “
TeamMember interfaceid, name, email, avatarUrl, role, status, lastActiveAt
PendingInvite interfaceid, email, role, sentAt, expiresAt, status
TeamSeatInfo interfaceused, total, planName

Accessibility Requirements

IDRequirement
A11Y-01Member list must be navigable by keyboard with clear focus indicators
A11Y-02Role change dropdown must announce the current role and available options
A11Y-03Invite dialog email input must have an accessible label and error announcements
A11Y-04Remove member dialog must include the member’s name in its accessible description
A11Y-05Seat count must be announced as "{used} of {total} seats used" for screen readers
A11Y-06Empty and error states must use appropriate ARIA roles

Content and Documentation Requirements

IDRequirement
DOC-01Update src/docs/recipes/00-overview.mdx to add Team Management recipe
DOC-02Include a “Role hierarchy” callout explaining Owner > Admin > Member > Viewer
DOC-03Include a “When to use” / “When not to use” section

Dependencies

DependencyTypeRisk
DataGrid componentInternalMust support row actions and custom cell renderers
Dialog componentInternalUsed for invite flow
AlertDialog componentInternalUsed for remove member confirmation
DropdownMenu componentInternalUsed for role change and row actions
Badge componentInternalUsed for role and status display
TokenInput componentInternalPreferred for multi-email input; falls back to TextField
Avatar componentInternalUsed in member list name column

Risks and Tradeoffs

RiskImpactMitigation
TokenInput may not exist for multi-email inputLess polished invite UXFall back to comma-separated TextField with validation
Role hierarchy varies by applicationRecipe may not fit all role modelsUse a generic 4-tier hierarchy (Owner, Admin, Member, Viewer); note that apps should customize
Seat limit logic interacts with billingCross-concern complexityRecipe shows the UI only; link to the Billing recipe for upgrade flows

Open Questions

#QuestionStatus
1Should pending invites be a separate tab or a section below the member list?Open — leaning section
2Should the recipe show a “Transfer ownership” flow?Open — likely out of scope for v1
3Should expired invites be automatically hidden or shown with a “Resend” CTA?Open
4Should the recipe include a “Bulk invite from CSV” pattern?Open — likely a follow-up

Acceptance Criteria

  • src/docs/recipes/team-management.mdx exists and renders in Storybook.
  • Recipe appears in sidebar under “Docs/Best Practices/Recipes/Team Management”.
  • Recipe shows member list with name, email, role badge, status, and row actions.
  • Recipe shows invite dialog with email input, role selector, and validation.
  • Recipe shows pending invite section with resend and revoke actions.
  • Recipe shows seat count with progress indicator and upgrade CTA at limit.
  • Recipe shows loading, empty, and error states.
  • All code blocks compile when extracted.
  • pnpm build-storybook succeeds.

LLM Handoff Instructions

When an LLM agent picks up this FRD:

  1. Read src/docs/recipes/00-overview.mdx for recipe conventions.
  2. Read component source for: DataGrid, Dialog, AlertDialog, DropdownMenu, Select, TextField, Badge, Button, Toast, EmptyState, Skeleton, Avatar, TokenInput (if it exists).
  3. Read each component’s stories to understand usage patterns.
  4. Create src/docs/recipes/team-management.mdx with the section structure from the Proposed Solution.
  5. Sample data: A team of 6 members across 4 roles (1 Owner, 1 Admin, 3 Members, 1 Viewer), 2 pending invites (1 sent yesterday, 1 expired), seat plan of 8/10 seats used.
  6. Include TypeScript interfaces for TeamMember, PendingInvite, and TeamSeatInfo.
  7. All code blocks must use public package import paths.
  8. After creating, run pnpm build-storybook to verify.
  9. Update src/docs/recipes/00-overview.mdx.

Decision Log

DateDecisionRationale
2026-05-26Use a 4-tier role hierarchy (Owner, Admin, Member, Viewer)Covers the most common B2B role model; apps can customize
2026-05-26Show pending invites as a section rather than a tabKeeps the full team picture visible on one page; tabs hide information

Document History

DateVersionAuthorChanges
2026-05-260.1David HolmesInitial draft