refactor: replace popperjs with floating-ui

This commit is contained in:
Yassine Doghri 2021-12-31 09:42:52 +00:00
parent 02557539e6
commit ad5cd2c2e9
5 changed files with 115 additions and 56 deletions

View File

@ -1,4 +1,10 @@
import { createPopper, Instance, Placement } from "@popperjs/core";
import {
computePosition,
flip,
offset,
Placement,
shift,
} from "@floating-ui/dom";
const Dropdown = (): void => {
const dropdownButtons: NodeListOf<HTMLButtonElement> =
@ -16,46 +22,46 @@ const Dropdown = (): void => {
// place the menu at then end of the body to prevent any overflow cuts
document.body.appendChild(menu);
let popperInstance: Instance | null = null;
const create = () => {
const update = () => {
const offsetX = menu.dataset.dropdownOffsetX
? parseInt(menu.dataset.dropdownOffsetX)
: 0;
const offsetY = menu.dataset.dropdownOffsetY
? parseInt(menu.dataset.dropdownOffsetY)
: 0;
popperInstance = createPopper(button, menu, {
computePosition(button, menu, {
placement: menu.dataset.dropdownPlacement as Placement,
modifiers: [
{
name: "offset",
options: {
offset: [offsetX, offsetY],
},
},
middleware: [
offset({ mainAxis: offsetY, crossAxis: offsetX }),
flip(),
shift(),
],
}).then(({ x, y }) => {
Object.assign(menu.style, {
left: `${x}px`,
top: `${y}px`,
});
});
};
const destroy = () => {
if (popperInstance) {
popperInstance.destroy();
popperInstance = null;
}
const showMenu = () => {
menu.setAttribute("data-show", "");
button.setAttribute("aria-expanded", "true");
update();
};
const hideMenu = () => {
menu.removeAttribute("data-show");
button.setAttribute("aria-expanded", "false");
};
const dropdownToggle = () => {
const isExpanded = menu.hasAttribute("data-show");
if (isExpanded) {
menu.removeAttribute("data-show");
button.setAttribute("aria-expanded", "false");
destroy();
hideMenu();
} else {
menu.setAttribute("data-show", "");
button.setAttribute("aria-expanded", "true");
create();
showMenu();
}
};

View File

@ -1,4 +1,12 @@
import { createPopper, Placement } from "@popperjs/core";
import { Coords } from "@floating-ui/core";
import {
arrow,
computePosition,
flip,
offset,
Placement,
shift,
} from "@floating-ui/dom";
const Tooltip = (): void => {
const tooltipContainers: NodeListOf<HTMLElement> =
@ -12,30 +20,60 @@ const Tooltip = (): void => {
tooltip.setAttribute("id", "tooltip" + i);
tooltip.setAttribute(
"class",
"px-2 py-1 text-sm bg-gray-900 text-white rounded max-w-xs z-50"
"absolute px-2 py-1 text-sm bg-gray-900 text-white rounded max-w-xs z-50"
);
tooltip.innerHTML = tooltipContent;
const arrowElement = document.createElement("div");
arrowElement.setAttribute(
"class",
"absolute bg-gray-900 w-2 h-2 rotate-45"
);
arrowElement.setAttribute("id", "arrow" + i);
tooltip.appendChild(arrowElement);
const popper = createPopper(tooltipReference, tooltip, {
placement: tooltipReference.dataset.tooltip as Placement,
modifiers: [
{
name: "offset",
options: {
offset: [0, 8],
},
},
],
});
const update = () => {
computePosition(tooltipReference, tooltip, {
placement: tooltipReference.dataset.tooltip as Placement,
middleware: [
flip(),
shift(),
offset(8),
arrow({ element: arrowElement }),
],
}).then(({ x, y, placement, middlewareData }) => {
Object.assign(tooltip.style, {
left: `${x}px`,
top: `${y}px`,
});
const show = () => {
// Accessing the data
const { x: arrowX, y: arrowY } = middlewareData.arrow as Coords;
const staticSide = {
top: "bottom",
right: "left",
bottom: "top",
left: "right",
}[placement.split("-")[0]];
Object.assign(arrowElement.style, {
left: arrowX != null ? `${arrowX}px` : "",
top: arrowY != null ? `${arrowY}px` : "",
right: "",
bottom: "",
[staticSide as string]: "-4px",
});
});
};
const showTooltip = () => {
tooltipReference.removeAttribute("title");
tooltipReference.setAttribute("aria-describedby", "tooltip" + i);
document.body.appendChild(tooltip);
popper.update();
update();
};
const hide = () => {
const hideTooltip = () => {
const element = document.getElementById("tooltip" + i);
tooltipReference.removeAttribute("aria-describedby");
tooltipReference.setAttribute("title", tooltipContent);
@ -48,11 +86,11 @@ const Tooltip = (): void => {
const hideEvents = ["mouseleave", "blur"];
showEvents.forEach((event) => {
tooltipReference.addEventListener(event, show);
tooltipReference.addEventListener(event, showTooltip);
});
hideEvents.forEach((event) => {
tooltipReference.addEventListener(event, hide);
tooltipReference.addEventListener(event, hideTooltip);
});
}
};

View File

@ -1,8 +1,8 @@
@layer base {
[data-dropdown="menu"] {
@apply z-50;
@apply absolute z-50;
}
[data-dropdown="menu"]:not([data-show]) {
@apply absolute top-0 left-0 invisible pointer-events-none;
@apply hidden;
}
}

39
package-lock.json generated
View File

@ -16,11 +16,11 @@
"@codemirror/lang-xml": "^0.19.2",
"@codemirror/state": "^0.19.6",
"@codemirror/view": "^0.19.32",
"@floating-ui/dom": "^0.1.10",
"@github/clipboard-copy-element": "^1.1.2",
"@github/hotkey": "^1.6.1",
"@github/markdown-toolbar-element": "^2.1.0",
"@github/time-elements": "^3.1.2",
"@popperjs/core": "^2.11.0",
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
"@vime/core": "^5.3.0",
"choices.js": "^9.0.1",
@ -2355,6 +2355,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@floating-ui/core": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.3.1.tgz",
"integrity": "sha512-ensKY7Ub59u16qsVIFEo2hwTCqZ/r9oZZFh51ivcLGHfUwTn8l1Xzng8RJUe91H/UP8PeqeBronAGx0qmzwk2g=="
},
"node_modules/@floating-ui/dom": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.1.10.tgz",
"integrity": "sha512-4kAVoogvQm2N0XE0G6APQJuCNuErjOfPW8Ux7DFxh8+AfugWflwVJ5LDlHOwrwut7z/30NUvdtHzQ3zSip4EzQ==",
"dependencies": {
"@floating-ui/core": "^0.3.0"
}
},
"node_modules/@foliojs-fork/fontkit": {
"version": "1.9.1",
"license": "MIT",
@ -2606,14 +2619,6 @@
"@octokit/openapi-types": "^11.2.0"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.0",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@rollup/plugin-babel": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz",
@ -18285,6 +18290,19 @@
}
}
},
"@floating-ui/core": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.3.1.tgz",
"integrity": "sha512-ensKY7Ub59u16qsVIFEo2hwTCqZ/r9oZZFh51ivcLGHfUwTn8l1Xzng8RJUe91H/UP8PeqeBronAGx0qmzwk2g=="
},
"@floating-ui/dom": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.1.10.tgz",
"integrity": "sha512-4kAVoogvQm2N0XE0G6APQJuCNuErjOfPW8Ux7DFxh8+AfugWflwVJ5LDlHOwrwut7z/30NUvdtHzQ3zSip4EzQ==",
"requires": {
"@floating-ui/core": "^0.3.0"
}
},
"@foliojs-fork/fontkit": {
"version": "1.9.1",
"requires": {
@ -18491,9 +18509,6 @@
"@octokit/openapi-types": "^11.2.0"
}
},
"@popperjs/core": {
"version": "2.11.0"
},
"@rollup/plugin-babel": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz",

View File

@ -34,11 +34,11 @@
"@codemirror/lang-xml": "^0.19.2",
"@codemirror/state": "^0.19.6",
"@codemirror/view": "^0.19.32",
"@floating-ui/dom": "^0.1.10",
"@github/clipboard-copy-element": "^1.1.2",
"@github/hotkey": "^1.6.1",
"@github/markdown-toolbar-element": "^2.1.0",
"@github/time-elements": "^3.1.2",
"@popperjs/core": "^2.11.0",
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
"@vime/core": "^5.3.0",
"choices.js": "^9.0.1",