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.
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.
<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.
.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.