Skip to content

Instantly share code, notes, and snippets.

@wolfadex
Created May 23, 2026 02:46
Show Gist options
  • Select an option

  • Save wolfadex/54900355660171ee2bf0eb70b47f9294 to your computer and use it in GitHub Desktop.

Select an option

Save wolfadex/54900355660171ee2bf0eb70b47f9294 to your computer and use it in GitHub Desktop.
Elm tooltips, using popover and anchor
.tooltip {
position: absolute;
margin-bottom: 6px;
background: #1a1a1a;
color: #ffffff;
font-size: 12px;
padding: 5px 10px;
border-radius: 6px;
border: none;
width: max-content;
max-width: 220px;
position-area: center top;
position-try-fallbacks: --below;
}
module Tooltip exposing (..)
import Html exposing (Html)
import Html.Attributes
view : { anchor : List (Html.Attribute msg) -> Html msg, anchorId : String, label : String } -> Html msg
view opts =
let
tooltipId =
opts.anchorId ++ "-tooltip"
in
Html.div []
[ Html.div
[ Html.Attributes.id tooltipId
, Html.Attributes.attribute "popover" "manual"
, Html.Attributes.attribute "role" "tooltip"
, Html.Attributes.class "tooltip"
, Html.Attributes.style "position-anchor" ("--" ++ opts.anchorId)
]
[ Html.text opts.label ]
, opts.anchor
[ Html.Attributes.id opts.anchorId
, Html.Attributes.attribute "popovertarget" tooltipId
, Html.Attributes.attribute "aria-describedby" tooltipId
, Html.Attributes.attribute "data-tooltip-trigger" tooltipId
, Html.Attributes.style "anchor-name" ("--" ++ opts.anchorId)
, Html.Attributes.style "anchor" tooltipId
]
]
document.addEventListener("mouseover", handleTrigger);
document.addEventListener("focusin", handleTrigger);
function handleTrigger(e) {
const trigger = e.target.closest("[data-tooltip-trigger]");
if (!trigger) return;
const id = trigger.getAttribute("popovertarget");
const popover = document.getElementById(id);
if (!popover) return;
const delay =
e.type === "focusin"
? 0
: Number(
trigger.getAttribute("data-tooltip-delay") || "300",
);
const timer = setTimeout(() => {
popover.showPopover();
}, delay);
const hideEvent = e.type === "focusin" ? "focusout" : "mouseleave";
trigger.addEventListener(
hideEvent,
() => {
clearTimeout(timer);
popover.hidePopover();
},
{ once: true },
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment