Hotspots
A hotspot is shipdot’s signature feature: when an unread entry has a target, the widget finds that element on the page and draws a pulsing dot on its top-right corner. Clicking the dot (or pressing Enter on it) opens a tooltip with the note. Got it marks the entry as read and removes the dot.
---date: 2026-10-14type: newtitle: Export to Exceltarget: "#btn-export"---Choosing a selector
Section titled “Choosing a selector”target is any CSS selector accepted by document.querySelector. The first match is used. Prefer selectors that survive refactors:
- An
id:#btn-export. - A dedicated data attribute:
[data-shipdot="export"]. This makes the intent obvious to whoever touches that markup later.
Avoid generated class names (CSS modules, Tailwind utility soup); they change between builds.
Behavior
Section titled “Behavior”- Only unread entries get hotspots. Opening the feed panel marks everything as read, which also removes the dots.
- At most
max-hotspotsdots are visible at once (default 3), newest first. - The dot is hidden while its target is not visible:
display: none,visibility: hidden, zero size, or scrolled out of the viewport. - It follows the target on scroll, resize and layout changes (ResizeObserver plus rAF-throttled scroll and resize listeners).
- Late targets are supported: in single-page apps the element can appear after navigation. A MutationObserver watches the DOM only while some target is still missing, and disconnects as soon as all of them are found.
- Keyboard: dots are real
<button>s. Enter opens the tooltip, Esc closes it and returns focus to the dot. - Motion: with
prefers-reduced-motion: reducethe pulse animation is replaced by a static ring. - An invalid selector dispatches a
shipdot:errorevent and is ignored.
Hotspots live in their own fixed layer at the end of <body>, with its own shadow root, so overflow: hidden or transformed ancestors in your app never clip or shift them.
Turning them off
Section titled “Turning them off”<ship-dot src="/shipdot.json" hotspots="off"></ship-dot><ship-dot src="/shipdot.json" max-hotspots="1"></ship-dot>Styling
Section titled “Styling”The layer copies the widget’s custom properties. Dots use --shipdot-hotspot (pink by default, so they stand out on brand-colored buttons); tooltips use the rest of the theme. For deeper changes, target the layer’s parts:
.shipdot-layer::part(hotspot) { /* the dot button */ }.shipdot-layer::part(tooltip) { /* the tooltip */ }.shipdot-layer::part(got-it) { /* the "Got it" button */ }Limitations
Section titled “Limitations”- Elements inside other components’ shadow roots or inside iframes can’t be targeted (
document.querySelectordoes not reach them). - Hotspots are tab-ordered at the end of the page, after your content.