Tooltips

Find the source code here.

Overview

Tooltip allows you to give a piece of information, mostly, in the shortest way.

This component has many props enabling you to customize the content you want to show. Here are many examples you can achieve.

Installation

Notes

To use this component, you need to initialize your project first. If not done yet, run one of the following command:

npx jsxpine init or yarn jsxpine init or pnpm jsxpine init or bunx jsxpine init.

Go to the installation and usage page to learn more.

jsxpine add tooltip
Copied !

Copied !


	--------------------     Tooltip Component   -------------------------

		import clsx from "clsx";
import { textSizeClassMap } from "../common/classes";

/**
 * @typedef {"top" | "bottom" | "left" | "right"} TooltipPositionType
 */

/**
 * @typedef TooltipProps
 * @type {{ text?: string, component?: import("@kitajs/html").Children, triggerOnHover?: boolean, position?: TooltipPositionType } & import("../common/props").HTMLTagWithChildren & import("../common/props").SizeProps & import("../common/props").ThemeColorProps}
 */

/**
 * Tooltip component props
 * @type {import("../common/props").JSXComponent<TooltipProps>}
 */
export function Tooltip(props) {
	const {
		children,
		text = "",
		component,
		position = "top",
		type = "",
		size = "sm",
		triggerOnHover = true
	} = props;

	/**
	 * @type {Map<import("../common/types").ThemeColorType, string>}
	 */
	const colorTypeClassMap = new Map([
		["primary", "bg-primary"],
		["secondary", "bg-secondary"],
		["success", "bg-success"],
		["danger", "bg-danger"],
		["info", "bg-info"],
		["warning", "bg-warning"]
	]);

	/**
	 * @type {Map<TooltipPositionType, string>}
	 */
	const positionClassMap = new Map([
		["top", "top-0 left-1/2 -translate-x-1/2 -mt-0.5 -translate-y-full"],
		["left", "top-1/2 -translate-y-1/2 -ml-0.5 left-0 -translate-x-full"],
		["bottom", "bottom-0 left-1/2 -translate-x-1/2 -mb-0.5 translate-y-full"],
		["right", "top-1/2 -translate-y-1/2 -mr-0.5 right-0 translate-x-full"]
	]);

	/**
	 * @type {Map<TooltipPositionType, string>}
	 */
	const arrowPositionClassMap = new Map([
		["top", "bottom-0 -translate-x-1/2 left-1/2 w-2.5 translate-y-full"],
		["left", "right-0 -translate-y-1/2 top-1/2 h-2.5 -mt-px translate-x-full"],
		["bottom", "top-0 -translate-x-1/2 left-1/2 w-2.5 -translate-y-full"],
		["right", "left-0 -translate-y-1/2 top-1/2 h-2.5 -mt-px -translate-x-full"]
	]);

	/**
	 * @type {Map<TooltipPositionType, string>}
	 */
	const arrowOrientationClassMap = new Map([
		["top", "origin-top-left -rotate-45"],
		["left", "origin-top-left rotate-45"],
		["bottom", "origin-bottom-left rotate-45"],
		["right", "origin-top-right -rotate-45"]
	]);

	return (
		<div x-data={`tooltip(${triggerOnHover})`} class="relative inline-flex">
			<div
				x-bind="tooltipContent"
				class={clsx(
					"absolute",
					positionClassMap.get(position),
					textSizeClassMap.get(size)
				)}
			>
				<div
					x-transition=""
					class={clsx(
						"relative px-2 py-1 p-1",
						type ? colorTypeClassMap.get(type) : "bg-background border"
					)}
				>
					{text ? (
						<p class="flex-shrink-0 block whitespace-nowrap" safe>
							{text}
						</p>
					) : (
						component
					)}
					<div
						class={clsx(
							"absolute inline-flex items-center justify-center overflow-hidden",
							arrowPositionClassMap.get(position)
						)}
					>
						<div
							class={clsx(
								"w-1.5 h-1.5 p-1",
								arrowOrientationClassMap.get(position),
								type ? colorTypeClassMap.get(type) : "bg-background border"
							)}
						></div>
					</div>
				</div>
			</div>
			<div x-ref="tooltipTrigger" class="inline-table">
				{children}
			</div>
		</div>
	);
}

	
	
	--------------------     Alpine Dependencies   -------------------------

		/**
 * @typedef {Object} TooltipDataOutput
 * @property {boolean} visible
 * @property {Function} show
 * @property {Function} hide
 * @property {Record<string, Function>} toggle
 * @property {Record<string, Function>} tooltipContent
 */

/**
 * Tooltip alpine data
 * @param {boolean} [triggerOnHover]
 * @returns {import("alpinejs").AlpineComponent<TooltipDataOutput>}
 */

export function tooltipData(triggerOnHover = true) {
  return {
		visible: false,
		init() {
			if (triggerOnHover) {
				this.$refs.tooltipTrigger.addEventListener("mouseenter", () => {
					this.visible = true;
				});
				this.$refs.tooltipTrigger.addEventListener("mouseleave", () => {
					this.visible = false;
				});
			}
		},
		show() {
			this.visible = true;
		},
		hide() {
			this.visible = false;
		},
		toggle: {
			["@mouseenter"]() {
				if (!triggerOnHover) {
					this.show();
				}
			},
			["@mouseleave"]() {
				if (!triggerOnHover) {
					this.hide();
				}
			}
		},
		tooltipContent: {
			["@click.away"]() {
        console.log("away")
				this.hide();
			},
			["x-show"]() {
				return this.visible;
			}
		}
	};
}


	

Tooltip as Text

A regular way to tooltip is just to pass to text props a string value as message.

I'm a tooltip but to left

Tooltip Left

I'm a tooltip by default to top

Hover me !

I'm a tooltip showing at bottom

Tooltip Bottom

I'm a tooltip and I'm at right

Tooltip Right

Copied !

import { Badge } from "$components/badge.component";
import { Tooltip } from "$components/tooltip.component";

export function WithTextTooltipExample() {
	return (
		<div class="grid grid-cols-2 items-center gap-4">
			<div>
				<Tooltip text="I'm a tooltip but to left" position="left" type="primary">
					<Badge text="Tooltip Left" />
				</Tooltip>
			</div>
			<div>
				<Tooltip text="I'm a tooltip by default to top" type="success">
					<Badge text="Hover me !" />
				</Tooltip>
			</div>
			<div>
				<Tooltip text="I'm a tooltip showing at bottom" position="bottom" type="info">
					<Badge text="Tooltip Bottom" />
				</Tooltip>
			</div>
			<div>
				<Tooltip text="I'm a tooltip and I'm at right" position="right" type="danger">
					<Badge text="Tooltip Right" />
				</Tooltip>
			</div>
		</div>
	);
}

Tooltip as Component

Even better, you can pass an astro component to tooltip with component props.

PS: text props has priority to component props.

I was made for TooltipWithComponentExample

Display Dummy Content !

Copied !

import { Badge } from "$components/badge.component";
import { Tooltip } from "$components/tooltip.component";

function TooltipDummyComponent() {
    return <p>I was made for TooltipWithComponentExample</p>;
}

export function WithComponentTooltipExample() {
    return (
			<Tooltip
				triggerOnHover={false}
				component={<TooltipDummyComponent />}
				position="bottom"
			>
				<Badge x-bind="toggle" text="Display Dummy Content !" />
			</Tooltip>
		);
}

Custom Tooltip Trigger

By default, tooltip message is triggered by hovering content. With triggerOnHover props, you can disable this mechanism and trigger tooltip in your own way.

Below is an example with a trigger on click. By the way, the copy button in code side is a tooltip triggering by click.

I'm a tooltip triggering by click

Copied !

import { SecondaryButton } from "$components/button.component";
import { Tooltip } from "$components/tooltip.component";

export function CustomTriggerTooltipExample() {
	return (
		<Tooltip
			text="I'm a tooltip triggering by click"
			size="md"
			triggerOnHover={false}
		>
			<SecondaryButton
				x-on:click="visible = !visible"
				text="Click Me to show Tooltip message"
				borderRadius="arc"
			/>
		</Tooltip>
	);
}
ComponentsTabs
ComponentsTrees