Shell: tooltips at once, one or two words; text-size buttons are drawn − and +
Every header and top-bar button's title becomes a tip the shell shows the moment the pointer arrives (the browser's own waits a second and looks different everywhere); it moves from `title` to data-tip so the native one never appears, and a module that sets `title` again is picked up on the next hover. The shell's own labels are "Settings" and "Remove"; the top bar's are "Fullscreen", "Add tile", "Layouts", "Admin"; Slack, PCO Plan, ProdCom and Timers shorten theirs to match. A− / A+ are a drawn − and + in Slack, PCO Plan and ProdCom, sized like every other header icon. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
1930fb142d
commit
818def822d
+68
-2
@@ -283,7 +283,7 @@ function buildTile(tile) {
|
||||
if (hasSettings) {
|
||||
const gear = document.createElement('button');
|
||||
gear.className = 'tile-btn';
|
||||
gear.title = 'Tile settings (this tile only)';
|
||||
gear.title = 'Settings';
|
||||
gear.innerHTML = GEAR_SVG;
|
||||
gear.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
@@ -294,7 +294,7 @@ function buildTile(tile) {
|
||||
|
||||
const close = document.createElement('button');
|
||||
close.className = 'tile-btn close';
|
||||
close.title = 'Remove this tile';
|
||||
close.title = 'Remove';
|
||||
close.innerHTML = CLOSE_SVG; // a drawn cross, the same size in every browser (the ✕ glyph varies)
|
||||
close.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
@@ -1106,6 +1106,72 @@ function tileSchema(tile, man) {
|
||||
};
|
||||
}
|
||||
|
||||
/* ── tooltips: at once on hover, short, one for the whole page ──────────
|
||||
Every header and top-bar button's `title` becomes a tip the shell shows
|
||||
the moment the pointer arrives — the browser's own waits about a second
|
||||
and looks different in each browser. The text moves from `title` to
|
||||
data-tip so the native one never appears; a module that sets `title`
|
||||
again later is picked up on the next hover. */
|
||||
let tipEl = null;
|
||||
const TIP_TARGETS = '.tile-btn, .tb-btn, [data-tip]';
|
||||
|
||||
function tipTextFor(el) {
|
||||
if (el.title) {
|
||||
el.dataset.tip = el.title;
|
||||
if (!el.getAttribute('aria-label')) el.setAttribute('aria-label', el.title);
|
||||
el.removeAttribute('title');
|
||||
}
|
||||
return el.dataset.tip || '';
|
||||
}
|
||||
|
||||
function showTip(el) {
|
||||
const text = tipTextFor(el);
|
||||
if (!text) return;
|
||||
if (!tipEl) {
|
||||
tipEl = document.createElement('div');
|
||||
tipEl.id = 'tip';
|
||||
tipEl.setAttribute('role', 'tooltip');
|
||||
document.body.appendChild(tipEl);
|
||||
}
|
||||
tipEl.textContent = text;
|
||||
tipEl.hidden = false;
|
||||
const r = el.getBoundingClientRect();
|
||||
const w = tipEl.offsetWidth;
|
||||
const h = tipEl.offsetHeight;
|
||||
const left = Math.max(6, Math.min(r.left + r.width / 2 - w / 2, window.innerWidth - w - 6));
|
||||
let top = r.bottom + 6;
|
||||
if (top + h > window.innerHeight - 6) top = r.top - h - 6;
|
||||
tipEl.style.left = `${Math.round(left)}px`;
|
||||
tipEl.style.top = `${Math.round(top)}px`;
|
||||
tipEl._for = el;
|
||||
}
|
||||
|
||||
function hideTip(el = null) {
|
||||
if (!tipEl || tipEl.hidden) return;
|
||||
if (el && tipEl._for !== el) return;
|
||||
tipEl.hidden = true;
|
||||
tipEl._for = null;
|
||||
}
|
||||
|
||||
document.addEventListener('pointerover', (e) => {
|
||||
const el = e.target?.closest?.(TIP_TARGETS);
|
||||
if (!el || (tipEl && tipEl._for === el && !tipEl.hidden)) return;
|
||||
showTip(el);
|
||||
});
|
||||
document.addEventListener('pointerout', (e) => {
|
||||
const el = e.target?.closest?.(TIP_TARGETS);
|
||||
if (!el || (e.relatedTarget && el.contains(e.relatedTarget))) return;
|
||||
hideTip(el);
|
||||
});
|
||||
document.addEventListener('pointerdown', () => hideTip(), true);
|
||||
document.addEventListener('focusin', (e) => {
|
||||
const el = e.target?.closest?.(TIP_TARGETS);
|
||||
if (el) showTip(el);
|
||||
});
|
||||
document.addEventListener('focusout', () => hideTip());
|
||||
window.addEventListener('scroll', () => hideTip(), true);
|
||||
window.addEventListener('resize', () => hideTip());
|
||||
|
||||
function closeSettingsPopovers() {
|
||||
document.querySelectorAll('.tile-settings').forEach((p) => {
|
||||
p._cleanup?.();
|
||||
|
||||
Reference in New Issue
Block a user