Avatar GroupiOS
Overlapping avatar stack with a border ring per avatar, staggered pop-in, and a tappable "+N" overflow bubble
$ npx lumioui add avatar-group
import { AvatarGroup } from "@/components/ui/avatar-group/avatar-group";
Files installed into your repo
components/ui/avatar-group/avatar-group.tsx
Registry dependencies (installed automatically)
Native packages required
@lumioui/core@latestreact-native-reanimated@*
Props8
| items | AvatarGroupItem[] | |
| max? | number | Max avatars rendered before the "+N" overflow bubble. Default 4. |
| size? | "sm" | "md" | "lg" | Avatar size. Default "md". |
| onItemPress? | (item: AvatarGroupItem, index: number) => void | Fired when an avatar is tapped — makes avatars pressable. |
| onOverflowPress? | (items: AvatarGroupItem[]) => void | Makes the "+N" bubble tappable (open the full roster). |
| animate? | boolean | Staggered pop-in on mount. Default true. |
| haptic? | "light" | "selection" | false | Haptic on taps. Default "light". |
| className? | string | |
Avatar Group — Overflowoverflow.tsx
Live preview offline the relay is unreachable — check back shortly
avatar-group/variants/overflow.tsx open Overlapping avatar stack with a border ring per avatar, staggered pop-in, and a tappable "+N" overflow bubble
import { AvatarGroupOverflow } from "@/components/ui/avatar-group/variants/overflow";
export function Example() {
return (
<AvatarGroupOverflow />
);
}
import * as React from "react";
import { View } from "react-native";
import { AvatarGroup } from "../avatar-group";
import { Text } from "../../text/text";
import { Glass } from "../../glass/glass";
const TEAM = [
{ source: { uri: "https://i.pravatar.cc/150?img=47" }, fallback: "AC", alt: "Amara Chen" },
{ source: { uri: "https://i.pravatar.cc/150?img=15" }, fallback: "JT", alt: "Jon Tanaka" },
{ source: { uri: "https://i.pravatar.cc/150?img=59" }, fallback: "SK", alt: "Sofia Kovacs" },
{ fallback: "MR", alt: "Marta Reyes" },
{ source: { uri: "https://i.pravatar.cc/150?img=25" }, fallback: "AH", alt: "Amir Haddad" },
{ fallback: "PN", alt: "Priya Nair" },
{ source: { uri: "https://i.pravatar.cc/150?img=33" }, fallback: "LB", alt: "Lena Beck" },
];
/** AvatarGroupOverflow — 7 collaborators, max 4 visible → "+3" bubble. */
export function AvatarGroupOverflow() {
const [last, setLast] = React.useState("7 collaborators on Lisbon crew");
return (
<View className="w-full gap-3">
<Glass interactive curvature="edge" className="w-full gap-3 rounded-2xl p-4">
<View className="flex-row items-center justify-between">
<Text variant="small" className="font-semibold">Lisbon crew</Text>
<AvatarGroup
items={TEAM}
max={4}
onItemPress={(item) => setLast(`Opened ${item.alt ?? "avatar"}`)}
onOverflowPress={(rest) => setLast(`${rest.length} more collaborators`)}
/>
</View>
<Text variant="muted">{last}</Text>
</Glass>
</View>
);
}
Avatar Group — Sizessizes.tsx
Live preview offline the relay is unreachable — check back shortly
avatar-group/variants/sizes.tsx open Overlapping avatar stack with a border ring per avatar, staggered pop-in, and a tappable "+N" overflow bubble
import { AvatarGroupSizes } from "@/components/ui/avatar-group/variants/sizes";
export function Example() {
return (
<AvatarGroupSizes />
);
}
import * as React from "react";
import { View } from "react-native";
import { AvatarGroup } from "../avatar-group";
import { Text } from "../../text/text";
import { Glass } from "../../glass/glass";
const PAIR = [
{ source: { uri: "https://i.pravatar.cc/150?img=32" }, fallback: "EM", alt: "Eli Mora" },
{ fallback: "KO", alt: "Kai Osei" },
{ source: { uri: "https://i.pravatar.cc/150?img=44" }, fallback: "RV", alt: "Ruth Vega" },
];
/** AvatarGroupSizes — the stack at sm, md, and lg. */
export function AvatarGroupSizes() {
return (
<View className="w-full gap-3">
<Glass interactive curvature="edge" className="w-full gap-4 rounded-2xl p-4">
{(["sm", "md", "lg"] as const).map((size) => (
<View key={size} className="flex-row items-center gap-3">
<Text variant="small" className="w-8 uppercase">{size}</Text>
<AvatarGroup items={PAIR} size={size} max={2} />
</View>
))}
</Glass>
</View>
);
}