Connection lost. Reconnecting… attempt 1 of 8
Paused. Your work is held on the server.
Could not reconnect.
This session has expired on the server.
An unhandled error has occurred.
Sedna.UI
v0.17.0 · main

Hover hints

tier 2 — classes

A one-line explanation of what a control does and what happens if you press it, attached with data-tip and nothing else. Part of the frame rather than of the script's API: one bubble serves the whole document, and no page writes a class for it.

A hint explains a consequence, not a label data-tip="Export" on a button that already says Export is noise, and the engine drops it — a hint whose text is already in the trigger's own visible text is not shown at all, unless that text is cut short, when the hint gives back what the ellipsis hid. Write the thing the label had no room for: what it acts on, and what changes.

On any control

data-tip works on anything — a button, an icon button, a badge, a status chip. It is delegated from document, so content rendered later needs no wiring and a Blazor re-render cannot break it. The bubble is a single .sedna-tip appended to <body> and faded in with .sedna-tip--visible; you write neither. It is position: fixed for one reason — a ::after tooltip is clipped by the first card or table that scrolls.

Awaiting stock Degraded
<div class="sedna-row-wrap sedna-gap-2">
    <button class="btn" type="button" data-tip="Reload the list from the server. Unsaved notes are kept.">
        <i class="ri-refresh-line"></i> Refresh
    </button>
    <button class="btn btn-icon" type="button" aria-label="Export"
            data-tip="Downloads every row that matches the current filters, as CSV.">
        <i class="ri-download-2-line"></i>
    </button>
    <button class="btn btn-danger" type="button"
            data-tip="Deletes the reservation. The order goes back to unreserved." data-tip-pos="right">
        <i class="ri-delete-bin-line"></i> Discard
    </button>
    <span class="badge badge-warn" data-tip="Two of five lines have no stock in any warehouse."
          data-tip-pos="bottom">Awaiting stock</span>
    <span class="health-badge health-badge--degraded" data-tip="One of three warehouses is not answering."
          data-tip-pos="top"><span class="health-dot"></span> Degraded</span>
</div>

Which side

data-tip-pos takes top (the default), bottom, left or right. The vertical pair auto-flips when the preferred side has no room, and the bubble is then clamped so the whole of it stays inside the viewport — so a hint on a control at the very top of the page opens downwards without being told to.

<div class="sedna-row-wrap sedna-gap-3" style="justify-content:center; padding:28px 0">
    <button class="btn" type="button" data-tip-pos="top"
            data-tip="Above the control. The default, and what a toolbar wants.">
        Top
    </button>
    <button class="btn" type="button" data-tip-pos="bottom"
            data-tip="Below the control. Right for anything near the top of the page.">
        Bottom
    </button>
    <button class="btn" type="button" data-tip-pos="left"
            data-tip="To the left of the control, centred on it.">
        Left
    </button>
    <button class="btn" type="button" data-tip-pos="right"
            data-tip="To the right of the control, centred on it.">
        Right
    </button>
</div>

On touch

A finger has no hover, so press and hold shows the hint — a third of a second: longer than a tap, shorter than the platform's own long press, which would select the text instead — and it stays a moment after the finger lifts so it can be read with the finger out of the way. The press that showed it does not also act: the click that follows a long press is swallowed, so holding “Delete” to find out what it deletes never deletes anything. A tap is unchanged. That is the practice the platforms themselves use for a link's address, and the reason the hint is still supplementary: a reader who never holds anything still has the label and the page.

Both themes

The bubble resolves through --tip-bg, --tip-border, --tip-fg and --shadow-tip, so it follows the variant like every other surface: a dark bubble on the dark theme and a light one on the light theme. Flip the theme in the header and hover any control above.

Nothing inside .sidebar gets one The collapsed rail already has a CSS flyout for the same job, and both firing draws two tooltips over each other. The engine skips the whole subtree, so a data-tip on a nav link is silently inert — which is the intended answer, not a bug to work around.

Suppressing them

Assign a predicate to sednaUi.tips.gate and it is asked before every hint, with the trigger element. Use it while something else owns the reader's attention — a guided tour, a drag in progress. The library has no knowledge of what is suppressing them, which is why this is a predicate and not a setting. From C#, where the reason is usually a setting the app already holds, ISednaUi.SetTipsEnabledAsync(false) switches every hint off and hides the one showing; both apply together.

// Suppress hints while something else owns the reader's attention — a tour, a modal,
// a drag in progress. The library has no knowledge of what is suppressing them.
sednaUi.tips.gate = el => !document.body.classList.contains('tour-active');

// Or all of them, from a setting — the form C# has, as ISednaUi.SetTipsEnabledAsync:
sednaUi.tips.setEnabled(false);

What it is not

A hint is supplementary. The bubble carries role="tooltip" and appears on hover and focus, but it is not reachable by touch and it is not an accessible name — so a control whose only label is a data-tip has no label. Give an icon button an aria-label and let the hint add the consequence on top of it, the way the icon button in the first example does. Anything a reader must have in order to act belongs in the page, in a .form-hint or a callout.