webdevpuneet.com

Shared Document Presence Bar — Free HTML CSS JS Snippet

Shared Document Presence Bar · Cards · Plain HTML, CSS & JS · Live preview

CategoryCards

Copy & paste

Source Code

<div class="sdp-page">
  <div class="sdp-bar">
    <div class="sdp-left">
      <svg class="sdp-doc-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>
      <span class="sdp-title">Roadmap 2026.doc</span>
    </div>
    <div class="sdp-right">
      <div class="sdp-stack" id="sdpStack"></div>
      <button type="button" class="sdp-share">Share</button>
    </div>
  </div>
  <div class="sdp-body">
    <div class="sdp-line w1"></div>
    <div class="sdp-line w2"></div>
    <div class="sdp-line w3"></div>
    <div class="sdp-line w2"></div>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Overlapping bubble stack
Negative margins create a compact, fixed-footprint avatar stack from any headcount.
Editing/viewing status dots
A color-coded corner dot distinguishes active editors from read-only viewers.
Honest overflow count
A "+N" bubble reports exactly how many collaborators aren't individually shown.
Hover tooltips
Full name and status text appear on hover without permanently using bar space.
Data-driven rendering
One PEOPLE array drives the whole bar — no manual bubble markup.
Predictable bar width
The visible stack never grows past MAX_VISIBLE, keeping the header layout stable.
Truncated document title
Long file names ellipsize instead of pushing the presence stack off-screen.
Framework-agnostic markup
Plain HTML/CSS/JS ports cleanly into React, Vue, or Angular components.

About this UI Snippet

Shared Document Presence Bar — Who's Viewing, Editing & the Overflow Count

Screenshot of the Shared Document Presence Bar snippet rendered live

Every collaborative document tool needs a fast answer to "who else is here right now" without opening a separate panel. The presence bar puts that answer directly in the document's top bar: a compact stack of avatar bubbles, a colored status dot showing who's actively editing versus just viewing, and an overflow bubble once the room gets crowded. This snippet builds that bar in plain HTML, CSS, and vanilla JavaScript. Compare it with collaborator presence bar and avatar stack tooltip for related patterns.

Overlapping bubbles from one array

PEOPLE holds everyone currently in the document, each with a name, initials, color, and a status of 'editing' or 'viewing'. render() slices the first MAX_VISIBLE entries and lays them out with a negative left margin so each bubble overlaps the previous one — the same compact-stack technique used in avatar stack, giving a crowd of people a tidy, fixed-width footprint regardless of how many are actually present.

Editing vs viewing at a glance

Rather than a text label per person, each bubble gets a small corner dot: green for actively editing, gray for read-only viewing. This is the same visual grammar used by Google Docs and Notion — a quick color scan tells you whether anyone is actively changing the document right now versus just reading it, which matters far more than an exact headcount when you're deciding whether it's safe to make your own edit.

Overflow that stays honest

When more people are present than MAX_VISIBLE allows, a final "+N" bubble is appended showing exactly how many additional collaborators aren't shown — never silently dropping people from the count. This keeps the bar's width predictable (it never grows past five bubbles) while still being truthful about how many people are actually in the document.

Tooltips confirm identity on demand

Hovering any avatar bubble reveals a small tooltip with the person's full name and their current status in words ("editing" or "viewing"), so the compact initials-only bubbles never leave you guessing who's who — full identity is one hover away, not permanently taking up bar space.

Extending it for real presence

To wire this to real collaboration, replace PEOPLE with live presence data from your backend (a WebSocket channel, Supabase Realtime, Liveblocks, or similar), re-running render() whenever someone joins, leaves, or switches between editing and viewing. Add a click handler on the overflow bubble to open a full presence panel — a natural pairing with team presence list.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA document top bar renders with four overlapping avatar bubbles and a "+2" overflow bubble.
  2. 2
    Hover a bubbleA tooltip shows the person's name and whether they're editing or viewing.
  3. 3
    Look at the corner dotsGreen dots mean actively editing; gray dots mean read-only viewing.
  4. 4
    Check the overflow bubbleIt shows exactly how many additional people aren't shown in the stack.
  5. 5
    Change MAX_VISIBLEShow more or fewer bubbles before the overflow count kicks in.
  6. 6
    Connect real presenceReplace PEOPLE with live data from your collaboration backend and re-render on change.

Real-world uses

Common Use Cases

Collaborative document editors
Answer who else is here at a glance, with overlapping avatar bubbles and a coloured corner dot separating editors from viewers.
Design and whiteboard tools
Pair with live cursor name tags so the top bar shows who is present and the canvas shows where they are working.
Project management boards
Show active viewers on a kanban board, with an honest +N bubble reporting how many collaborators do not fit.
Code review and IDE tools
Indicate who else has a file open, using hover tooltips so full names and statuses do not permanently take up space.
Scheduling and team dashboards
Combine with an availability scheduler or a team presence list for a fuller picture of who is around.
Related: File Explorer Tree View
See the File Explorer Tree View for a related navigation pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

render() slices the PEOPLE array to the first MAX_VISIBLE entries for bubbles, then computes the overflow as PEOPLE.length minus that visible count. Because the overflow number is always derived from the real array length rather than hard-coded, it stays accurate automatically as people join or leave — there's no separate counter to keep in sync.

Each person in the data has a status of "editing" or "viewing", which maps to a green or gray corner dot on their bubble respectively (plus the matching word in the hover tooltip). This mirrors how Google Docs and Notion distinguish someone actively typing changes from someone who merely has the document open in read mode.

Add a click handler to .sdp-overflow that opens a dropdown, popover, or modal listing the remaining PEOPLE entries beyond MAX_VISIBLE — reusing the same bubble/tooltip markup at a larger scale, similar to how team presence list shows a fuller roster.

Replace the static PEOPLE array with data from your realtime backend (WebSocket, Supabase Realtime, Liveblocks, Firebase, etc.), and call render() again whenever a presence event arrives — someone joining, leaving, or switching between editing and viewing. Because render() is a pure function of the array, you never need to manually patch individual bubbles.

Pass PEOPLE as a prop or reactive state, derive the visible slice and overflow count with a computed value (useMemo, a Vue computed, or an Angular pipe), and map the visible array to bubble components with their status class and tooltip. The overlapping-stack CSS ports unchanged.