Live Presence
Show who else is in a shared space right now so collaborators feel each other and avoid colliding.
On this page now
ALGHATKJ
7 people viewing+3
Example result — your output may vary with your context and the prompt you pass.
# Live Presence: Avatar Stack
## Context
Flexnative UI intent — a reference solution from the shadcn/ui registry (@flx). The intent frames the problem; the decision is one approach to it.
## Problem
Show who else is in a shared space right now so collaborators feel each other and avoid colliding.
## Decision
- Best for: The default ambient signal in a header or toolbar. A row of overlapping faces with an overflow count tells everyone who is here without taking real estate or stealing focus.
- Trade-off: It answers who but not where or what, so on its own it cannot stop two people editing the same thing at once.
## Registry Item
@flx/live-presence-1
## Stack
- UI: shadcn/ui
- Styling: Tailwind CSS
- shadcn components: Avatar, Card, Tooltip
## Registry Source
https://ui.flexnative.com/r/live-presence-1.json
## Preview
https://ui.flexnative.com/intents/live-presence#1
## Reference Implementation
```tsx
'use client'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/components/ui/tooltip'
type Viewer = { id: string; name: string; avatar: string }
const VIEWERS: Viewer[] = [
{
id: 'ada',
name: 'Ada Lovelace',
avatar:
'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=128&h=128&fit=crop&crop=faces',
},
{
id: 'grace',
name: 'Grace Hopper',
avatar:
'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=128&h=128&fit=crop&crop=faces',
},
{
id: 'alan',
name: 'Alan Turing',
avatar:
'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=128&h=128&fit=crop&crop=faces',
},
{
id: 'katherine',
name: 'Katherine Johnson',
avatar:
'https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?w=128&h=128&fit=crop&crop=faces',
},
]
const OVERFLOW = 3
export function LivePresence1() {
return (
<Card>
<CardHeader>
<CardTitle>On this page now</CardTitle>
</CardHeader>
<CardContent className="flex flex-wrap items-center gap-3">
<div className="flex -space-x-2">
{VIEWERS.map((viewer) => (
<Tooltip key={viewer.id}>
<TooltipTrigger asChild>
<Avatar className="ring-background size-9 ring-2">
<AvatarImage src={viewer.avatar} alt={viewer.name} />
<AvatarFallback className="bg-muted text-xs">
{viewer.name
.split(' ')
.map((n) => n[0])
.join('')}
</AvatarFallback>
</Avatar>
</TooltipTrigger>
<TooltipContent>{viewer.name}</TooltipContent>
</Tooltip>
))}
<Tooltip>
<TooltipTrigger asChild>
<div className="bg-muted text-muted-foreground ring-background flex size-9 items-center justify-center rounded-full text-xs font-medium ring-2">
+{OVERFLOW}
</div>
</TooltipTrigger>
<TooltipContent>3 more viewing</TooltipContent>
</Tooltip>
</div>
<span className="text-muted-foreground text-sm">
{VIEWERS.length + OVERFLOW} people viewing
</span>
</CardContent>
</Card>
)
}
```Paste into your AI tool and adapt it to your context.
Other ways
Reach for these when the context shifts. Each is copyable too.
Who is here
AL
Ada LovelacePricing section
EditingGH
Grace HopperExecutive summary
ViewingAT
Alan TuringAway for 5m
IdleActivity Status