diff --git a/src/components/ui/avatar-stack.tsx b/src/components/ui/avatar-stack.tsx new file mode 100644 index 000000000..fe0aa13c7 --- /dev/null +++ b/src/components/ui/avatar-stack.tsx @@ -0,0 +1,107 @@ +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { cn } from "@/lib/utils"; +import { type VariantProps, cva } from "class-variance-authority"; +import type * as React from "react"; + +const avatarStackVariants = cva("flex", { + variants: { + orientation: { + vertical: "flex-col", + horizontal: "flex-row", + }, + spacing: { + sm: "-space-x-5 -space-y-5", + md: "-space-x-4 -space-y-4", + lg: "-space-x-3 -space-y-3", + xl: "-space-x-2 -space-y-2", + }, + }, + defaultVariants: { + orientation: "horizontal", + spacing: "md", + }, +}); + +export interface AvatarStackProps + extends React.HTMLAttributes, + VariantProps { + avatars: { name: string; image: string }[]; + maxAvatarsAmount?: number; +} + +const AvatarStack = ({ + className, + orientation, + avatars, + spacing, + maxAvatarsAmount = 3, + ...props +}: AvatarStackProps) => { + const shownAvatars = avatars.slice(0, maxAvatarsAmount); + const hiddenAvatars = avatars.slice(maxAvatarsAmount); + + return ( +
+ {shownAvatars.map(({ name, image }, index) => ( + + + + + + + {name + ?.split(" ") + ?.map((word) => word[0]) + ?.join("") + ?.toUpperCase()} + + + + +

{name}

+
+
+
+ ))} + + {hiddenAvatars.length ? ( + + + + + + +{avatars.length - shownAvatars.length} + + + + + {hiddenAvatars.map(({ name }, index) => ( +

{name}

+ ))} +
+
+
+ ) : null} +
+ ); +}; + +export { AvatarStack, avatarStackVariants };