mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-25 20:46:48 +00:00
It's not great to have Stimulus controller rendering markup on `connect` Stimulus is intended to add behavior to existing markup. Plus add some documentation
72 lines
2.0 KiB
JavaScript
72 lines
2.0 KiB
JavaScript
import { Controller } from "stimulus";
|
|
import { computePosition, offset, arrow } from "@floating-ui/dom";
|
|
|
|
// This is meant to be used with the follwing html where element can be a
|
|
// "div", "a", "span" or "button", etc... :
|
|
//
|
|
// <div data-controller="tooltip">
|
|
// <element data-tooltip-target="element">
|
|
// <div class="tooltip-container">
|
|
// <div class="tooltip" data-tooltip-target="tooltip">
|
|
// tooltip_text
|
|
// <div class=arrow data-tooltip-target="arrow"></div>
|
|
// </div>
|
|
// </div>
|
|
// </div>
|
|
//
|
|
// You can also use this partial app/views/admin/shared/_tooltip.html.haml
|
|
|
|
export default class extends Controller {
|
|
static targets = ["element", "tooltip", "arrow"];
|
|
static values = {
|
|
placement: { type: String, default: "top" },
|
|
};
|
|
|
|
connect() {
|
|
this.elementTarget.addEventListener("mouseenter", this.showTooltip);
|
|
this.elementTarget.addEventListener("mouseleave", this.hideTooltip);
|
|
}
|
|
|
|
disconnect() {
|
|
this.elementTarget.removeEventListener("mouseenter", this.showTooltip);
|
|
this.elementTarget.removeEventListener("mouseleave", this.hideTooltip);
|
|
}
|
|
|
|
update() {
|
|
computePosition(this.elementTarget, this.tooltipTarget, {
|
|
placement: this.placementValue,
|
|
middleware: [offset(6), arrow({ element: this.arrowTarget })],
|
|
}).then(({ x, y, placement, middlewareData }) => {
|
|
Object.assign(this.tooltipTarget.style, {
|
|
left: `${x}px`,
|
|
top: `${y}px`,
|
|
});
|
|
const { x: arrowX, y: arrowY } = middlewareData.arrow;
|
|
|
|
const staticSide = {
|
|
top: "bottom",
|
|
right: "left",
|
|
bottom: "top",
|
|
left: "right",
|
|
}[placement.split("-")[0]];
|
|
|
|
Object.assign(this.arrowTarget.style, {
|
|
left: arrowX != null ? `${arrowX}px` : "",
|
|
top: arrowY != null ? `${arrowY}px` : "",
|
|
right: "",
|
|
bottom: "",
|
|
[staticSide]: "-4px",
|
|
});
|
|
});
|
|
}
|
|
|
|
showTooltip = () => {
|
|
this.tooltipTarget.style.display = "block";
|
|
this.update();
|
|
};
|
|
|
|
hideTooltip = () => {
|
|
this.tooltipTarget.style.display = "";
|
|
};
|
|
}
|