Updated
Invite Members
NewCustomize
Seats10
Duration0.45s
Installation
npx shadcn@latest add https://uibrik.com/r/invite-members.jsonInstall the packages
npm install @tabler/icons-react motion react-use-measureAdd the cn helper
Imports
cnfrom@/lib/utils, whichshadcn initcreates. Add it by hand without shadcn.Copy the source into your project
components/uibrik/invite-members/invite-members.tsx"use client"; import { useId, useRef, useState, type ClipboardEvent, type KeyboardEvent, type ReactNode } from "react"; import { AnimatePresence, LayoutGroup, MotionConfig, motion } from "motion/react"; import useMeasure from "react-use-measure"; import { IconChevronDown, IconLoader2, IconUser, IconX } from "@tabler/icons-react"; import { DropdownMenu, type MenuItem } from "../dropdown-menu/dropdown-menu"; import { cn } from "@/lib/utils"; // Invite members. Type or paste addresses (any mix of commas, spaces, semicolons // and new lines) and each one becomes a chip. Addresses that aren't valid, or // belong to someone already on the team, turn red with a small shake; click // one to pull it back into the field and fix it. Sending flies each address // out of its chip and into its own row in the member list, where the rest of // the list makes room. Roles change from each row's menu. export type Member = { id: string; email: string; name?: string; role: string; /** Pending members have been invited but haven't joined yet. */ status?: "active" | "pending"; /** Image URL. Initials are shown without one. */
Adds the files to
components/uibrik/invite-members and installs @tabler/icons-react, motion and react-use-measure. With the @uibrik namespace set up: npx shadcn@latest add @uibrik/invite-members. Builds on Dropdown Menu.Usage
import { InviteMembers } from "@/components/uibrik/invite-members/invite-members";const defaultMembers = [ { id: "m1", name: "Clara Novak", email: "clara@northwind.co", role: "admin", avatar: "/registry/invite-members/clara.webp" }, { id: "m2", name: "Kofi Mensah", email: "kofi@northwind.co", role: "member", avatar: "/registry/invite-members/kofi.webp" }, // …3 more];const roles = [ { value: "admin", label: "Admin" }, { value: "member", label: "Member" }, // …1 more];<InviteMembers title="Invite members" placeholder="Emails, separated by commas" seats={10} duration={0.45} defaultMembers={defaultMembers} roles={roles} onInvite={(emails, role) => {}} // members={[…]} // onMembersChange={(members) => {}} // defaultRole="…"/>Where to use Invite Members
SaaS onboarding
Pasting a list of emails that become chips makes inviting a team fast.
Pairs with Tag Input
Team settings
Bad or duplicate addresses shaking red prevent wasted invites.
Pairs with Permissions Matrix
Project sharing
Addresses flying into the member list confirm who was added.
Pairs with Avatar Stack
Props
InviteMembers- title
- Type string
- "Invite members"
- Heading at the top of the card.
- placeholder
- Type string
- "Emails, separated by commas"
- Shown in the empty field.
- seats
- Type number
- 10
- Seats on the plan. Invites stop once they're used up.
- duration
- Type number
- 0.45
- How long chips and rows take to move.
- members / onMembersChange
- Type Member[] / (members) => void
- –
- Controlled member list. A member is { id, email, name?, role, status?: "active" | "pending", avatar? }.
- defaultMembers
- Type Member[]
- –
- Members on mount when uncontrolled.
- onInvite
- Type (emails, role) => void | Promise
- –
- Called when invites are sent. Return a promise to show a spinner until it settles; if it rejects, the chips stay put.
- roles
- Type (string | { value; label })[]
- Admin, Member, Viewer
- Roles offered for invites and in each row's menu.
- defaultRole
- Type string
- –
- Role picked for new invites on mount. Defaults to the second role.
- className
- Type string
- –
- Classes for the card.