Initialize tooltips dynamically

This commit is contained in:
Konrad Szwarc 2023-01-31 21:55:15 +01:00
parent 544ad70d87
commit f51c4044b9

View file

@ -1,5 +1,4 @@
import { autoUpdate, computePosition, flip, offset, Placement, shift } from '@floating-ui/dom'; import type { Placement } from '@floating-ui/dom';
import { nanoid } from 'nanoid';
interface UpdateTooltipOptions { interface UpdateTooltipOptions {
element: HTMLElement; element: HTMLElement;
@ -7,7 +6,13 @@ interface UpdateTooltipOptions {
placement: Placement; placement: Placement;
} }
const updateTooltip = const elementsWithTooltipData = [...document.querySelectorAll('[data-tooltip]')] as HTMLElement[];
if (elementsWithTooltipData.length > 0) {
Promise.all([import('@floating-ui/dom'), import('nanoid')]).then(([floatingUi, { nanoid }]) => {
const { autoUpdate, computePosition, flip, offset, shift } = floatingUi;
const updateTooltip =
({ element, tooltip, placement }: UpdateTooltipOptions) => ({ element, tooltip, placement }: UpdateTooltipOptions) =>
() => { () => {
computePosition(element, tooltip, { placement, middleware: [offset(8), flip(), shift({ padding: 8 })] }).then( computePosition(element, tooltip, { placement, middleware: [offset(8), flip(), shift({ padding: 8 })] }).then(
@ -20,10 +25,10 @@ const updateTooltip =
); );
}; };
const tooltipClass = const tooltipClass =
/* tw */ 'absolute top-0 left-0 hidden max-w-sm animate-show rounded-lg bg-gray-700 px-3 py-1 text-white dark:bg-gray-100 dark:text-gray-800 sm:max-w-xs'; /* tw */ 'absolute top-0 left-0 hidden max-w-sm animate-show rounded-lg bg-gray-700 px-3 py-1 text-white dark:bg-gray-100 dark:text-gray-800 sm:max-w-xs';
const createTooltip = (content: string) => { const createTooltip = (content: string) => {
const tooltip = document.createElement('div'); const tooltip = document.createElement('div');
tooltip.innerText = content; tooltip.innerText = content;
@ -32,9 +37,9 @@ const createTooltip = (content: string) => {
tooltip.setAttribute('role', 'tooltip'); tooltip.setAttribute('role', 'tooltip');
return tooltip; return tooltip;
}; };
const addListeners = (element: HTMLElement, tooltip: HTMLElement, updateFn: () => void) => { const addListeners = (element: HTMLElement, tooltip: HTMLElement, updateFn: () => void) => {
element.addEventListener('mouseenter', () => { element.addEventListener('mouseenter', () => {
tooltip.style.display = 'block'; tooltip.style.display = 'block';
updateFn(); updateFn();
@ -43,9 +48,9 @@ const addListeners = (element: HTMLElement, tooltip: HTMLElement, updateFn: () =
element.addEventListener('mouseleave', () => { element.addEventListener('mouseleave', () => {
tooltip.style.display = ''; tooltip.style.display = '';
}); });
}; };
const creteTooltipsForElements = (elements: HTMLElement[]) => { const creteTooltipsForElements = (elements: HTMLElement[]) => {
const tooltipsContainer = document.createElement('div'); const tooltipsContainer = document.createElement('div');
const tooltips = elements.map((element) => { const tooltips = elements.map((element) => {
@ -57,12 +62,9 @@ const creteTooltipsForElements = (elements: HTMLElement[]) => {
document.body.appendChild(tooltipsContainer); document.body.appendChild(tooltipsContainer);
return tooltips; return tooltips;
}; };
const elements = [...document.querySelectorAll('[data-tooltip]')] as HTMLElement[]; creteTooltipsForElements(elementsWithTooltipData).forEach(({ element, tooltip }) => {
const elementsWithTooltips = creteTooltipsForElements(elements);
elementsWithTooltips.forEach(({ element, tooltip }) => {
const placement = (element.dataset.tooltipPlacement ?? 'top') as Placement; const placement = (element.dataset.tooltipPlacement ?? 'top') as Placement;
const updateFn = updateTooltip({ element, tooltip, placement }); const updateFn = updateTooltip({ element, tooltip, placement });
@ -70,4 +72,6 @@ elementsWithTooltips.forEach(({ element, tooltip }) => {
autoUpdate(element, tooltip, updateFn); autoUpdate(element, tooltip, updateFn);
addListeners(element, tooltip, updateFn); addListeners(element, tooltip, updateFn);
}); });
});
}