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
| File | Path |
|---|---|
| team-invitation.tsx | components/user-management/team-invitation/team-invitation.tsx |
| invite-modal.tsx | components/user-management/team-invitation/invite-modal.tsx |
| pending-invitations.tsx | components/user-management/team-invitation/pending-invitations.tsx |
| invitation-row.tsx | components/user-management/team-invitation/invitation-row.tsx |
| email-input.tsx | components/user-management/team-invitation/email-input.tsx |
| role-select.tsx | components/user-management/team-invitation/role-select.tsx |
| expiration-select.tsx | components/user-management/team-invitation/expiration-select.tsx |
| confirm-dialog.tsx | components/user-management/team-invitation/confirm-dialog.tsx |
| types.ts | components/user-management/team-invitation/types.ts |
| index.ts | components/user-management/team-invitation/index.ts |
Utility Files
| File | Path |
|---|---|
| design-tokens.ts | lib/design-tokens.ts |
Dependencies
Install these dependencies before using the component:
Terminal
bash
npx shadcn@latest add button dialog input select badgeTerminal
bash
npm install @phosphor-icons/reactInstallation
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
| Prop | Type | Default |
|---|---|---|
| invitations | Invitation[] | required |
| onInvite | (emails: string[], role: InvitationRole, expiresAt?: Date | null) => Promise | required |
| onResend | (invitationId: string) => Promise | - |
| onRevoke | (invitationId: string) => Promise | - |