# 💬 react-tooltip-z

[![NPM](https://img.shields.io/npm/v/react-tooltip-z.svg)](https://www.npmjs.com/package/react-tooltip-z) ![Downloads](https://img.shields.io/npm/dt/react-tooltip-z.svg)


<a href="https://codesandbox.io/p/sandbox/v5mmhv" target="_blank">LIVE EXAMPLE</a>

---

Lightweight, smart auto-positioned tooltip for React 18+.  
Zero dependencies. Portal-based. Fully controllable.

> 🚀 Smart auto-positioning engine.
>
> The tooltip dynamically calculates its position (`top`, `right`, `bottom`, `left`)
> and automatically adjusts when it would overflow the screen — ensuring it always remains visible inside the viewport.

---

## Why react-tooltip-z?

-   🧩 Simple wrapper API
-   🪟 Rendered via React Portal (outside root)
-   🎯 Supports `hover`, `click`, `manual`
-   🎨 Fully customizable content (text / jsx / component)
-   ⚡ ForwardRef control (`show`, `hide`)
-   📦 Lightweight & dependency-free
-   📱 Smart auto-position (viewport aware)

Designed for flexible UI overlays and explicit control flows.

---

## Installation

``` bash
npm install react-tooltip-z
```

---

## Basic Usage

``` tsx
import React from "react";
import { Tooltip } from "react-tooltip-z";

export function Example() {
  return (
    <Tooltip
      content={<b>This is JSX<br />Tooltip</b>}
      placement="right"
    >
      <button>Hover me</button>
    </Tooltip>
  );
}
```

---

## Manual Control (ForwardRef)

``` tsx
import React, { useRef } from "react";
import { Tooltip } from "react-tooltip-z";

export function Example() {
  const tooltipRef = useRef(null);

  return (
    <>
      <button
        onClick={() => {
          tooltipRef.current?.show("Dynamic content");
        }}
      >
        Show Tooltip
      </button>

      <button
        onClick={() => {
          tooltipRef.current?.hide();
        }}
      >
        Show Tooltip
      </button>

      <Tooltip
        ref={tooltipRef}
        trigger="manual"
        placement="top"
      >
        <span>Target Element</span>
      </Tooltip>
    </>
  );
}
```

---

## Controlled Mode (`open` + `onOpenChange`)

```tsx
export function ControlledExample() {
  const [open, setOpen] = React.useState(false);

  return (
    <>
      <button onClick={() => setOpen(prev => !prev)}>
        Toggle
      </button>

      <Tooltip
        content="Controlled tooltip"
        open={open}
        onOpenChange={setOpen}
      >
        <span>Target</span>
      </Tooltip>
    </>
  );
}

```

---

## Global Control (Provider API)

```tsx
import { TooltipProvider, useTooltip } from "react-tooltip-z";
<TooltipProvider>
  <App />
</TooltipProvider>
```


```tsx
const { show, hide } = useTooltip();
```

---

## ForwardRef API

``` ts
tooltipRef.current?.show(content?);
tooltipRef.current?.hide();
```

---

## Props

| Prop               | Type                                     | Default   | Description                     |
| ------------------ | ---------------------------------------- | --------- | ------------------------------- |
| `children`         | `ReactNode`                              | —         | Target element                  |
| `content`          | `string \| ReactNode`                    | —         | Tooltip content                 |
| `placement`        | `"top" \| "right" \| "bottom" \| "left"` | `"top"`   | Tooltip position                |
| `trigger`          | `"hover" \| "click" \| "manual"`         | `"hover"` | Trigger behavior                |
| `tooltipClassName` | `string`                                 | —         | Custom tooltip class            |
| `backgroundColor`  | `string`                                 | `#282727` | Tooltip background color        |
| `textColor`        | `string`                                 | `#ffffff` | Tooltip text color              |
| `constrainWidth`   | `boolean`                                | `true`    | Limit max width (220px) to prevent overflow        |
| `animation`        | `"fade" \| "zoom"`                       | `"fade"`  | Tooltip animation               |
| `delay`            | `number`                                 | `250`     | Delay before show (ms)          |
| `arrowCentered`    | `boolean`                                | `false`   | Center arrow to element         |
| `open`             | `boolean`                                | —         | Controlled visibility           |
| `closeOnResize`    | `boolean`                                | `true`    | Hide on window resize           |
| `closeOnScroll`    | `boolean`                                | `false`   | Hide on scroll                  |
| `onOpenChange`     | `(boolean) => void`                      | —         | Callback after show/hide        |
| `tagName`          | `string`                                 | `"span"`  | Wrap children with custom tag   |
| `...rest`          | `any`                                    | —         | orwarded to wrapped child element |

---

## Behavior Notes

-   Tooltip auto-adjusts if it goes outside viewport.
-   `trigger="manual"` requires ref methods (`show`, `hide`) or `open` prop.
-   Extra props are forwarded to the wrapped child element.

---

## Comparison

| Criteria             | react-tooltip-z | Browser `title`  | Generic Tooltip Library  |
|----------------------|-----------------|------------------|--------------------------|
| Portal rendering     | ✅              | ❌               | ✅                        |
| Smart auto-position  | ✅              | ❌               | ⚠️ Partial                |
| ForwardRef API       | ✅              | ❌               | ❌                        |
| Controlled mode      | ✅              | ❌               | ⚠️ Optional               |
| Zero dependencies    | ✅              | ⚪ Built-in      | ❌                        |
| Custom JSX content   | ✅              | ❌               | ⚠️ Partial                |


---

## License

MIT
