diff --git a/core/static/bundled/core/tooltips-index.ts b/core/static/bundled/core/tooltips-index.ts index 47df492d..f9721ca4 100644 --- a/core/static/bundled/core/tooltips-index.ts +++ b/core/static/bundled/core/tooltips-index.ts @@ -1,12 +1,22 @@ -import { type Placement, computePosition, offset } from "@floating-ui/dom"; +import { + type Placement, + autoPlacement, + computePosition, + flip, + offset, + size, +} from "@floating-ui/dom"; /** * Library usage: * * Add a `tooltip` attribute to any html element with it's tooltip text * You can control the position of the tooltp with the `tooltip-position` attribute - * Allowed placements are `top`, `right`, `bottom`, `left` - * You can add `-start` and `-end` to all allowed placement values + * Allowed placements are `auto`, `top`, `right`, `bottom`, `left` + * You can add `-start` and `-end` to all allowed placement values except for `auto` + * Default placement is `auto` + * Note: placement are suggestions and the position could change if the popup gets + * outside of the screen. * * You can customize your tooltip by passing additionnal classes or ids to it * You can use `tooltip-class` and `tooltip-id` to add additional elements to the @@ -24,12 +34,30 @@ type Status = "open" | "close"; const tooltips = new Map(); -function getPlacement(element: HTMLElement): Placement { +function getPosition(element: HTMLElement): Placement | "auto" { const position = element.getAttribute("tooltip-position"); if (position) { - return position as Placement; + return position as Placement | "auto"; } - return "bottom"; + return "auto"; +} + +function getMiddleware(element: HTMLElement) { + const middleware = [offset(6), size()]; + if (getPosition(element) === "auto") { + middleware.push(autoPlacement()); + } else { + middleware.push(flip()); + } + return { middleware: middleware }; +} + +function getPlacement(element: HTMLElement) { + const position = getPosition(element); + if (position !== "auto") { + return { placement: position }; + } + return {}; } function createTooltip(element: HTMLElement) { @@ -48,9 +76,9 @@ function updateTooltip(element: HTMLElement, tooltip: HTMLElement, status: Statu { src: "tooltip-class", dst: "class", default: ["tooltip"] }, { src: "tooltip-id", dst: "id", default: [] }, ]) { - let populated = attributes.default; + const populated = attributes.default; if (element.hasAttribute(attributes.src)) { - populated = populated.concat(element.getAttribute(attributes.src).split(" ")); + populated.push(...element.getAttribute(attributes.src).split(" ")); } tooltip.setAttribute(attributes.dst, populated.join(" ")); } @@ -75,8 +103,8 @@ addEventListener("mouseover", (event: MouseEvent) => { updateTooltip(target, tooltip, "open"); computePosition(target, tooltip, { - placement: getPlacement(target), - middleware: [offset(6)], + ...getPlacement(target), + ...getMiddleware(target), }).then(({ x, y }) => { Object.assign(tooltip.style, { left: `${x}px`, diff --git a/core/static/core/tooltips.scss b/core/static/core/tooltips.scss index 57bcb7a3..3efce0ce 100644 --- a/core/static/core/tooltips.scss +++ b/core/static/core/tooltips.scss @@ -13,8 +13,8 @@ white-space: nowrap; opacity: 0; transition: opacity 500ms ease-out; - position: absolute; - width: max-content; + + white-space: normal; left: 0; top: 0;