Open demo

CSS code

HTML
<div class="duo">
<div><span class="lbl">Account menu</span>
<header class="um-bar">
  <span class="um-brand"><i aria-hidden="true"></i>Ledgerly</span>
  <div class="um">
    <button class="um-btn" type="button" aria-expanded="false" aria-controls="um-menu"><span class="um-av" aria-hidden="true">SM</span>Sofia<span class="sr-only"> Marchetti, account menu</span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M6.5 9.5 12 15l5.5-5.5"/></svg></button>
    <div class="um-menu" id="um-menu" hidden>
      <div class="um-head">
        <span class="um-av" aria-hidden="true">SM</span>
        <div><p class="um-name">Sofia Marchetti</p><p class="um-mail">[email protected]</p><span class="um-plan">Team plan · admin</span></div>
      </div>
      <p class="um-meter"><b>7.2 GB</b> of 10 GB used<span aria-hidden="true"></span></p>
      <ul class="um-links">
        <li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="8" r="4"/><path d="M4.5 20.5c.8-4 3.8-6 7.5-6s6.7 2 7.5 6"/></svg>Your profile</a></li>
        <li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></svg>Settings</a></li>
        <li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="2.5" y="5" width="19" height="14" rx="2.5"/><path d="M2.5 10h19M6.5 15h4"/></svg>Billing<small>Due 3 Nov</small></a></li>
        <li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="3.5" y="3.5" width="7" height="7" rx="1.5"/><rect x="13.5" y="3.5" width="7" height="7" rx="1.5"/><rect x="3.5" y="13.5" width="7" height="7" rx="1.5"/><rect x="13.5" y="13.5" width="7" height="7" rx="1.5"/></svg>Switch workspace</a></li>
      </ul>
      <div class="um-links um-out"><button type="button"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M14.5 4.5h3a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2h-3M10 16.5 14.5 12 10 7.5M14.5 12H3.5"/></svg>Sign out</button></div>
    </div>
  </div>
</header></div>

<div><span class="lbl">Team list with hover cards</span>
<section class="hl" aria-labelledby="hl-title">
  <h3 class="hl-title" id="hl-title">Q4 planning doc · 4 people</h3>
  <ul>
    <li><span class="hl-pic"><span class="um-av" aria-hidden="true">TL</span><i class="on" aria-hidden="true"></i></span>
      <div class="hl-who"><div class="hc"><a class="hc-name" href="#">Théo Laurent</a>
        <div class="hc-card">
          <div class="hc-top"><span class="um-av" aria-hidden="true">TL</span><span><b>Théo Laurent</b><span class="hc-role">Finance lead · Lyon, 16:42 local</span></span></div>
          <p class="hc-bio">Owns the budget model and every number in this document. Ask him before changing a forecast.</p>
          <dl class="hc-meta"><div><dt>docs</dt><dd>128</dd></div><div><dt>reviews</dt><dd>54</dd></div><div><dt>joined</dt><dd>2021</dd></div></dl>
          <div class="hc-actions"><a href="#">View profile<span class="sr-only"> of Théo Laurent</span></a><a href="#">Message<span class="sr-only"> Théo Laurent</span></a></div>
        </div></div>
        <span class="hl-role">Editing section 3</span></div>
      <span class="hl-state on">Online</span></li>
    <li><span class="hl-pic"><span class="um-av av-b" aria-hidden="true">AK</span><i class="busy" aria-hidden="true"></i></span>
      <div class="hl-who"><div class="hc"><a class="hc-name" href="#">Aiko Kimura</a>
        <div class="hc-card">
          <div class="hc-top"><span class="um-av av-b" aria-hidden="true">AK</span><span><b>Aiko Kimura</b><span class="hc-role">Product designer · Osaka, 23:42 local</span></span></div>
          <p class="hc-bio">Designing the new invoice flow. In reviews until 15:00 UTC; she answers comments in batches.</p>
          <dl class="hc-meta"><div><dt>docs</dt><dd>76</dd></div><div><dt>reviews</dt><dd>212</dd></div><div><dt>joined</dt><dd>2019</dd></div></dl>
          <div class="hc-actions"><a href="#">View profile<span class="sr-only"> of Aiko Kimura</span></a><a href="#">Message<span class="sr-only"> Aiko Kimura</span></a></div>
        </div></div>
        <span class="hl-role">Commented 12 minutes ago</span></div>
      <span class="hl-state busy">In a meeting</span></li>
    <li><span class="hl-pic"><span class="um-av av-c" aria-hidden="true">NB</span><i class="on" aria-hidden="true"></i></span>
      <div class="hl-who"><div class="hc"><a class="hc-name" href="#">Nadia Benali</a>
        <div class="hc-card">
          <div class="hc-top"><span class="um-av av-c" aria-hidden="true">NB</span><span><b>Nadia Benali</b><span class="hc-role">Head of sales · Paris, 16:42 local</span></span></div>
          <p class="hc-bio">Brings the pipeline numbers to every planning round. Prefers a call to a long comment thread.</p>
          <dl class="hc-meta"><div><dt>docs</dt><dd>41</dd></div><div><dt>reviews</dt><dd>19</dd></div><div><dt>joined</dt><dd>2022</dd></div></dl>
          <div class="hc-actions"><a href="#">View profile<span class="sr-only"> of Nadia Benali</span></a><a href="#">Message<span class="sr-only"> Nadia Benali</span></a></div>
        </div></div>
        <span class="hl-role">Viewing</span></div>
      <span class="hl-state on">Online</span></li>
    <li><span class="hl-pic"><span class="um-av av-d" aria-hidden="true">OW</span><i aria-hidden="true"></i></span>
      <div class="hl-who"><div class="hc"><a class="hc-name" href="#">Owen Walsh</a>
        <div class="hc-card">
          <div class="hc-top"><span class="um-av av-d" aria-hidden="true">OW</span><span><b>Owen Walsh</b><span class="hc-role">Engineering manager · Dublin, 15:42 local</span></span></div>
          <p class="hc-bio">Signs off on the hiring plan in section 5. Back from leave on Monday.</p>
          <dl class="hc-meta"><div><dt>docs</dt><dd>93</dd></div><div><dt>reviews</dt><dd>148</dd></div><div><dt>joined</dt><dd>2018</dd></div></dl>
          <div class="hc-actions"><a href="#">View profile<span class="sr-only"> of Owen Walsh</span></a><a href="#">Message<span class="sr-only"> Owen Walsh</span></a></div>
        </div></div>
        <span class="hl-role">Last seen yesterday</span></div>
      <span class="hl-state">Away</span></li>
  </ul>
</section></div>
</div>
CSS
/* User menu: a disclosure button (aria-expanded) that opens a panel with a mini profile and account links; Escape, a click
   outside or tabbing away closes it. Hover cards: a mini profile that opens on hover or keyboard focus of a name, stays open
   while the pointer or focus is inside it, and closes with Escape. */
.um,.hl{--um-accent:#2563eb;--um-ink:#0f172a;--um-muted:#475569;--um-line:#e2e8f0;--um-soft:#f1f5f9;color:var(--um-ink)}
.um :where(p,ul,h3),.hl :where(p,ul,h3,dl,dd){margin:0;padding:0}
.um-av{display:grid;place-items:center;flex:none;width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,#2563eb,#7c3aed);color:#fff;font-size:.8rem;font-weight:700}
/* the bar */
.um-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px 10px 18px;background:#fff;border:1px solid var(--um-line);border-radius:16px}
.um-brand{display:flex;align-items:center;gap:8px;font-weight:800;letter-spacing:-.01em}
.um-brand i{width:22px;height:22px;border-radius:7px;background:conic-gradient(from 45deg,#2563eb,#22d3ee,#2563eb)}
.um{position:relative}
.um-btn{display:flex;align-items:center;gap:8px;padding:4px 10px 4px 4px;border:1px solid transparent;border-radius:999px;background:none;color:inherit;font:inherit;font-size:.9rem;font-weight:600;cursor:pointer;transition:background-color .2s}
.um-btn:hover,.um-btn[aria-expanded=true]{background:var(--um-soft)}
.um-btn:focus-visible{outline:3px solid var(--um-accent);outline-offset:2px}
.um-btn svg{width:16px;height:16px;color:var(--um-muted);transition:transform .2s}
.um-btn[aria-expanded=true] svg{transform:rotate(180deg)}
.um-menu{position:absolute;right:0;top:calc(100% + 10px);z-index:10;width:min(300px,calc(100vw - 32px));padding:8px;background:#fff;border:1px solid var(--um-line);border-radius:16px;
  box-shadow:0 24px 48px -16px rgba(15,23,42,.28);animation:um-in .18s ease-out}
.um-menu[hidden]{display:none}
@keyframes um-in{from{opacity:0;transform:translateY(-6px)}}
.um-head{display:flex;gap:12px;align-items:center;padding:10px 10px 14px}
.um-head .um-av{width:44px;height:44px;font-size:.95rem}
.um-name{font-weight:700}
.um-mail{margin-top:2px;font-size:.84rem;color:var(--um-muted);overflow-wrap:anywhere}
.um-plan{display:inline-block;margin-top:6px;padding:2px 8px;border-radius:999px;background:#dbeafe;color:#1e40af;font-size:.72rem;font-weight:700}
.um-meter{margin:0 10px 12px;padding:10px 12px;border-radius:12px;background:var(--um-soft);font-size:.8rem;color:var(--um-muted)}
.um-meter b{color:var(--um-ink)}
.um-meter span{display:block;height:6px;margin-top:8px;border-radius:9px;background:#cbd5e1;overflow:hidden}
.um-meter span::before{content:"";display:block;width:72%;height:100%;border-radius:inherit;background:var(--um-accent)}
.um-links{list-style:none;padding:6px 0;border-top:1px solid var(--um-line)}
.um-links a,.um-links button{display:flex;align-items:center;gap:10px;width:100%;padding:9px 10px;border:0;border-radius:10px;background:none;color:inherit;font:inherit;font-size:.9rem;text-align:left;text-decoration:none;cursor:pointer}
.um-links a:hover,.um-links button:hover{background:var(--um-soft)}
.um-links a:focus-visible,.um-links button:focus-visible{outline:2px solid var(--um-accent);outline-offset:-2px}
.um-links svg{flex:none;width:18px;height:18px;color:var(--um-muted)}
.um-links small{margin-left:auto;font-size:.75rem;color:var(--um-muted)}
.um-out{border-top:1px solid var(--um-line);padding-top:6px}
.um-out button{color:#b91c1c}
.um-out button svg{color:#b91c1c}
/* list with presence and hover cards */
.hl{background:#fff;border:1px solid var(--um-line);border-radius:18px;padding:8px 20px}
.hl-title{padding:12px 0 6px;font-size:1rem;font-weight:800}
.hl ul{list-style:none}
.hl li{position:relative;display:flex;align-items:center;gap:12px;padding:12px 0;border-top:1px solid var(--um-line)}
.hl-pic{position:relative;flex:none}
.hl-pic i{position:absolute;right:-1px;bottom:-1px;width:12px;height:12px;border:2px solid #fff;border-radius:50%;background:#94a3b8}
.hl-pic i.on{background:#16a34a}.hl-pic i.busy{background:#d97706}
.hl-who{flex:1;min-width:0}
.hl-role{display:block;margin-top:2px;font-size:.84rem;color:var(--um-muted)}
.hl-state{flex:none;font-size:.8rem;font-weight:600;color:var(--um-muted)}
.hl-state.on{color:#15803d}.hl-state.busy{color:#b45309}
.hc{position:relative;display:inline-block}
@media (max-width:480px){.hc{position:static}.hc-card{left:0;right:0;width:auto}}
.hc-name{color:var(--um-ink);font-weight:700;text-decoration:underline;text-decoration-color:#cbd5e1;text-underline-offset:3px;text-decoration-thickness:2px;border-radius:4px}
.hc-name:hover{text-decoration-color:var(--um-accent)}
.hc-name:focus-visible{outline:3px solid var(--um-accent);outline-offset:2px}
.hc-card{position:absolute;left:-12px;top:calc(100% + 8px);z-index:5;width:min(290px,calc(100vw - 48px));padding:16px;background:#fff;border:1px solid var(--um-line);border-radius:16px;
  box-shadow:0 24px 48px -16px rgba(15,23,42,.3);opacity:0;visibility:hidden;transform:translateY(4px);transition:opacity .16s,transform .16s,visibility 0s .16s}
.hc-card::before{content:"";position:absolute;left:0;right:0;top:-10px;height:10px}
.hc:hover .hc-card,.hc:focus-within .hc-card,.hc.is-open .hc-card{opacity:1;visibility:visible;transform:none;transition:opacity .16s .25s,transform .16s .25s,visibility 0s .25s}
.hc:focus-within .hc-card,.hc.is-open .hc-card{transition-delay:0s}
.hc.is-dismissed .hc-card{opacity:0;visibility:hidden}
.hc-top{display:flex;align-items:center;gap:12px}
.hc-top .um-av{width:48px;height:48px;font-size:1rem}
.hc-top b{display:block}
.hc-role{display:block;margin-top:2px;font-size:.82rem;color:var(--um-muted)}
.hc-bio{margin-top:12px;font-size:.86rem;line-height:1.5;color:var(--um-muted)}
.hc-meta{display:flex;gap:18px;margin-top:12px;font-size:.8rem;color:var(--um-muted)}
.hc-meta dd{color:var(--um-ink);font-size:.95rem;font-weight:700}
.hc-meta div{display:flex;flex-direction:column-reverse}
.hc-actions{display:flex;gap:8px;margin-top:14px}
.hc-actions a{flex:1;padding:8px 10px;border:1.5px solid var(--um-accent);border-radius:10px;color:var(--um-accent);font-size:.84rem;font-weight:700;text-align:center;text-decoration:none}
.hc-actions a:first-child{background:var(--um-accent);color:#fff}
.hc-actions a:focus-visible{outline:3px solid var(--um-accent);outline-offset:2px}
.um .sr-only,.hl .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.av-b{background:linear-gradient(135deg,#0f766e,#22c55e)}.av-c{background:linear-gradient(135deg,#c2410c,#db2777)}.av-d{background:linear-gradient(135deg,#334155,#64748b)}
@media (prefers-reduced-motion:reduce){.um-menu{animation:none}.um-btn,.um-btn svg,.hc-card{transition:none!important}.hc-card{transform:none}}
JavaScript
/* Account menu: toggle on click; Escape closes it and returns focus to the button; a click outside or tabbing out closes it.
   Hover cards: Escape hides an open card until the pointer or focus leaves its name. */
document.querySelectorAll('.um').forEach(function (um) {
  var btn = um.querySelector('.um-btn'), menu = um.querySelector('.um-menu');
  function set(open) { btn.setAttribute('aria-expanded', String(open)); menu.hidden = !open; }
  btn.addEventListener('click', function () { set(menu.hidden); });
  um.addEventListener('keydown', function (e) { if (e.key === 'Escape' && !menu.hidden) { set(false); btn.focus(); } });
  um.addEventListener('focusout', function (e) { if (e.relatedTarget && !um.contains(e.relatedTarget)) set(false); });
  document.addEventListener('click', function (e) { if (!um.contains(e.target)) set(false); });
});
document.querySelectorAll('.hc').forEach(function (hc) {
  hc.addEventListener('keydown', function (e) { if (e.key === 'Escape') { hc.classList.add('is-dismissed'); hc.classList.remove('is-open'); } });
  hc.addEventListener('mouseleave', function () { if (!hc.contains(document.activeElement)) hc.classList.remove('is-dismissed'); });
  hc.addEventListener('focusout', function (e) { if (!hc.contains(e.relatedTarget)) hc.classList.remove('is-dismissed', 'is-open'); });
});

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS, Bootstrap 5.3.8 JS bundle

HTML
<div class="duo">
<div><span class="lbl">Account menu</span>
<header class="um-bar">
  <span class="um-brand"><i aria-hidden="true"></i>Ledgerly</span>
  <div class="um dropdown">
    <button class="btn um-btn dropdown-toggle" type="button" data-bs-toggle="dropdown" data-bs-display="static" aria-expanded="false"><span class="um-av" aria-hidden="true">SM</span>Sofia<span class="visually-hidden"> Marchetti, account menu</span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M6.5 9.5 12 15l5.5-5.5"/></svg></button>
    <div class="dropdown-menu dropdown-menu-end">
      <div class="um-head">
        <span class="um-av" aria-hidden="true">SM</span>
        <div><p class="um-name">Sofia Marchetti</p><p class="um-mail">[email protected]</p><span class="um-plan badge rounded-pill">Team plan · admin</span></div>
      </div>
      <div class="um-meter"><b>7.2 GB</b> of 10 GB used<div class="progress" aria-hidden="true"><div class="progress-bar" style="width:72%"></div></div></div>
      <hr class="dropdown-divider">
      <a class="dropdown-item" href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="8" r="4"/><path d="M4.5 20.5c.8-4 3.8-6 7.5-6s6.7 2 7.5 6"/></svg>Your profile</a>
      <a class="dropdown-item" href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></svg>Settings</a>
      <a class="dropdown-item" href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="2.5" y="5" width="19" height="14" rx="2.5"/><path d="M2.5 10h19M6.5 15h4"/></svg>Billing<small>Due 3 Nov</small></a>
      <a class="dropdown-item" href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" aria-hidden="true" focusable="false"><rect x="3.5" y="3.5" width="7" height="7" rx="1.5"/><rect x="13.5" y="3.5" width="7" height="7" rx="1.5"/><rect x="3.5" y="13.5" width="7" height="7" rx="1.5"/><rect x="13.5" y="13.5" width="7" height="7" rx="1.5"/></svg>Switch workspace</a>
      <hr class="dropdown-divider">
      <button class="dropdown-item um-out" type="button"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M14.5 4.5h3a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2h-3M10 16.5 14.5 12 10 7.5M14.5 12H3.5"/></svg>Sign out</button>
    </div>
  </div>
</header></div>

<div><span class="lbl">Team list with hover cards</span>
<section class="card hl" aria-labelledby="hl-title">
  <h3 class="hl-title" id="hl-title">Q4 planning doc · 4 people</h3>
  <ul class="list-unstyled">
    <li><span class="hl-pic"><span class="um-av" aria-hidden="true">TL</span><i class="on" aria-hidden="true"></i></span>
      <div class="hl-who"><div class="hc"><a class="hc-name" href="#">Théo Laurent</a>
        <div class="hc-card card">
          <div class="hc-top"><span class="um-av" aria-hidden="true">TL</span><span><b>Théo Laurent</b><span class="hc-role">Finance lead · Lyon, 16:42 local</span></span></div>
          <p class="hc-bio">Owns the budget model and every number in this document. Ask him before changing a forecast.</p>
          <dl class="hc-meta"><div><dt>docs</dt><dd>128</dd></div><div><dt>reviews</dt><dd>54</dd></div><div><dt>joined</dt><dd>2021</dd></div></dl>
          <div class="hc-actions"><a class="btn btn-primary" href="#">View profile<span class="visually-hidden"> of Théo Laurent</span></a><a class="btn btn-outline-primary" href="#">Message<span class="visually-hidden"> Théo Laurent</span></a></div>
        </div></div>
        <span class="hl-role">Editing section 3</span></div>
      <span class="hl-state on">Online</span></li>
    <li><span class="hl-pic"><span class="um-av av-b" aria-hidden="true">AK</span><i class="busy" aria-hidden="true"></i></span>
      <div class="hl-who"><div class="hc"><a class="hc-name" href="#">Aiko Kimura</a>
        <div class="hc-card card">
          <div class="hc-top"><span class="um-av av-b" aria-hidden="true">AK</span><span><b>Aiko Kimura</b><span class="hc-role">Product designer · Osaka, 23:42 local</span></span></div>
          <p class="hc-bio">Designing the new invoice flow. In reviews until 15:00 UTC; she answers comments in batches.</p>
          <dl class="hc-meta"><div><dt>docs</dt><dd>76</dd></div><div><dt>reviews</dt><dd>212</dd></div><div><dt>joined</dt><dd>2019</dd></div></dl>
          <div class="hc-actions"><a class="btn btn-primary" href="#">View profile<span class="visually-hidden"> of Aiko Kimura</span></a><a class="btn btn-outline-primary" href="#">Message<span class="visually-hidden"> Aiko Kimura</span></a></div>
        </div></div>
        <span class="hl-role">Commented 12 minutes ago</span></div>
      <span class="hl-state busy">In a meeting</span></li>
    <li><span class="hl-pic"><span class="um-av av-c" aria-hidden="true">NB</span><i class="on" aria-hidden="true"></i></span>
      <div class="hl-who"><div class="hc"><a class="hc-name" href="#">Nadia Benali</a>
        <div class="hc-card card">
          <div class="hc-top"><span class="um-av av-c" aria-hidden="true">NB</span><span><b>Nadia Benali</b><span class="hc-role">Head of sales · Paris, 16:42 local</span></span></div>
          <p class="hc-bio">Brings the pipeline numbers to every planning round. Prefers a call to a long comment thread.</p>
          <dl class="hc-meta"><div><dt>docs</dt><dd>41</dd></div><div><dt>reviews</dt><dd>19</dd></div><div><dt>joined</dt><dd>2022</dd></div></dl>
          <div class="hc-actions"><a class="btn btn-primary" href="#">View profile<span class="visually-hidden"> of Nadia Benali</span></a><a class="btn btn-outline-primary" href="#">Message<span class="visually-hidden"> Nadia Benali</span></a></div>
        </div></div>
        <span class="hl-role">Viewing</span></div>
      <span class="hl-state on">Online</span></li>
    <li><span class="hl-pic"><span class="um-av av-d" aria-hidden="true">OW</span><i aria-hidden="true"></i></span>
      <div class="hl-who"><div class="hc"><a class="hc-name" href="#">Owen Walsh</a>
        <div class="hc-card card">
          <div class="hc-top"><span class="um-av av-d" aria-hidden="true">OW</span><span><b>Owen Walsh</b><span class="hc-role">Engineering manager · Dublin, 15:42 local</span></span></div>
          <p class="hc-bio">Signs off on the hiring plan in section 5. Back from leave on Monday.</p>
          <dl class="hc-meta"><div><dt>docs</dt><dd>93</dd></div><div><dt>reviews</dt><dd>148</dd></div><div><dt>joined</dt><dd>2018</dd></div></dl>
          <div class="hc-actions"><a class="btn btn-primary" href="#">View profile<span class="visually-hidden"> of Owen Walsh</span></a><a class="btn btn-outline-primary" href="#">Message<span class="visually-hidden"> Owen Walsh</span></a></div>
        </div></div>
        <span class="hl-role">Last seen yesterday</span></div>
      <span class="hl-state">Away</span></li>
  </ul>
</section></div>
</div>
CSS
/* User menu: Bootstrap's dropdown (bundle JS) opens a panel with a mini profile and account links; Bootstrap handles Escape,
   arrow keys and outside clicks. Hover cards: a mini profile that opens on hover or keyboard focus of a name, stays open
   while the pointer or focus is inside it, and closes with Escape. */
.um,.hl,.um-bar{--um-accent:#2563eb;--um-ink:#0f172a;--um-muted:#475569;--um-line:#e2e8f0;--um-soft:#f1f5f9;color:var(--um-ink)}
.um :where(p,ul,h3),.hl :where(p,ul,h3,dl,dd,dt){margin:0}
.hl ul,.hc-meta{padding:0}
.um-av{display:grid;place-items:center;flex:none;width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,#2563eb,#7c3aed);color:#fff;font-size:.8rem;font-weight:700}
/* the bar */
.um-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;color:var(--um-ink);padding:10px 12px 10px 18px;background:#fff;border:1px solid var(--um-line);border-radius:16px}
.um-brand{display:flex;align-items:center;gap:8px;font-weight:800;letter-spacing:-.01em}
.um-brand i{width:22px;height:22px;border-radius:7px;background:conic-gradient(from 45deg,#2563eb,#22d3ee,#2563eb)}
.um-btn{--bs-btn-padding-x:10px;--bs-btn-padding-y:4px;--bs-btn-font-size:.9rem;--bs-btn-font-weight:600;--bs-btn-border-radius:999px;--bs-btn-color:var(--um-ink);
  --bs-btn-hover-bg:var(--um-soft);--bs-btn-hover-color:var(--um-ink);--bs-btn-active-bg:var(--um-soft);--bs-btn-active-color:var(--um-ink);--bs-btn-active-border-color:transparent;--bs-btn-focus-box-shadow:none;
  display:flex;align-items:center;gap:8px;padding-left:4px;transition:background-color .2s}
.um-btn.show{background:var(--um-soft)}
.um-btn:focus-visible{outline:3px solid var(--um-accent);outline-offset:2px}
.um-btn::after{display:none}
.um-btn svg{width:16px;height:16px;color:var(--um-muted);transition:transform .2s}
.um-btn.show svg{transform:rotate(180deg)}
.um .dropdown-menu{--bs-dropdown-min-width:0;--bs-dropdown-padding-x:8px;--bs-dropdown-padding-y:8px;--bs-dropdown-border-color:var(--um-line);--bs-dropdown-border-radius:16px;--bs-dropdown-spacer:10px;
  --bs-dropdown-link-color:var(--um-ink);--bs-dropdown-link-hover-color:var(--um-ink);--bs-dropdown-link-hover-bg:var(--um-soft);--bs-dropdown-link-active-color:var(--um-ink);--bs-dropdown-link-active-bg:#e2e8f0;
  --bs-dropdown-item-padding-x:10px;--bs-dropdown-item-padding-y:9px;--bs-dropdown-item-border-radius:10px;--bs-dropdown-divider-bg:var(--um-line);--bs-dropdown-divider-margin-y:6px;--bs-dropdown-font-size:.9rem;
  width:min(300px,calc(100vw - 32px));box-shadow:0 24px 48px -16px rgba(15,23,42,.28)}
.um .dropdown-menu.show{animation:um-in .18s ease-out}
@keyframes um-in{from{opacity:0;transform:translateY(-6px)}}
.um-head{display:flex;gap:12px;align-items:center;padding:10px 10px 14px}
.um-head .um-av{width:44px;height:44px;font-size:.95rem}
.um-name{font-weight:700}
.um-mail{margin-top:2px;font-size:.84rem;color:var(--um-muted);overflow-wrap:anywhere}
.um-plan{--bs-badge-padding-x:8px;--bs-badge-padding-y:2px;--bs-badge-font-size:.72rem;--bs-badge-font-weight:700;--bs-badge-color:#1e40af;margin-top:6px;background:#dbeafe;line-height:1.5}
.um-meter{margin:0 10px 6px;padding:10px 12px;border-radius:12px;background:var(--um-soft);font-size:.8rem;color:var(--um-muted)}
.um-meter b{color:var(--um-ink)}
.um-meter .progress{--bs-progress-height:6px;--bs-progress-bg:#cbd5e1;--bs-progress-bar-bg:var(--um-accent);--bs-progress-border-radius:9px;margin-top:8px}
.um .dropdown-item{display:flex;align-items:center;gap:10px;margin:0}
.um .dropdown-item:focus-visible{outline:2px solid var(--um-accent);outline-offset:-2px}
.um .dropdown-item svg{flex:none;width:18px;height:18px;color:var(--um-muted)}
.um .dropdown-item small{margin-left:auto;font-size:.75rem;color:var(--um-muted)}
.um .um-out{color:#b91c1c}
.um .um-out svg{color:#b91c1c}
.um .um-out:hover,.um .um-out:active{color:#b91c1c}
/* list with presence and hover cards */
.hl{--bs-card-border-color:var(--um-line);--bs-card-border-radius:18px;padding:8px 20px}
.hl .hl-title{padding:12px 0 6px;font-size:1rem;font-weight:800;line-height:normal}
.hl ul{list-style:none}
.hl li{position:relative;display:flex;align-items:center;gap:12px;padding:12px 0;border-top:1px solid var(--um-line)}
.hl-pic{position:relative;flex:none}
.hl-pic i{position:absolute;right:-1px;bottom:-1px;width:12px;height:12px;border:2px solid #fff;border-radius:50%;background:#94a3b8}
.hl-pic i.on{background:#16a34a}.hl-pic i.busy{background:#d97706}
.hl-who{flex:1;min-width:0}
.hl-role{display:block;margin-top:2px;font-size:.84rem;color:var(--um-muted)}
.hl-state{flex:none;font-size:.8rem;font-weight:600;color:var(--um-muted)}
.hl-state.on{color:#15803d}.hl-state.busy{color:#b45309}
.hc{position:relative;display:inline-block}
@media (max-width:480px){.hc{position:static}.hc-card{left:0;right:0;width:auto}}
.hc-name{color:var(--um-ink);font-weight:700;text-decoration:underline;text-decoration-color:#cbd5e1;text-underline-offset:3px;text-decoration-thickness:2px;border-radius:4px}
.hc-name:hover{text-decoration-color:var(--um-accent)}
.hc-name:focus-visible{outline:3px solid var(--um-accent);outline-offset:2px}
.hc-card{--bs-card-border-color:var(--um-line);--bs-card-border-radius:16px;position:absolute;left:-12px;top:calc(100% + 8px);z-index:5;width:min(290px,calc(100vw - 48px));padding:16px;background:#fff;border:1px solid var(--um-line);border-radius:16px;
  box-shadow:0 24px 48px -16px rgba(15,23,42,.3);opacity:0;visibility:hidden;transform:translateY(4px);transition:opacity .16s,transform .16s,visibility 0s .16s}
.hc-card::before{content:"";position:absolute;left:0;right:0;top:-10px;height:10px}
.hc:hover .hc-card,.hc:focus-within .hc-card,.hc.is-open .hc-card{opacity:1;visibility:visible;transform:none;transition:opacity .16s .25s,transform .16s .25s,visibility 0s .25s}
.hc:focus-within .hc-card,.hc.is-open .hc-card{transition-delay:0s}
.hc.is-dismissed .hc-card{opacity:0;visibility:hidden}
.hc-top{display:flex;align-items:center;gap:12px}
.hc-top .um-av{width:48px;height:48px;font-size:1rem}
.hc-top b{display:block}
.hc-role{display:block;margin-top:2px;font-size:.82rem;color:var(--um-muted)}
.hc-bio{margin-top:12px;font-size:.86rem;line-height:1.5;color:var(--um-muted)}
.hc-meta{display:flex;gap:18px;margin-top:12px;font-size:.8rem;color:var(--um-muted)}
.hc-meta dt{font-weight:400}
.hc-meta dd{color:var(--um-ink);font-size:.95rem;font-weight:700}
.hc-meta div{display:flex;flex-direction:column-reverse}
.hc-actions{display:flex;gap:8px;margin-top:14px}
.hc-actions .btn{--bs-btn-padding-x:10px;--bs-btn-padding-y:8px;--bs-btn-font-size:.84rem;--bs-btn-font-weight:700;--bs-btn-line-height:normal;--bs-btn-border-width:1.5px;--bs-btn-border-radius:10px;--bs-btn-focus-box-shadow:none;flex:1}
.hc-actions .btn-primary{--bs-btn-bg:var(--um-accent);--bs-btn-border-color:var(--um-accent);--bs-btn-hover-bg:#1d4ed8;--bs-btn-hover-border-color:#1d4ed8}
.hc-actions .btn-outline-primary{--bs-btn-color:var(--um-accent);--bs-btn-border-color:var(--um-accent);--bs-btn-hover-bg:var(--um-accent);--bs-btn-hover-border-color:var(--um-accent)}
.hc-actions .btn:focus-visible{outline:3px solid var(--um-accent);outline-offset:2px}
.av-b{background:linear-gradient(135deg,#0f766e,#22c55e)}.av-c{background:linear-gradient(135deg,#c2410c,#db2777)}.av-d{background:linear-gradient(135deg,#334155,#64748b)}
@media (prefers-reduced-motion:reduce){.um .dropdown-menu.show{animation:none}.um-btn,.um-btn svg,.hc-card{transition:none!important}.hc-card{transform:none}}
JavaScript
/* The account menu is Bootstrap's dropdown plugin. Hover cards: Escape hides an open card until the pointer or focus leaves its name. */
document.querySelectorAll('.hc').forEach(function (hc) {
  hc.addEventListener('keydown', function (e) { if (e.key === 'Escape') { hc.classList.add('is-dismissed'); hc.classList.remove('is-open'); } });
  hc.addEventListener('mouseleave', function () { if (!hc.contains(document.activeElement)) hc.classList.remove('is-dismissed'); });
  hc.addEventListener('focusout', function (e) { if (!hc.contains(e.relatedTarget)) hc.classList.remove('is-dismissed', 'is-open'); });
});

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div class="flex flex-wrap items-start gap-x-7 gap-y-14">
<div class="min-h-[520px] min-w-0 flex-[1_1_360px]"><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#475569] uppercase">Account menu</span>
<header class="flex items-center justify-between gap-3 rounded-2xl border border-[#e2e8f0] bg-white py-2.5 pr-3 pl-[18px] text-[#0f172a]">
  <span class="flex items-center gap-2 font-extrabold tracking-[-.01em]"><i class="size-[22px] rounded-[7px] bg-[conic-gradient(from_45deg,#2563eb,#22d3ee,#2563eb)]" aria-hidden="true"></i>Ledgerly</span>
  <div class="um relative">
    <button class="um-btn group flex cursor-pointer items-center gap-2 rounded-full py-1 pr-2.5 pl-1 text-[.9rem] font-semibold transition-[color,background-color,border-color] duration-200 hover:bg-[#f1f5f9] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb] aria-expanded:bg-[#f1f5f9] motion-reduce:transition-none" type="button" aria-expanded="false" aria-controls="um-menu"><span class="grid size-9 flex-none place-items-center rounded-full text-[.8rem] font-bold text-white bg-[linear-gradient(135deg,#2563eb,#7c3aed)]" aria-hidden="true">SM</span>Sofia<span class="sr-only"> Marchetti, account menu</span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-4 text-[#475569] transition-transform duration-200 group-aria-expanded:rotate-180 motion-reduce:transition-none"><path d="M6.5 9.5 12 15l5.5-5.5"/></svg></button>
    <div class="um-menu absolute top-[calc(100%+10px)] right-0 z-10 w-[min(300px,calc(100vw-32px))] animate-um-in rounded-2xl border border-[#e2e8f0] bg-white p-2 shadow-[0_24px_48px_-16px_rgba(15,23,42,.28)] motion-reduce:animate-none" id="um-menu" hidden>
      <div class="flex items-center gap-3 px-2.5 pt-2.5 pb-3.5">
        <span class="grid size-11 flex-none place-items-center rounded-full text-[.95rem] font-bold text-white bg-[linear-gradient(135deg,#2563eb,#7c3aed)]" aria-hidden="true">SM</span>
        <div><p class="font-bold">Sofia Marchetti</p><p class="mt-0.5 text-[.84rem] wrap-anywhere text-[#475569]">[email protected]</p><span class="mt-1.5 inline-block rounded-full bg-[#dbeafe] px-2 py-0.5 text-[.72rem] font-bold text-[#1e40af]">Team plan · admin</span></div>
      </div>
      <p class="mx-2.5 mb-3 rounded-xl bg-[#f1f5f9] px-3 py-2.5 text-[.8rem] text-[#475569]"><b class="text-[#0f172a]">7.2 GB</b> of 10 GB used<span class="mt-2 block h-1.5 overflow-hidden rounded-[9px] bg-[#cbd5e1]" aria-hidden="true"><span class="block h-full w-[72%] rounded-[inherit] bg-[#2563eb]"></span></span></p>
      <ul class="border-t border-[#e2e8f0] py-1.5">
        <li><a class="flex w-full cursor-pointer items-center gap-2.5 rounded-[10px] px-2.5 py-[9px] text-left text-[.9rem] no-underline hover:bg-[#f1f5f9] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#2563eb]" href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[18px] flex-none text-[#475569]"><circle cx="12" cy="8" r="4"/><path d="M4.5 20.5c.8-4 3.8-6 7.5-6s6.7 2 7.5 6"/></svg>Your profile</a></li>
        <li><a class="flex w-full cursor-pointer items-center gap-2.5 rounded-[10px] px-2.5 py-[9px] text-left text-[.9rem] no-underline hover:bg-[#f1f5f9] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#2563eb]" href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[18px] flex-none text-[#475569]"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></svg>Settings</a></li>
        <li><a class="flex w-full cursor-pointer items-center gap-2.5 rounded-[10px] px-2.5 py-[9px] text-left text-[.9rem] no-underline hover:bg-[#f1f5f9] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#2563eb]" href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[18px] flex-none text-[#475569]"><rect x="2.5" y="5" width="19" height="14" rx="2.5"/><path d="M2.5 10h19M6.5 15h4"/></svg>Billing<small class="ml-auto text-[.75rem] text-[#475569]">Due 3 Nov</small></a></li>
        <li><a class="flex w-full cursor-pointer items-center gap-2.5 rounded-[10px] px-2.5 py-[9px] text-left text-[.9rem] no-underline hover:bg-[#f1f5f9] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#2563eb]" href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[18px] flex-none text-[#475569]"><rect x="3.5" y="3.5" width="7" height="7" rx="1.5"/><rect x="13.5" y="3.5" width="7" height="7" rx="1.5"/><rect x="3.5" y="13.5" width="7" height="7" rx="1.5"/><rect x="13.5" y="13.5" width="7" height="7" rx="1.5"/></svg>Switch workspace</a></li>
      </ul>
      <div class="border-t border-[#e2e8f0] pt-1.5"><button class="flex w-full cursor-pointer items-center gap-2.5 rounded-[10px] px-2.5 py-[9px] text-left text-[.9rem] no-underline hover:bg-[#f1f5f9] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#2563eb] text-[#b91c1c]" type="button"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" class="size-[18px] flex-none"><path d="M14.5 4.5h3a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2h-3M10 16.5 14.5 12 10 7.5M14.5 12H3.5"/></svg>Sign out</button></div>
    </div>
  </div>
</header></div>

<div class="min-w-0 flex-[1_1_480px]"><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#475569] uppercase">Team list with hover cards</span>
<section class="rounded-[18px] border border-[#e2e8f0] bg-white px-5 py-2 text-[#0f172a]" aria-labelledby="hl-title">
  <h3 class="pt-3 pb-1.5 text-base font-extrabold" id="hl-title">Q4 planning doc · 4 people</h3>
  <ul>
    <li class="relative flex items-center gap-3 border-t border-[#e2e8f0] py-3">
      <span class="relative flex-none"><span class="grid size-9 flex-none place-items-center rounded-full text-[.8rem] font-bold text-white bg-[linear-gradient(135deg,#2563eb,#7c3aed)]" aria-hidden="true">TL</span><i class="absolute -right-px -bottom-px size-3 rounded-full border-2 border-white bg-[#16a34a]" aria-hidden="true"></i></span>
      <div class="min-w-0 flex-1"><div class="hc group/hc relative inline-block max-[480px]:static"><a class="rounded font-bold text-[#0f172a] underline decoration-[#cbd5e1] decoration-2 underline-offset-3 hover:decoration-[#2563eb] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]" href="#">Théo Laurent</a>
        <div class="invisible absolute top-[calc(100%+8px)] -left-3 z-5 w-[min(290px,calc(100vw-48px))] translate-y-1 max-[480px]:right-0 max-[480px]:left-0 max-[480px]:w-auto rounded-2xl border border-[#e2e8f0] bg-white p-4 opacity-0 shadow-[0_24px_48px_-16px_rgba(15,23,42,.3)] transition-[opacity,transform,visibility] duration-150 before:absolute before:inset-x-0 before:-top-2.5 before:h-2.5 group-hover/hc:visible group-hover/hc:translate-y-0 group-hover/hc:opacity-100 group-hover/hc:delay-[250ms] group-focus-within/hc:visible group-focus-within/hc:translate-y-0 group-focus-within/hc:opacity-100 group-focus-within/hc:delay-0 group-[.is-open]/hc:visible group-[.is-open]/hc:translate-y-0 group-[.is-open]/hc:opacity-100 group-[.is-dismissed]/hc:invisible! group-[.is-dismissed]/hc:opacity-0! motion-reduce:translate-y-0 motion-reduce:transition-none">
          <div class="flex items-center gap-3"><span class="grid size-12 flex-none place-items-center rounded-full text-base font-bold text-white bg-[linear-gradient(135deg,#2563eb,#7c3aed)]" aria-hidden="true">TL</span><span><b class="block">Théo Laurent</b><span class="mt-0.5 block text-[.82rem] text-[#475569]">Finance lead · Lyon, 16:42 local</span></span></div>
          <p class="mt-3 text-[.86rem] leading-normal text-[#475569]">Owns the budget model and every number in this document. Ask him before changing a forecast.</p>
          <dl class="mt-3 flex gap-[18px] text-[.8rem] text-[#475569]"><div class="flex flex-col-reverse"><dt>docs</dt><dd class="text-[.95rem] font-bold text-[#0f172a]">128</dd></div><div class="flex flex-col-reverse"><dt>reviews</dt><dd class="text-[.95rem] font-bold text-[#0f172a]">54</dd></div><div class="flex flex-col-reverse"><dt>joined</dt><dd class="text-[.95rem] font-bold text-[#0f172a]">2021</dd></div></dl>
          <div class="mt-3.5 flex gap-2"><a class="flex-1 rounded-[10px] border-[1.5px] border-[#2563eb] bg-[#2563eb] px-2.5 py-2 text-center text-[.84rem] font-bold text-white no-underline hover:bg-[#1d4ed8] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]" href="#">View profile<span class="sr-only"> of Théo Laurent</span></a><a class="flex-1 rounded-[10px] border-[1.5px] border-[#2563eb] px-2.5 py-2 text-center text-[.84rem] font-bold text-[#2563eb] no-underline hover:bg-[#2563eb] hover:text-white focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]" href="#">Message<span class="sr-only"> Théo Laurent</span></a></div>
        </div></div>
        <span class="mt-0.5 block text-[.84rem] text-[#475569]">Editing section 3</span></div>
      <span class="flex-none text-[.8rem] font-semibold text-[#15803d]">Online</span></li>
    <li class="relative flex items-center gap-3 border-t border-[#e2e8f0] py-3">
      <span class="relative flex-none"><span class="grid size-9 flex-none place-items-center rounded-full text-[.8rem] font-bold text-white bg-[linear-gradient(135deg,#0f766e,#22c55e)]" aria-hidden="true">AK</span><i class="absolute -right-px -bottom-px size-3 rounded-full border-2 border-white bg-[#d97706]" aria-hidden="true"></i></span>
      <div class="min-w-0 flex-1"><div class="hc group/hc relative inline-block max-[480px]:static"><a class="rounded font-bold text-[#0f172a] underline decoration-[#cbd5e1] decoration-2 underline-offset-3 hover:decoration-[#2563eb] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]" href="#">Aiko Kimura</a>
        <div class="invisible absolute top-[calc(100%+8px)] -left-3 z-5 w-[min(290px,calc(100vw-48px))] translate-y-1 max-[480px]:right-0 max-[480px]:left-0 max-[480px]:w-auto rounded-2xl border border-[#e2e8f0] bg-white p-4 opacity-0 shadow-[0_24px_48px_-16px_rgba(15,23,42,.3)] transition-[opacity,transform,visibility] duration-150 before:absolute before:inset-x-0 before:-top-2.5 before:h-2.5 group-hover/hc:visible group-hover/hc:translate-y-0 group-hover/hc:opacity-100 group-hover/hc:delay-[250ms] group-focus-within/hc:visible group-focus-within/hc:translate-y-0 group-focus-within/hc:opacity-100 group-focus-within/hc:delay-0 group-[.is-open]/hc:visible group-[.is-open]/hc:translate-y-0 group-[.is-open]/hc:opacity-100 group-[.is-dismissed]/hc:invisible! group-[.is-dismissed]/hc:opacity-0! motion-reduce:translate-y-0 motion-reduce:transition-none">
          <div class="flex items-center gap-3"><span class="grid size-12 flex-none place-items-center rounded-full text-base font-bold text-white bg-[linear-gradient(135deg,#0f766e,#22c55e)]" aria-hidden="true">AK</span><span><b class="block">Aiko Kimura</b><span class="mt-0.5 block text-[.82rem] text-[#475569]">Product designer · Osaka, 23:42 local</span></span></div>
          <p class="mt-3 text-[.86rem] leading-normal text-[#475569]">Designing the new invoice flow. In reviews until 15:00 UTC; she answers comments in batches.</p>
          <dl class="mt-3 flex gap-[18px] text-[.8rem] text-[#475569]"><div class="flex flex-col-reverse"><dt>docs</dt><dd class="text-[.95rem] font-bold text-[#0f172a]">76</dd></div><div class="flex flex-col-reverse"><dt>reviews</dt><dd class="text-[.95rem] font-bold text-[#0f172a]">212</dd></div><div class="flex flex-col-reverse"><dt>joined</dt><dd class="text-[.95rem] font-bold text-[#0f172a]">2019</dd></div></dl>
          <div class="mt-3.5 flex gap-2"><a class="flex-1 rounded-[10px] border-[1.5px] border-[#2563eb] bg-[#2563eb] px-2.5 py-2 text-center text-[.84rem] font-bold text-white no-underline hover:bg-[#1d4ed8] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]" href="#">View profile<span class="sr-only"> of Aiko Kimura</span></a><a class="flex-1 rounded-[10px] border-[1.5px] border-[#2563eb] px-2.5 py-2 text-center text-[.84rem] font-bold text-[#2563eb] no-underline hover:bg-[#2563eb] hover:text-white focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]" href="#">Message<span class="sr-only"> Aiko Kimura</span></a></div>
        </div></div>
        <span class="mt-0.5 block text-[.84rem] text-[#475569]">Commented 12 minutes ago</span></div>
      <span class="flex-none text-[.8rem] font-semibold text-[#b45309]">In a meeting</span></li>
    <li class="relative flex items-center gap-3 border-t border-[#e2e8f0] py-3">
      <span class="relative flex-none"><span class="grid size-9 flex-none place-items-center rounded-full text-[.8rem] font-bold text-white bg-[linear-gradient(135deg,#c2410c,#db2777)]" aria-hidden="true">NB</span><i class="absolute -right-px -bottom-px size-3 rounded-full border-2 border-white bg-[#16a34a]" aria-hidden="true"></i></span>
      <div class="min-w-0 flex-1"><div class="hc group/hc relative inline-block max-[480px]:static"><a class="rounded font-bold text-[#0f172a] underline decoration-[#cbd5e1] decoration-2 underline-offset-3 hover:decoration-[#2563eb] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]" href="#">Nadia Benali</a>
        <div class="invisible absolute top-[calc(100%+8px)] -left-3 z-5 w-[min(290px,calc(100vw-48px))] translate-y-1 max-[480px]:right-0 max-[480px]:left-0 max-[480px]:w-auto rounded-2xl border border-[#e2e8f0] bg-white p-4 opacity-0 shadow-[0_24px_48px_-16px_rgba(15,23,42,.3)] transition-[opacity,transform,visibility] duration-150 before:absolute before:inset-x-0 before:-top-2.5 before:h-2.5 group-hover/hc:visible group-hover/hc:translate-y-0 group-hover/hc:opacity-100 group-hover/hc:delay-[250ms] group-focus-within/hc:visible group-focus-within/hc:translate-y-0 group-focus-within/hc:opacity-100 group-focus-within/hc:delay-0 group-[.is-open]/hc:visible group-[.is-open]/hc:translate-y-0 group-[.is-open]/hc:opacity-100 group-[.is-dismissed]/hc:invisible! group-[.is-dismissed]/hc:opacity-0! motion-reduce:translate-y-0 motion-reduce:transition-none">
          <div class="flex items-center gap-3"><span class="grid size-12 flex-none place-items-center rounded-full text-base font-bold text-white bg-[linear-gradient(135deg,#c2410c,#db2777)]" aria-hidden="true">NB</span><span><b class="block">Nadia Benali</b><span class="mt-0.5 block text-[.82rem] text-[#475569]">Head of sales · Paris, 16:42 local</span></span></div>
          <p class="mt-3 text-[.86rem] leading-normal text-[#475569]">Brings the pipeline numbers to every planning round. Prefers a call to a long comment thread.</p>
          <dl class="mt-3 flex gap-[18px] text-[.8rem] text-[#475569]"><div class="flex flex-col-reverse"><dt>docs</dt><dd class="text-[.95rem] font-bold text-[#0f172a]">41</dd></div><div class="flex flex-col-reverse"><dt>reviews</dt><dd class="text-[.95rem] font-bold text-[#0f172a]">19</dd></div><div class="flex flex-col-reverse"><dt>joined</dt><dd class="text-[.95rem] font-bold text-[#0f172a]">2022</dd></div></dl>
          <div class="mt-3.5 flex gap-2"><a class="flex-1 rounded-[10px] border-[1.5px] border-[#2563eb] bg-[#2563eb] px-2.5 py-2 text-center text-[.84rem] font-bold text-white no-underline hover:bg-[#1d4ed8] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]" href="#">View profile<span class="sr-only"> of Nadia Benali</span></a><a class="flex-1 rounded-[10px] border-[1.5px] border-[#2563eb] px-2.5 py-2 text-center text-[.84rem] font-bold text-[#2563eb] no-underline hover:bg-[#2563eb] hover:text-white focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]" href="#">Message<span class="sr-only"> Nadia Benali</span></a></div>
        </div></div>
        <span class="mt-0.5 block text-[.84rem] text-[#475569]">Viewing</span></div>
      <span class="flex-none text-[.8rem] font-semibold text-[#15803d]">Online</span></li>
    <li class="relative flex items-center gap-3 border-t border-[#e2e8f0] py-3">
      <span class="relative flex-none"><span class="grid size-9 flex-none place-items-center rounded-full text-[.8rem] font-bold text-white bg-[linear-gradient(135deg,#334155,#64748b)]" aria-hidden="true">OW</span><i class="absolute -right-px -bottom-px size-3 rounded-full border-2 border-white bg-[#94a3b8]" aria-hidden="true"></i></span>
      <div class="min-w-0 flex-1"><div class="hc group/hc relative inline-block max-[480px]:static"><a class="rounded font-bold text-[#0f172a] underline decoration-[#cbd5e1] decoration-2 underline-offset-3 hover:decoration-[#2563eb] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]" href="#">Owen Walsh</a>
        <div class="invisible absolute top-[calc(100%+8px)] -left-3 z-5 w-[min(290px,calc(100vw-48px))] translate-y-1 max-[480px]:right-0 max-[480px]:left-0 max-[480px]:w-auto rounded-2xl border border-[#e2e8f0] bg-white p-4 opacity-0 shadow-[0_24px_48px_-16px_rgba(15,23,42,.3)] transition-[opacity,transform,visibility] duration-150 before:absolute before:inset-x-0 before:-top-2.5 before:h-2.5 group-hover/hc:visible group-hover/hc:translate-y-0 group-hover/hc:opacity-100 group-hover/hc:delay-[250ms] group-focus-within/hc:visible group-focus-within/hc:translate-y-0 group-focus-within/hc:opacity-100 group-focus-within/hc:delay-0 group-[.is-open]/hc:visible group-[.is-open]/hc:translate-y-0 group-[.is-open]/hc:opacity-100 group-[.is-dismissed]/hc:invisible! group-[.is-dismissed]/hc:opacity-0! motion-reduce:translate-y-0 motion-reduce:transition-none">
          <div class="flex items-center gap-3"><span class="grid size-12 flex-none place-items-center rounded-full text-base font-bold text-white bg-[linear-gradient(135deg,#334155,#64748b)]" aria-hidden="true">OW</span><span><b class="block">Owen Walsh</b><span class="mt-0.5 block text-[.82rem] text-[#475569]">Engineering manager · Dublin, 15:42 local</span></span></div>
          <p class="mt-3 text-[.86rem] leading-normal text-[#475569]">Signs off on the hiring plan in section 5. Back from leave on Monday.</p>
          <dl class="mt-3 flex gap-[18px] text-[.8rem] text-[#475569]"><div class="flex flex-col-reverse"><dt>docs</dt><dd class="text-[.95rem] font-bold text-[#0f172a]">93</dd></div><div class="flex flex-col-reverse"><dt>reviews</dt><dd class="text-[.95rem] font-bold text-[#0f172a]">148</dd></div><div class="flex flex-col-reverse"><dt>joined</dt><dd class="text-[.95rem] font-bold text-[#0f172a]">2018</dd></div></dl>
          <div class="mt-3.5 flex gap-2"><a class="flex-1 rounded-[10px] border-[1.5px] border-[#2563eb] bg-[#2563eb] px-2.5 py-2 text-center text-[.84rem] font-bold text-white no-underline hover:bg-[#1d4ed8] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]" href="#">View profile<span class="sr-only"> of Owen Walsh</span></a><a class="flex-1 rounded-[10px] border-[1.5px] border-[#2563eb] px-2.5 py-2 text-center text-[.84rem] font-bold text-[#2563eb] no-underline hover:bg-[#2563eb] hover:text-white focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#2563eb]" href="#">Message<span class="sr-only"> Owen Walsh</span></a></div>
        </div></div>
        <span class="mt-0.5 block text-[.84rem] text-[#475569]">Last seen yesterday</span></div>
      <span class="flex-none text-[.8rem] font-semibold text-[#475569]">Away</span></li>
  </ul>
</section></div>
</div>
CSS
@theme {
  --animate-um-in: um-in .18s ease-out;
  @keyframes um-in { from { opacity: 0; transform: translateY(-6px); } }
}
JavaScript
/* Account menu: toggle on click; Escape closes it and returns focus to the button; a click outside or tabbing out closes it.
   Hover cards: Escape hides an open card until the pointer or focus leaves its name. */
document.querySelectorAll('.um').forEach(function (um) {
  var btn = um.querySelector('.um-btn'), menu = um.querySelector('.um-menu');
  function set(open) { btn.setAttribute('aria-expanded', String(open)); menu.hidden = !open; }
  btn.addEventListener('click', function () { set(menu.hidden); });
  um.addEventListener('keydown', function (e) { if (e.key === 'Escape' && !menu.hidden) { set(false); btn.focus(); } });
  um.addEventListener('focusout', function (e) { if (e.relatedTarget && !um.contains(e.relatedTarget)) set(false); });
  document.addEventListener('click', function (e) { if (!um.contains(e.target)) set(false); });
});
document.querySelectorAll('.hc').forEach(function (hc) {
  hc.addEventListener('keydown', function (e) { if (e.key === 'Escape') { hc.classList.add('is-dismissed'); hc.classList.remove('is-open'); } });
  hc.addEventListener('mouseleave', function () { if (!hc.contains(document.activeElement)) hc.classList.remove('is-dismissed'); });
  hc.addEventListener('focusout', function (e) { if (!hc.contains(e.relatedTarget)) hc.classList.remove('is-dismissed', 'is-open'); });
});

About this set

The small profile views an app shows everywhere. The account menu is a header bar with an avatar button that opens a panel with the user’s name, email and plan, a storage meter, links to the profile, settings, billing and workspaces, and Sign out. The button is a disclosure with aria-expanded; Escape closes the panel and returns focus to the button, and a click outside or tabbing away closes it too. The team list with hover cards shows who is in a document, each with an initials avatar, a presence dot, what they are doing and a status word such as Online or In a meeting. Hovering or focusing a name opens a mini profile with their role, local time, a short note, three counts and View profile and Message links. The card opens after a short delay on hover and at once on keyboard focus, stays open while the pointer or focus is inside it, and Escape dismisses it, which meets the hover content rules in WCAG 1.4.13. The Bootstrap version uses Bootstrap’s dropdown plugin for the menu.

What’s included

  • Account menu with a mini profile, storage meter and Sign out
  • Hover cards that also open on keyboard focus
  • Escape closes the menu and dismisses hover cards
  • Presence shown as text, not only as a coloured dot
  • Bootstrap version built on .dropdown-menu and .dropdown-item

Accessibility

The menu button reports aria-expanded and its name includes the user's full name. Hover cards are part of the focus order right after the name that opens them, so their links can be reached with Tab, and Escape hides them. Presence is written out as text next to each dot. Every control shows a visible focus outline, and the menu animation and card transitions stop under prefers-reduced-motion.

Customise it

Change --um-accent, --um-ink, --um-muted, --um-line and --um-soft on .um and .hl, and the avatar gradients in .um-av and the av-* classes. In Bootstrap the menu colours go through the --bs-dropdown-* variables; in Tailwind edit the colour utilities and the um-in animation in the theme block.