Beta

Tooltip Group <mv-tooltip-group>

Tooltip, den sich eine Gruppe von Auslösern teilt, etwa eine Toolbar: Nach der ersten Verzögerung gleitet eine einzige Blase von Button zu Button, passt ihre Größe an und blendet ihr Label über, ohne Schließen, erneutes Öffnen oder zweites Warten.

KategorieOverlays
TypWeb Component (<mv-tooltip-group>)
StatusBeta
Keywordstooltip, morphic-tooltip, shared-layout, toolbar, hint, glide, morph

When to use

  • A toolbar of icon buttons needs one tooltip that slides between triggers instead of reopening each time
  • Users scan adjacent controls quickly and each label should appear instantly after the first delay
  • A label changes in place after an action, such as Copy link becoming Link copied

Avoid when

  • The triggers are scattered across the page rather than grouped side by side → use Tooltip instead
  • The hint holds interactive content or must work on touch devices → use Popover instead

Installation

node scripts/add.mjs tooltip-group --out ./src/marvelous

KI-Agent mit dem MCP-Server von Marvelous UI: install_components({ slugs: ["tooltip-group"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Kopierte Dateien (inklusive Abhängigkeiten): tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/position.js, components/tooltip-group/tooltip-group.js, components/tooltip-group/tooltip-group.css.

Verwendung

Referenz-Markup zum Starten und Anpassen mit Attributen, data-* und CSS-Variablen:

<div id="tg-demo" style="display:flex;flex-wrap:wrap;gap:3rem 4rem;align-items:center;justify-content:center;padding-block:2.5rem">
  <style>
    #tg-demo .tg-bar { display: flex; align-items: center; gap: 2px; padding: 4px; border: 1px solid var(--mv-border); border-radius: var(--mv-radius-lg); background: var(--mv-surface-raised); box-shadow: var(--mv-shadow-sm); }
    #tg-demo .tg-bar[aria-orientation="vertical"] { flex-direction: column; }
    #tg-demo .tg-sep { flex: none; width: 1px; height: 1.25rem; margin: 0 4px; background: var(--mv-border); }
    #tg-demo .tg-bar[aria-orientation="vertical"] .tg-sep { width: 1.25rem; height: 1px; margin: 4px 0; }
    #tg-demo .tg-bar svg { width: 1rem; height: 1rem; }
    #tg-demo .tg-cap { margin: .875rem 0 0; text-align: center; font-size: .75rem; color: var(--mv-fg-muted); }
  </style>

  <figure style="margin:0">
    <mv-tooltip-group delay="400">
      <div class="tg-bar" role="toolbar" aria-label="Text formatting">
        <button class="mv-button" data-variant="ghost" data-size="icon" aria-label="Bold" data-tooltip="Bold" data-tooltip-kbd="⌘B"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M7 5h6a3.5 3.5 0 0 1 0 7H7zM7 12h7a3.5 3.5 0 0 1 0 7H7z"/></svg></button>
        <button class="mv-button" data-variant="ghost" data-size="icon" aria-label="Italic" data-tooltip="Italic" data-tooltip-kbd="⌘I"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M14 5h5M5 19h5M15 5 9 19"/></svg></button>
        <button class="mv-button" data-variant="ghost" data-size="icon" aria-label="Strikethrough" data-tooltip="Strikethrough" data-tooltip-kbd="⇧⌘X"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 12h16M16 6.5A4 3 0 0 0 12 5c-2.5 0-4 1.3-4 3M8 17.5A4 3 0 0 0 12 19c2.5 0 4-1.3 4-3"/></svg></button>
        <span class="tg-sep" aria-hidden="true"></span>
        <button class="mv-button" data-variant="ghost" data-size="icon" aria-label="Mention" data-tooltip-template="tg-demo-mention"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M16 8v5a3 3 0 0 0 5 0v-1a9 9 0 1 0-3.5 7.1"/></svg></button>
        <button class="mv-button" data-variant="ghost" data-size="icon" aria-label="Copy link" data-tooltip="Copy link" id="tg-demo-copy"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M10 14a4 4 0 0 0 5.7 0l3-3a4 4 0 0 0-5.7-5.7l-1 1M14 10a4 4 0 0 0-5.7 0l-3 3a4 4 0 0 0 5.7 5.7l1-1"/></svg></button>
      </div>
    </mv-tooltip-group>
    <template id="tg-demo-mention"><span style="display:grid;gap:2px"><strong>Mention someone</strong><span style="opacity:.72;font-weight:400">Type @ then a name, like @Aiko</span></span></template>
    <figcaption class="tg-cap">One bubble slides from button to button</figcaption>
  </figure>

  <figure style="margin:0;display:flex;align-items:center;gap:1rem">
    <mv-tooltip-group placement="right" delay="300">
      <nav class="tg-bar" role="toolbar" aria-orientation="vertical" aria-label="Workspace">
        <button class="mv-button" data-variant="ghost" data-size="icon" aria-label="Inbox" data-tooltip="Inbox: 3 unread"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 13h4l1.5 3h5L16 13h4M5 6h14l1 7v5H4v-5z"/></svg></button>
        <button class="mv-button" data-variant="ghost" data-size="icon" aria-label="Calendar" data-tooltip="Calendar"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><rect x="4" y="5" width="16" height="15" rx="2"/><path d="M4 10h16M9 3v4M15 3v4"/></svg></button>
        <span class="tg-sep" aria-hidden="true"></span>
        <button class="mv-button" data-variant="ghost" data-size="icon" aria-label="Settings" data-tooltip="Settings" data-tooltip-kbd="⌘,"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M12 3v2.5M12 18.5V21M3 12h2.5M18.5 12H21M5.6 5.6l1.8 1.8M16.6 16.6l1.8 1.8M5.6 18.4l1.8-1.8M16.6 7.4l1.8-1.8"/></svg></button>
      </nav>
    </mv-tooltip-group>
    <figcaption class="tg-cap" style="margin:0;max-width:9rem;text-align:start">Side rail: placement="right", resizing to each label</figcaption>
  </figure>

  <script type="module">
    const copy = document.querySelector("#tg-demo-copy");
    let timer = 0;
    copy?.addEventListener("click", () => {
      navigator.clipboard?.writeText("https://example.com/doc/roadmap-2027").catch(() => {});
      copy.dataset.tooltip = "Link copied";
      copy.closest("mv-tooltip-group")?.show(copy); // the press closed it: confirm in place
      clearTimeout(timer);
      timer = setTimeout(() => { copy.dataset.tooltip = "Copy link"; }, 1600);
    });
  </script>
</div>

API

Attributes

NameTypDefaultDescription
placementtop | bottom | left | right[-start|-end]topDefault side (auto flip); override per trigger with data-placement.
delaynumber500Delay before the first appearance (ms). While the bubble is open, or just after any tooltip closed (mv-tooltip included), moving to another trigger is instant.
close-delaynumber160Grace period before closing when the pointer leaves a trigger (lets it cross the gap between two buttons).
offsetnumber8Distance from the trigger (px).
disabledbooleanDisables the whole group.
data-arrow="false"stringHides the arrow.

Properties

NameTypDescription
activeTriggerHTMLElement | nullTrigger currently being described.
isOpenbooleanWhether the bubble is visible (read-only).

Methods

NameDescription
show(trigger)Shows the bubble on a trigger, sliding over if it is already open.
hide()Closes the surface.

Events

NameDescription
mv-openFirst appearance. detail: { trigger }.
mv-changeThe bubble slid to another trigger. detail: { trigger }.
mv-closeAfter closing.

Content structure

NameDescription
[data-tooltip]Any descendant carrying this text becomes a trigger (delegated: elements added later work too). Changing it while open crossfades the label in place.
[data-tooltip-kbd]Shortcut shown to the right of the label.
[data-tooltip-template="id"]Rich content: a clone of a <template id> in the document.
[data-placement]Trigger-specific side.
[data-tooltip-disabled]Ignores this trigger.

CSS variables

NameDefaultDescription
--mv-tooltip-bgBackground (shared with mv-tooltip).
--mv-tooltip-fgText color (shared with mv-tooltip).
--mv-tooltip-group-durationvar(--mv-duration-normal)Duration of the slide and resize between triggers.

Accessibility

A single role=tooltip bubble, linked to the active trigger with aria-describedby (skipped when the label only repeats the trigger name). Opens at once on keyboard focus (:focus-visible), closes on Escape, on press and when focus or pointer leaves the group. The open bubble can be hovered without closing (WCAG 1.4.13). Never opens on touch. Outgoing labels are aria-hidden. Reduced motion makes the slide and crossfade instant; forced colors add an outline.

Diese Seite wurde mit KI übersetzt. Übersetzungsfehler melden