Team Invitation Flow

A clean, minimal component for inviting team members with role-based permissions. Simple structure with clear actions and status indicators.

Preview

Features

  • Clean card layout with header and invitation list
  • Bulk email input with colorful avatar chips
  • Role selector with distinct icons (Admin, Member, Viewer)
  • Expiration dropdown with quick presets
  • Always-visible action buttons for better accessibility
  • Mobile-friendly layout with stacked rows and accessible controls
  • Status badges with semantic colors
  • Simple empty state design
  • Confirmation dialog for destructive actions
  • Loading skeleton states

Install Summary

This kit will add the following files and dependencies to your project. Download the bundle and extract it into your project root.

Component Files

FilePath
team-invitation.tsxcomponents/user-management/team-invitation/team-invitation.tsx
invite-modal.tsxcomponents/user-management/team-invitation/invite-modal.tsx
pending-invitations.tsxcomponents/user-management/team-invitation/pending-invitations.tsx
invitation-row.tsxcomponents/user-management/team-invitation/invitation-row.tsx
email-input.tsxcomponents/user-management/team-invitation/email-input.tsx
role-select.tsxcomponents/user-management/team-invitation/role-select.tsx
expiration-select.tsxcomponents/user-management/team-invitation/expiration-select.tsx
confirm-dialog.tsxcomponents/user-management/team-invitation/confirm-dialog.tsx
types.tscomponents/user-management/team-invitation/types.ts
index.tscomponents/user-management/team-invitation/index.ts

Utility Files

FilePath
design-tokens.tslib/design-tokens.ts

Dependencies

Install these dependencies before using the component:

Terminal
bash
npx shadcn@latest add button dialog input select badge
Terminal
bash
npm install @phosphor-icons/react

Installation

Download the complete bundle as a ZIP file, or copy the text bundle to your clipboard:

Component Files

The component consists of the following files:

1. team-invitation.tsx

team-invitation.tsx
tsx
"use client";

import { useState } from "react";
import { UserPlus, UsersThree as Users } from "@phosphor-icons/react";
import { Button } from "@/components/ui/button";

2. invite-modal.tsx

invite-modal.tsx
tsx
"use client";

import { useState } from "react";
import { CircleNotch as Loader2, PaperPlaneTilt as Send, UserPlus } from "@phosphor-icons/react";
import { Button } from "@/components/ui/button";

3. pending-invitations.tsx

pending-invitations.tsx
tsx
"use client";

import { useState } from "react";
import { UserPlus } from "@phosphor-icons/react";
import { Skeleton } from "@/components/ui/skeleton";

4. invitation-row.tsx

invitation-row.tsx
tsx
"use client";

import { useState } from "react";
import {
  CircleNotch as Loader2,

5. email-input.tsx

email-input.tsx
tsx
"use client";

import { useState, useCallback, KeyboardEvent, useRef } from "react";
import { X } from "@phosphor-icons/react";
import { cn } from "@/lib/utils";

6. role-select.tsx

role-select.tsx
tsx
"use client";

import { CaretDown as ChevronDown, Check, ShieldStar as Shield, UsersThree as Users, Eye } from "@phosphor-icons/react";
import { Button } from "@/components/ui/button";
import {

7. expiration-select.tsx

expiration-select.tsx
tsx
"use client";

import { CaretDown as ChevronDown, Check, Clock } from "@phosphor-icons/react";
import {
  DropdownMenu,

8. confirm-dialog.tsx

confirm-dialog.tsx
tsx
"use client";

import { useState } from "react";
import { CircleNotch as Loader2, XCircle, EnvelopeSimple as Mail } from "@phosphor-icons/react";
import { Button } from "@/components/ui/button";

9. types.ts

types.ts
tsx
export type InvitationRole = "admin" | "member" | "viewer";

export type InvitationStatus = "pending" | "accepted" | "expired" | "revoked";
export type ExpirationOption = "never" | "7d" | "14d" | "30d";

10. index.ts

index.ts
tsx
export { TeamInvitation } from "./team-invitation";
export { InviteModal } from "./invite-modal";
export { PendingInvitations } from "./pending-invitations";
export { InvitationRow } from "./invitation-row";
export { EmailInput } from "./email-input";

Shared Utilities

This component uses shared utility functions. These are included in the bundle above:

design-tokens.ts

design-tokens.ts
tsx
// Border radius
export const radius = {
  card: "rounded-xl",
  badge: "rounded-full",
  button: "rounded-lg",

Usage

app/team.tsx
tsx
"use client";

import { useState } from "react";
import { TeamInvitation, type Invitation, type InvitationRole } from "@/components/user-management";

TeamInvitation Props

PropTypeDefault
invitationsInvitation[]required
onInvite(emails: string[], role: InvitationRole, expiresAt?: Date | null) => Promiserequired
onResend(invitationId: string) => Promise-
onRevoke(invitationId: string) => Promise-