You've already forked decomp.dev
mirror of
https://github.com/encounter/decomp.dev.git
synced 2026-07-10 03:18:48 -07:00
111 lines
2.9 KiB
TypeScript
111 lines
2.9 KiB
TypeScript
const themeToggleButton = document.getElementById('theme-toggle');
|
|
if (themeToggleButton) {
|
|
themeToggleButton.addEventListener('click', (e) => {
|
|
const root = document.documentElement;
|
|
const defaultDark =
|
|
window.matchMedia?.('(prefers-color-scheme: dark)').matches ?? true;
|
|
const themeAttr = root.getAttribute('data-theme');
|
|
const isDark = themeAttr === null ? defaultDark : themeAttr === 'dark';
|
|
root.setAttribute('data-theme', isDark ? 'light' : 'dark');
|
|
try {
|
|
localStorage.setItem('theme', isDark ? 'light' : 'dark');
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
e.preventDefault();
|
|
});
|
|
}
|
|
|
|
let tooltipElem: HTMLElement | null = null;
|
|
const applyTooltip = (elem: HTMLElement) => {
|
|
const text = elem.getAttribute('data-tooltip');
|
|
if (!text) {
|
|
return;
|
|
}
|
|
let tooltip = document.getElementById('tooltip');
|
|
if (!tooltip) {
|
|
tooltip = document.createElement('div');
|
|
tooltip.id = 'tooltip';
|
|
tooltip.addEventListener('transitionend', (e) => {
|
|
if (
|
|
e.propertyName === 'opacity' &&
|
|
e.target instanceof HTMLElement &&
|
|
e.target.style.opacity === '0'
|
|
) {
|
|
e.target.remove();
|
|
}
|
|
});
|
|
document.body.appendChild(tooltip);
|
|
}
|
|
tooltip.innerText = text;
|
|
tooltip.style.opacity = '1';
|
|
const rect = elem.getBoundingClientRect();
|
|
const scrollGutter =
|
|
document.documentElement.clientWidth - document.body.clientWidth;
|
|
const scrollX = window.scrollX - scrollGutter;
|
|
let left = rect.left + scrollX + (rect.width - tooltip.offsetWidth) / 2;
|
|
const docWidth =
|
|
document.documentElement.clientWidth || document.body.clientWidth;
|
|
if (left + tooltip.offsetWidth > docWidth) {
|
|
left = docWidth - tooltip.offsetWidth;
|
|
}
|
|
if (left < 0) {
|
|
left = 0;
|
|
}
|
|
let top = rect.top + window.scrollY - tooltip.offsetHeight;
|
|
if (top < 0) {
|
|
top = rect.bottom + window.scrollY;
|
|
}
|
|
tooltip.style.left = `${left}px`;
|
|
tooltip.style.top = `${top}px`;
|
|
const arrowLeft = rect.left + scrollX + rect.width / 2 - left;
|
|
tooltip.style.setProperty('--arrow-left', `${arrowLeft}px`);
|
|
tooltipElem = elem;
|
|
};
|
|
const removeTooltip = (elem: HTMLElement) => {
|
|
if (elem !== tooltipElem) {
|
|
return;
|
|
}
|
|
const tooltip = document.getElementById('tooltip');
|
|
if (tooltip) {
|
|
tooltip.style.opacity = '0';
|
|
}
|
|
tooltipElem = null;
|
|
};
|
|
document.addEventListener(
|
|
'mouseover',
|
|
(e) => {
|
|
if (e.target instanceof HTMLElement) {
|
|
applyTooltip(e.target);
|
|
}
|
|
},
|
|
{ passive: true },
|
|
);
|
|
document.addEventListener(
|
|
'mouseout',
|
|
(e) => {
|
|
if (e.target instanceof HTMLElement) {
|
|
removeTooltip(e.target);
|
|
}
|
|
},
|
|
{ passive: true },
|
|
);
|
|
document.addEventListener(
|
|
'touchstart',
|
|
(e) => {
|
|
if (e.target instanceof HTMLElement) {
|
|
applyTooltip(e.target);
|
|
}
|
|
},
|
|
{ passive: true },
|
|
);
|
|
document.addEventListener(
|
|
'touchend',
|
|
(e) => {
|
|
if (e.target instanceof HTMLElement) {
|
|
removeTooltip(e.target);
|
|
}
|
|
},
|
|
{ passive: true },
|
|
);
|