# Empty State 02 - Invite Your Team

> A centered empty state with a custom illustration, heading, description, and two calls-to-action for inviting teammates or copying a shareable invite link, complete with an animated copy confirmation.

A shadcn/ui block from the [@shadcn-space](https://shadcnspace.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/shadcn-space/empty-state-02).

- Page, with a live preview: https://shadcn.exchange/r/shadcn-space/empty-state-02
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/shadcn-space/empty-state-02-light-ebee6020440f9074.png
- Registry item: https://shadcnspace.com/r/empty-state-02.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://shadcnspace.com/r/empty-state-02.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `lucide-react`, `motion`
- Registry items: `button`, `empty`

## Files

### `src/components/shadcn-space/blocks/empty-state-02/page.tsx`

```tsx
import EmptyState from "@/components/shadcn-space/blocks/empty-state-02/empty-state";

const Page = () => {
  return <EmptyState />;
};

export default Page;
```

### `src/components/shadcn-space/blocks/empty-state-02/empty-state.tsx`

```tsx
"use client";

import { useRef, useState } from "react";
import type { ReactNode } from "react";
import {
  AnimatePresence,
  motion,
  useInView,
  type Variants,
} from "motion/react";
import { Button } from "@/components/ui/button";
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from "@/components/ui/empty";
import { cn } from "@/lib/utils";
import { Check, Copy, Plus } from "lucide-react";

const COPIED_RESET_MS = 1800;

interface EmptyStateAction {
  label: string;
  icon?: ReactNode;
  onClick?: () => void;
}

interface EmptyStateProps {
  title?: string;
  description?: string;
  inviteLink?: string;
  primaryAction?: EmptyStateAction;
  secondaryAction?: EmptyStateAction;
}

const EASE = [0.16, 1, 0.3, 1] as const;

const containerVariants: Variants = {
  hidden: {},
  show: {
    transition: {
      staggerChildren: 0.1,
      delayChildren: 0.05,
    },
  },
};

const itemVariants: Variants = {
  hidden: { opacity: 0, y: 12 },
  show: {
    opacity: 1,
    y: 0,
    transition: { duration: 0.5, ease: EASE },
  },
};

const EmptyStateIllustration = () => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    width="120"
    height="120"
    viewBox="0 0 120 120"
    fill="none"
    className="size-30 shrink-0 text-foreground"
  >
    <path
      d="M54.3867 9.2849C61.6246 9.09881 68.2282 10.2864 74.8633 13.2467C85.985 18.3011 94.6586 27.5461 98.994 38.9673C103.318 50.2424 102.95 62.7797 97.9692 73.7813C98.7971 73.7725 99.85 73.8487 100.693 73.8815C102.275 73.9324 103.857 74.0262 105.435 74.1615C107.659 74.335 109.285 74.3555 110.988 76.0002C111.755 76.7338 112.317 77.6543 112.619 78.6715C112.935 79.7508 112.962 82.016 113.009 83.2078C113.093 85.2305 113.155 87.2543 113.196 89.2787C113.258 93.1043 113.203 96.9311 113.032 100.753C112.878 104.345 113.136 106.271 110.294 108.857C108.435 110.549 106.215 110.631 103.829 110.92C100.918 111.271 97.934 111.406 95.0114 111.444C93.1393 111.458 91.2672 111.425 89.3969 111.344C85.8737 111.221 80.8135 111.154 78.1405 108.544C75.9619 106.417 75.7961 102.81 75.7832 99.9317C75.7762 99.2291 75.7938 98.5002 75.8026 97.7953C74.3653 98.492 73.0885 99.1242 71.6055 99.7278C67.0053 101.585 62.1426 102.713 57.1943 103.069C44.7879 103.905 32.4348 100.285 23.0185 92.0309C13.5247 83.5658 7.72999 71.7153 6.87927 59.0238C6.11602 46.9382 10.2204 35.0494 18.2773 26.0086C24.1531 19.3481 31.2656 14.4394 39.8245 11.8476C40.6187 11.5038 41.6707 11.5737 42.4477 11.3313C46.4448 10.0849 50.214 9.54506 54.3867 9.2849ZM50.9623 65.7785C54.6274 67.4543 57.0215 67.3682 60.8108 65.952C62.1367 65.4703 63.4293 64.9002 64.6803 64.2469C67.2508 62.9104 69.3198 61.3694 72.2108 62.8254C76.9446 65.209 80.3272 69.7576 83.0969 74.0678C84.7885 74.0039 86.5446 73.8627 88.2713 73.7942C90.618 73.7121 92.9658 73.6729 95.3137 73.6781C95.6137 72.8965 96.0086 72.0961 96.3321 71.3086C96.8987 69.9293 97.392 68.5213 97.8092 67.0904C100.646 57.3326 99.9139 46.8835 95.7455 37.6162C91.0914 27.069 82.4489 18.7953 71.7086 14.6063C67.4506 12.9737 62.9588 12.0345 58.404 11.8244C57.1993 11.7583 55.5834 11.7075 54.3745 11.8025C52.5602 11.9094 51.0094 12.023 49.2052 12.3172C39.3762 13.8872 30.3901 18.8009 23.7641 26.2285C16.072 34.8186 12.1263 46.1233 12.8026 57.6342C13.3059 66.4951 16.5421 74.983 22.066 81.9299C23.5415 79.3658 24.9838 76.834 26.7299 74.4363C29.8676 70.1285 36.4004 63.2889 41.7308 61.8721C43.0637 61.5182 44.0986 61.7256 45.2765 62.4176C47.2364 63.5695 48.8313 64.8334 50.9623 65.7785ZM23.7688 84.0024C31.7784 92.7164 42.2937 97.9401 54.1853 98.4405C57.3553 98.5834 60.5313 98.3766 63.6561 97.8235C64.2121 97.7244 65.1631 97.558 65.6951 97.4086C68.4965 96.7776 71.227 95.8629 73.8438 94.6787C74.4268 94.4156 75.3162 94.0172 75.8412 93.6774C75.986 91.0447 75.8852 88.2451 75.9649 85.5961C76.027 83.5336 75.9133 81.1559 76.5473 79.1754C76.941 77.983 77.6401 76.9143 78.5752 76.0752C79.3141 75.4166 79.8192 75.2145 80.7508 74.9912C78.4405 71.5125 76.4237 68.6813 72.993 66.1787C69.8582 63.6551 68.7028 64.9951 65.6565 66.5584C62.8018 68.0238 58.8221 69.5836 55.5445 69.5203C51.9025 69.4506 48.1543 67.343 45.1933 65.332C44.2292 64.677 43.7913 64.0846 42.4948 64.2369C41.0994 64.6319 38.7511 65.8717 37.5451 66.8338C34.4487 69.3035 31.4116 72.3487 29.0106 75.4986C27.3145 77.7235 25.9444 80.0807 24.5735 82.4994C24.314 82.9629 23.9948 83.5248 23.7688 84.0024ZM99.8289 107.776C101.557 107.695 103.284 107.596 105.009 107.479C106.625 107.375 108.201 107.513 109.411 106.199C110.494 105.024 110.415 103.809 110.491 102.292C110.55 101.282 110.597 100.272 110.631 99.2602C110.833 93.0961 110.757 86.8641 110.418 80.7024C110.347 79.4186 110.097 78.5619 109.122 77.6655C108.739 77.3127 108.116 76.9904 107.604 76.9061C106.318 76.6934 104.849 76.6031 103.547 76.5147C99.2899 76.2164 95.0207 76.1127 90.7545 76.2035C89.602 76.234 88.45 76.2791 87.2987 76.3395C85.4518 76.4244 82.6908 76.3723 81.325 77.7938C81.0162 78.1119 80.7918 78.5027 80.674 78.9299C80.4871 79.6031 80.3758 81.7799 80.3225 82.5621C79.9498 88.1174 79.8813 93.6891 80.118 99.252C80.1596 100.319 80.2668 104.027 80.5621 104.919C80.7514 105.489 81.0848 106 81.5301 106.403C82.518 107.314 83.5621 107.331 84.8254 107.474C89.6606 108.022 94.5848 108.031 99.4446 107.797C99.5729 107.791 99.7012 107.784 99.8289 107.776Z"
      fill="currentColor"
    />
    <path
      d="M58.8187 17.2479C63.0187 16.8957 67.2533 18.6239 69.8741 21.9592C73.0452 25.9941 74.0062 31.1612 74.857 36.0893C75.539 40.099 76.0945 44.126 76.1958 48.198C76.2409 50.0136 76.3552 51.7163 75.8905 53.4959C75.3667 55.501 74.0671 56.7566 72.0111 57.1163C70.3622 57.4048 68.9032 56.6485 67.2714 56.7006C66.549 56.7237 65.8294 56.9153 65.1234 57.0573C63.7212 57.3602 62.3074 57.536 60.8741 57.3619C60.512 57.3179 60.1517 57.1849 59.7866 57.1709C59.3126 57.18 58.7226 57.4448 58.2491 57.5526C56.8094 57.9852 55.2943 57.9945 53.8147 57.7944C53.3738 57.7348 52.9434 57.657 52.4992 57.6261C51.9839 57.5902 51.6436 57.7212 51.1652 57.8818C48.9215 58.572 46.5173 58.536 44.2954 57.7789C43.4202 57.4777 42.5403 57.0456 41.6058 57.0601C39.9838 57.0764 38.4806 58.1142 36.8252 57.8673C34.9922 57.594 34.055 56.0193 34.1083 54.271C34.147 53.001 34.322 51.8772 34.5214 50.638C34.7841 49.0805 35.0379 47.5216 35.2829 45.9612C35.5457 44.2873 35.7789 42.6087 35.9823 40.9265C36.8693 33.3588 37.5271 23.8335 46.3688 20.8996C47.9213 20.3844 49.2416 20.4503 50.8386 20.662C53.3589 18.4973 55.5545 17.6576 58.8187 17.2479ZM66.8074 36.3665C66.1218 35.4078 65.2124 34.5989 64.5931 33.5551C64.4331 33.2864 63.8759 32.381 63.6925 32.2588C62.0788 33.8074 60.5273 35.357 59.1216 37.1034C58.8111 37.4893 58.4283 37.9485 58.0571 38.2863C56.211 39.5744 54.3491 34.6952 53.8379 33.7137C52.4754 35.3163 50.8295 36.9887 49.6012 38.6885C47.8957 41.0488 47.4793 40.3695 45.4727 38.6869C44.3894 37.781 43.7261 36.7792 42.8121 35.7112C42.6548 36.0097 41.9154 37.2726 41.919 37.528C41.9636 40.7298 42.9609 44.1541 44.1221 47.1096C44.8069 48.5698 45.4246 49.7202 46.4729 50.9478C49.3906 54.3646 54.6916 56.7772 59.0132 54.652C65.1603 51.6289 66.4001 45.1198 66.6685 38.9471C66.706 38.0832 66.8033 37.229 66.8074 36.3665ZM38.8263 37.5275C38.3811 42.9215 37.3195 48.2992 36.6016 53.6598C36.2775 56.0803 37.866 55.4466 39.4847 54.9137C42.2405 54.0063 43.1651 54.9156 45.6293 55.5983C46.6888 55.8912 47.4002 55.8915 48.5002 55.9127C47.5207 55.2299 46.5838 54.5685 45.7261 53.7415C41.8972 50.0494 40.1987 44.7004 39.5786 39.543C39.5021 38.9065 39.4568 37.8848 38.8263 37.5275ZM67.8908 33.8029C68.9742 32.7056 70.0699 31.6212 71.179 30.55C70.1284 26.7313 68.6419 23.1111 65.0132 21.004C63.4212 20.0797 60.924 19.507 59.0988 19.7677C56.7749 20.023 55.0128 20.5574 53.1022 22.0112C52.2795 22.6371 52.2027 23.006 51.2173 23.3527C45.1124 21.6822 41.2114 26.9645 39.788 32.2325C39.6459 32.769 39.5155 33.3084 39.3968 33.8505C39.6649 34.3105 39.9671 34.7497 40.3008 35.1646L40.363 35.0666C40.6689 34.5802 41.0041 33.9312 41.2547 33.4359C42.6139 30.7492 43.7734 32.1603 44.7558 34.1032C45.1661 34.9146 46.7999 36.6825 47.6048 37.2134C49.1655 35.2148 50.826 33.2963 52.5799 31.465C53.1639 30.8248 54.3224 29.3525 55.3117 30.3746C55.8354 30.9156 55.9053 32.1133 56.1904 32.8041C56.475 33.5746 56.9259 34.6491 57.4325 35.2816C59.0718 33.2269 61.0863 31.2672 63.0322 29.496C63.3122 29.2406 63.6532 28.9863 64.0441 28.9546C64.3886 28.9276 64.7284 29.047 64.9804 29.2835C65.2452 29.5276 65.9982 31.1296 66.2747 31.5918C66.7394 32.38 67.2808 33.1205 67.8908 33.8029ZM71.7415 33.5046C71.1468 34.0275 70.5972 34.5916 70.0271 35.136C69.4282 35.7078 69.2993 35.9803 69.2548 36.8158C68.9179 43.1847 68.6202 49.9713 63.4915 54.5636C63.3802 54.6632 63.2677 54.7617 63.1534 54.8588C64.0997 54.7727 64.7015 54.6274 65.6109 54.3967C66.6269 54.1597 67.1501 54.1573 68.1409 54.23C69.5941 54.3365 72.1757 55.4473 73.105 53.7786C74.1615 51.8816 73.7484 48.5068 73.5984 46.3771C73.3657 42.8169 72.9333 39.2725 72.3017 35.7609C72.2361 35.3911 71.9794 33.7365 71.8687 33.5433L71.7415 33.5046Z"
      fill="currentColor"
    />
    <path
      d="M56.0619 83.5142C56.3683 83.482 56.6244 83.4779 56.9192 83.5758C57.3057 83.7012 57.6244 83.9783 57.8016 84.3439C58.3263 85.4004 57.7195 86.5254 56.7197 87.0187C55.7825 87.2719 54.9339 86.6648 54.8183 85.7074C54.7181 84.8765 54.934 84.331 55.4221 83.6906C55.6331 83.6162 55.845 83.5682 56.0619 83.5142Z"
      fill="currentColor"
    />
    <path
      d="M56.3199 74.3144C58.5849 74.2394 58.6353 77.2576 56.6536 77.8635C54.6843 78.0756 54.4499 75.7974 55.5497 74.475L56.3199 74.3144Z"
      fill="currentColor"
    />
    <path
      d="M56.2872 90.9557C57.0592 90.9797 57.671 91.2978 57.897 92.0807C58.0394 92.5816 57.9806 93.1189 57.7332 93.5777C57.4285 94.1314 57.0284 94.3728 56.4408 94.5281C54.8651 94.633 54.3516 92.659 55.1503 91.558C55.5162 91.0541 55.7181 91.0523 56.2872 90.9557Z"
      fill="currentColor"
    />
    <path
      d="M93.7256 82.3406C94.6784 82.2188 95.2971 82.6025 95.3317 83.6027C95.368 84.6609 95.3803 85.7449 95.3592 86.8043C95.3287 88.309 95.4307 89.8811 95.3358 91.3775C96.9653 91.3875 98.5953 91.3893 100.225 91.3828C101.076 91.3816 101.918 91.3705 102.769 91.4092C103.587 91.4467 104.197 91.9072 104.08 92.7856C104.038 93.1336 103.847 93.4465 103.556 93.6434C102.758 94.1959 97.7211 93.7893 96.4748 93.9217C96.2405 93.9469 95.6328 93.9064 95.3979 93.8578C95.2737 95.6766 95.4078 97.7256 95.3616 99.5637C95.3416 100.362 95.4231 101.263 95.2754 102.052C95.2004 102.453 94.9286 102.653 94.6028 102.864C93.762 103.074 92.9926 102.807 92.9153 101.844C92.8403 100.914 92.8789 99.9668 92.8807 99.0322L92.8778 93.9111C91.6174 93.9686 90.1555 93.8918 88.8659 93.917C87.6905 93.9387 86.5397 93.9311 85.3696 93.8795C83.7418 93.808 83.7688 91.6389 85.0994 91.4367C85.8459 91.323 86.9616 91.3793 87.7444 91.3811L92.852 91.3904C92.8825 89.7064 92.8912 88.0225 92.8795 86.3385C92.8789 85.6219 92.8684 84.9 92.8784 84.184C92.8912 83.2512 92.8362 82.807 93.7256 82.3406Z"
      fill="currentColor"
    />
    <path
      d="M101.078 13.8409C102.053 13.8024 102.378 14.107 102.68 14.9933C102.665 15.0547 102.65 15.116 102.633 15.177C102.55 15.4845 102.472 15.6306 102.277 15.8845C101.83 16.4588 101.333 17.0005 100.843 17.5407C99.4922 19.0334 98.1885 20.5745 96.8098 22.0415C96.6692 22.1913 96.4506 22.3248 96.2737 22.429C96.0516 22.4644 95.8307 22.4771 95.6163 22.399C95.253 22.2665 94.9049 21.9951 94.7532 21.6314C94.6436 21.3682 94.6571 21.0824 94.7626 20.8205C94.9776 20.2862 99.9194 14.7459 100.566 14.16C100.723 14.0177 100.885 13.9264 101.078 13.8409Z"
      fill="currentColor"
    />
    <path
      d="M104.546 26.5086C105.772 26.4727 109.043 26.1027 108.747 27.9449C108.668 28.4393 108.46 28.6653 108.079 28.9544C107.484 29.088 106.126 29.0137 105.46 29.0133C104.32 29.0126 103.558 29.0615 102.437 29.2349C101.725 29.3069 100.981 29.5285 100.293 29.6605C99.4467 29.8612 98.6774 29.5554 98.5907 28.6008C98.4741 27.3204 99.909 27.1594 100.832 26.9646C102.066 26.7042 103.294 26.5895 104.546 26.5086Z"
      fill="currentColor"
    />
    <path
      d="M92.4021 8.61638C93.2956 8.50406 94.2495 9.1483 93.9156 10.062C93.3788 11.5296 92.6411 12.8793 92.3113 14.4342C92.1232 15.323 92.0658 16.2373 91.8255 17.1062C91.7218 17.4799 91.4007 17.6839 91.0691 17.837C90.6185 17.8851 89.7472 17.7941 89.5949 17.2106C89.1812 15.6258 90.8939 9.18462 92.4021 8.61638Z"
      fill="currentColor"
    />
  </svg>
);

const EmptyState = ({
  title = "Bring your team on board",
  description = "Invite owners, editors, and reviewers by email or share a secure link collaboration starts the moment they join.",
  inviteLink = "https://app.shadcnspace.com/invite/2f9a7c1e",
  primaryAction = {
    label: "Invite member",
    icon: <Plus className="size-4" />,
  },
  secondaryAction = {
    label: "Copy invite link",
    icon: <Copy className="size-4" />,
  },
}: EmptyStateProps) => {
  const ref = useRef<HTMLDivElement>(null);
  const isInView = useInView(ref, { once: true, amount: 0.2 });
  const [copied, setCopied] = useState(false);

  const handleCopyClick = async () => {
    try {
      await navigator.clipboard.writeText(inviteLink);
      setCopied(true);
      window.setTimeout(() => setCopied(false), COPIED_RESET_MS);
    } catch {
      // Clipboard access denied or unavailable — no feedback shown.
    }
    secondaryAction?.onClick?.();
  };

  return (
    <div
      ref={ref}
      className="flex w-full items-center justify-center px-4 py-10 sm:py-16"
    >
      <motion.div
        variants={containerVariants}
        initial="hidden"
        animate={isInView ? "show" : "hidden"}
        className="flex w-92 max-w-full flex-col items-center gap-6"
      >
        <Empty className="gap-4 border-none p-0">
          <EmptyHeader className="gap-4">
            <motion.div variants={itemVariants}>
              <EmptyMedia variant="default" className="mb-0">
                <EmptyStateIllustration />
              </EmptyMedia>
            </motion.div>
            <motion.div
              variants={itemVariants}
              className="flex flex-col items-center gap-0.5"
            >
              <EmptyTitle className="text-lg font-medium text-foreground">
                {title}
              </EmptyTitle>
              <EmptyDescription className="text-center">
                {description}
              </EmptyDescription>
            </motion.div>
          </EmptyHeader>
          <motion.div variants={itemVariants}>
            <EmptyContent>
              <div className="flex items-start gap-3">
                {primaryAction && (
                  <motion.div
                    whileHover={{ scale: 1.03 }}
                    whileTap={{ scale: 0.97 }}
                    transition={{ duration: 0.2, ease: EASE }}
                    className="inline-flex"
                  >
                    <Button
                      size="lg"
                      onClick={primaryAction.onClick}
                      className="cursor-pointer px-4 hover:bg-primary/80"
                    >
                      {primaryAction.icon}
                      {primaryAction.label}
                    </Button>
                  </motion.div>
                )}
                {secondaryAction && (
                  <motion.div
                    whileHover={{ scale: 1.03 }}
                    whileTap={{ scale: 0.97 }}
                    transition={{ duration: 0.2, ease: EASE }}
                    className="inline-flex"
                  >
                    <Button
                      variant="outline"
                      size="lg"
                      onClick={handleCopyClick}
                      className={cn(
                        "relative cursor-pointer overflow-hidden px-4 transition-colors duration-300",
                        copied &&
                          "border-teal-400/50 dark:border-teal-400/50 text-teal-400 dark:text-teal-400 hover:text-teal-400",
                      )}
                    >
                      <motion.span
                        aria-hidden="true"
                        className="absolute inset-0 origin-left bg-teal-400/25"
                        initial={false}
                        animate={{ scaleX: copied ? 1 : 0 }}
                        transition={{
                          duration: copied ? COPIED_RESET_MS / 1000 : 0.2,
                          ease: copied ? "linear" : EASE,
                        }}
                      />
                      <span className="relative z-10 inline-flex items-center gap-1.5">
                        <AnimatePresence mode="wait" initial={false}>
                          <motion.span
                            key={copied ? "copied" : "copy"}
                            initial={{ opacity: 0, scale: 0.5 }}
                            animate={{ opacity: 1, scale: 1 }}
                            exit={{ opacity: 0, scale: 0.5 }}
                            transition={{ duration: 0.15, ease: EASE }}
                            className="inline-flex"
                          >
                            {copied ? (
                              <Check className="size-4" />
                            ) : (
                              secondaryAction.icon
                            )}
                          </motion.span>
                        </AnimatePresence>
                        {copied ? "Copied!" : secondaryAction.label}
                      </span>
                    </Button>
                  </motion.div>
                )}
              </div>
            </EmptyContent>
          </motion.div>
        </Empty>
      </motion.div>
    </div>
  );
};

export default EmptyState;
```
