diff --git a/index.html b/index.html index 6b622b4..fc86178 100644 --- a/index.html +++ b/index.html @@ -2410,17 +2410,32 @@

{title}

// untouched — a legend entry only becomes interactive where a caller says so. function LegendDot({ color, label, hollow, onClick, dim, title }) { const act = typeof onClick === "function"; + const ref = React.useRef(null); + const tooltip = React.useRef(null); + React.useEffect(() => { + if (!title || !window.tippy || !ref.current) return; + const instance = window.tippy(ref.current, { + content: title, allowHTML: false, theme: "light-border", arrow: true, + maxWidth: 360, offset: [0, 8], placement: "top", + }); + tooltip.current = instance; + return () => { instance.destroy(); tooltip.current = null; }; + }, [title]); return ( { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onClick(); } }) : undefined} + onKeyDown={e => { + if (e.key === "Escape" && tooltip.current) tooltip.current.hide(); + if (act && (e.key === "Enter" || e.key === " ")) { e.preventDefault(); onClick(); } + }} style={{ display: "inline-flex", alignItems: "center", gap: 7, fontSize: 12.5, color: "var(--ink-soft)", - opacity: dim ? 0.34 : 1, cursor: act ? "pointer" : undefined, + opacity: dim ? 0.34 : 1, cursor: act ? "pointer" : title ? "help" : undefined, userSelect: act ? "none" : undefined, transition: "opacity .12s" }}> {label} + ); } diff --git a/web/demo/60-atoms.jsx b/web/demo/60-atoms.jsx index aa163d0..b8e0a55 100644 --- a/web/demo/60-atoms.jsx +++ b/web/demo/60-atoms.jsx @@ -24,17 +24,32 @@ function Eyebrow({ children }) { // untouched — a legend entry only becomes interactive where a caller says so. function LegendDot({ color, label, hollow, onClick, dim, title }) { const act = typeof onClick === "function"; + const ref = React.useRef(null); + const tooltip = React.useRef(null); + React.useEffect(() => { + if (!title || !window.tippy || !ref.current) return; + const instance = window.tippy(ref.current, { + content: title, allowHTML: false, theme: "light-border", arrow: true, + maxWidth: 360, offset: [0, 8], placement: "top", + }); + tooltip.current = instance; + return () => { instance.destroy(); tooltip.current = null; }; + }, [title]); return ( { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onClick(); } }) : undefined} + onKeyDown={e => { + if (e.key === "Escape" && tooltip.current) tooltip.current.hide(); + if (act && (e.key === "Enter" || e.key === " ")) { e.preventDefault(); onClick(); } + }} style={{ display: "inline-flex", alignItems: "center", gap: 7, fontSize: 12.5, color: "var(--ink-soft)", - opacity: dim ? 0.34 : 1, cursor: act ? "pointer" : undefined, + opacity: dim ? 0.34 : 1, cursor: act ? "pointer" : title ? "help" : undefined, userSelect: act ? "none" : undefined, transition: "opacity .12s" }}> {label} + ); }