Team Invitation

Compound team invitation block with fluid morphing variant tabs, an invite form, member lists with role dropdowns, role groups, and pending invites.

Installation

npx shadcn@latest add @iconiq/team-invitation

File Structure

Usage

"use client";

import { Clock, ShieldCheck, UserPlus, Users } from "lucide-react";
import {
  TeamInvitation,
  TeamInvitationCard,
  TeamInvitationDescription,
  TeamInvitationHeader,
  TeamInvitationInviteField,
  TeamInvitationMemberList,
  TeamInvitationPanel,
  TeamInvitationPanels,
  TeamInvitationPendingList,
  TeamInvitationRoleGroups,
  TeamInvitationTab,
  TeamInvitationTabs,
  TeamInvitationTitle,
} from "@/components/ui/team-invitation";

const members = [
  {
    id: "trevor",
    name: "Trevor Phillips",
    email: "trevorphillips@gmail.com",
    role: "Assistant",
    avatar: "/assets/av1.png",
  },
  {
    id: "michael",
    name: "Michael De Santa",
    email: "michaeldesanta@gmail.com",
    role: "Junior Level",
    avatar: "/assets/av2.png",
  },
  {
    id: "franklin",
    name: "Franklin Clinton",
    email: "franklinclinton@gmail.com",
    role: "Senior Level",
    avatar: "/assets/av3.png",
  }
];

export function TeamInvitationPreview() {
  return (
    <TeamInvitation
      defaultVariant="invite"
      members={members}
      onInvite={(email) => console.log("invite", email)}
      onRoleChange={(id, role) => console.log(id, role)}
      pendingInvites={[
        { id: "jhon", email: "jhon@wick.com", sentAt: "Sent 2d ago" },
      ]}
      roles={["Assistant", "Junior Level", "Senior Level"]}
    >
      <TeamInvitationCard>
        <TeamInvitationHeader icon={<Users />}>
          <TeamInvitationTitle>Invite Team Member</TeamInvitationTitle>
          <TeamInvitationDescription>
            Share tasks with other users
          </TeamInvitationDescription>
        </TeamInvitationHeader>
        <TeamInvitationTabs>
          <TeamInvitationTab icon={<UserPlus />} value="invite">
            Invite Members
          </TeamInvitationTab>
          <TeamInvitationTab icon={<Users />} value="manage">
            Manage Team
          </TeamInvitationTab>
          <TeamInvitationTab icon={<ShieldCheck />} value="roles">
            Role Management
          </TeamInvitationTab>
          <TeamInvitationTab icon={<Clock />} value="pending">
            Pending Invites
          </TeamInvitationTab>
        </TeamInvitationTabs>
        <TeamInvitationPanels>
          <TeamInvitationPanel value="invite">
            <TeamInvitationInviteField
              buttonLabel="Invite Member"
              label="Email"
            />
            <TeamInvitationMemberList action="role" label="Member Lists" />
          </TeamInvitationPanel>
          <TeamInvitationPanel value="manage">
            <TeamInvitationMemberList
              action="remove"
              emptyMessage="No members yet. Invite someone first."
              label="Team Members"
            />
          </TeamInvitationPanel>
          <TeamInvitationPanel value="roles">
            <TeamInvitationRoleGroups emptyMessage="No members with this role yet." />
          </TeamInvitationPanel>
          <TeamInvitationPanel value="pending">
            <TeamInvitationPendingList
              emptyMessage="No pending invites. Invite someone from the Invite Members tab."
              label="Pending Invites"
            />
          </TeamInvitationPanel>
        </TeamInvitationPanels>
      </TeamInvitationCard>
    </TeamInvitation>
  );
}

Props

Props
Description

TeamInvitation

children

Composition surface. Place TeamInvitationCard with the header, tabs, and panels inside.

Type ReactNode

variant

Controlled active variant when the parent owns which panel is shown. Matches TeamInvitationTab and TeamInvitationPanel values.

Type string

defaultVariant

Initial variant for uncontrolled usage.

Type string

onVariantChange

Called when a variant tab is selected.

Type (variant: string) => void

members

Seed member list ({ id, name, email, role, avatar? }). The root keeps a working copy so role changes and removals animate locally.

Type TeamMember[]

pendingInvites

Seed pending invite list ({ id, email, sentAt? }). Invites submitted from TeamInvitationInviteField are appended here.

Type PendingInvite[]

roles

Assignable roles shown in role dropdowns and as TeamInvitationRoleGroups sections.

Type string[]

onInvite

Called with the trimmed email when the invite button is pressed or Enter is hit in the field.

Type (email: string) => void

onRoleChange

Called when a member is assigned a new role.

Type (id: string, role: string) => void

onRemove

Called when a member is removed.

Type (id: string) => void

onResend

Called when a pending invite's resend button is pressed.

Type (id: string) => void

onCancelInvite

Called when a pending invite is cancelled.

Type (id: string) => void

onClose

Renders the header close button and is called when it is pressed. Omit to hide the button.

Type () => void

className

Extra classes for the outer wrapper.

Type string

TeamInvitationTabs, TeamInvitationTab

value

Variant id. Selecting the tab reveals the TeamInvitationPanel with the same value.

Type string

icon

Icon shown while the tab is collapsed and expanded.

Type ReactNode

children

Label revealed while the tab is active.

Type ReactNode

TeamInvitationPanels, TeamInvitationPanel

value

Variant id paired with the TeamInvitationTab of the same value.

Type string

children

Panel content — section parts below or any custom markup.

Type ReactNode

InviteField, MemberList, RoleGroups, PendingList

label

Section heading rendered with TeamInvitationSectionLabel. On TeamInvitationInviteField this sits above the field row.

Type ReactNode

buttonLabel

Invite button copy on TeamInvitationInviteField.

Type ReactNode

placeholder

Input placeholder on TeamInvitationInviteField.

Type string

action

Trailing control per row on TeamInvitationMemberList. Defaults to role.

Type "role" | "remove" | "none"

emptyMessage

Dashed empty-state row shown when a list or role group has no entries. Omit to render nothing.

Type ReactNode

TeamInvitationCard, Header, Title, Description, SectionLabel

Structural parts that compose the card shell. Card animates in with a spring and morphs its height between variants, Header wraps an optional icon tile, your Title and Description, and the close button when onClose is set on the root. Each accepts `children` and an optional `className`.

TeamInvitationCard renders the bordered card surface with the entrance spring and fluid height morph.

TeamInvitationHeader takes an optional `icon` rendered in a bordered tile before your heading copy.

TeamInvitationSectionLabel is the shared heading used by the section parts — reuse it for your own panel content.

Registry bundle

Install the exact registry entry shown on the right when you want the component file and its declared runtime dependencies together.

Dependencies: motion, lucide-react.

Contact

Additionally, if you find any bug or issue, feel free to raise an issue.

Invite Team Member

Share tasks with other users

Email

Member Lists

  • Trevor PhillipsTrevor Phillipstrevorphillips@gmail.com
  • Michael De SantaMichael De Santamichaeldesanta@gmail.com
  • Franklin ClintonFranklin Clintonfranklinclinton@gmail.com