react-floater
Version:
Floaters everywhere!
231 lines (186 loc) • 10.5 kB
Markdown
# React Floater
[](https://www.npmjs.com/package/react-floater) [](https://github.com/gilbarbara/react-floater/actions/workflows/ci.yml) [](https://sonarcloud.io/summary/new_code?id=gilbarbara_react-floater) [](https://sonarcloud.io/summary/new_code?id=gilbarbara_react-floater)
**Flexible, customizable, and accessible tooltips, popovers, and guided hints for React.**
> **Maintenance Mode:** This library is built on Popper.js v2, which is no longer actively maintained.
> For new projects, we recommend using [Floating UI](https://floating-ui.com/) directly.
[**View the live demo →**](https://codesandbox.io/s/github/gilbarbara/react-floater/tree/main/demo)
## Highlights
- 🏖 **Easy to use:** Just set the `content`
- 🛠 **Flexible:** Personalize the options to fit your needs
- 🟦 **Type-safe:** Full TypeScript support
## Usage
```shell
npm install react-floater
```
Import it into your app:
```tsx
import Floater from 'react-floater';
<Floater content="This is the Floater content">
<span>click me</span>
</Floater>;
```
Voilà! A tooltip will appear on click!
## Customization & Styling
React Floater is highly customizable. You can:
- Use a custom component for the content via the `component` prop
(see `WithStyledComponents.ts` in the [demo](https://codesandbox.io/s/github/gilbarbara/react-floater/tree/main/demo)).
- Pass a custom arrow using the `arrow` prop.
- Customize the UI appearance using the `styles` prop.
You only need to provide the keys you want to override—defaults will be merged automatically.
```tsx
<Floater
content={<div>Custom content <b>with bold!</b></div>}
placement="right"
arrow={<MyCustomArrow />}
styles={{
container: { backgroundColor: "#222", color: "#fff" },
arrow: { color: "#222", size: 16, base: 24 },
}}
>
<button>Hover or click me</button>
</Floater>
```
For all available style keys and their default values, see the [styles.ts](src/modules/styles.ts) source.
## Props
| **Prop** | **Type** | **Default** | **Description** |
|---------------------|------------------------------------------------------------------|-------------|---------------------------------------------------------------------------|
| arrow ✨ | ReactNode | – | Custom arrow for the floater. [See styles.arrow](#styles-type-definition) |
| autoOpen | boolean | false | Open the Floater automatically. |
| callback | (action: ‘open’ \| ‘close’, props: Props) => void | – | Called when the Floater opens or closes. |
| children | ReactNode | – | Element to trigger the Floater. |
| component | ComponentType \| ReactElement | – | Custom component UI for the Floater. Has access to closeFn. |
| content | ReactNode | – | The content of the Floater. (Required unless you pass a component.) |
| debug | boolean | false | Log basic actions. |
| disableFlip | boolean | false | Disable changes in position on scroll/resize. |
| disableHoverToClick | boolean | false | Don’t convert hover to click on mobile. |
| event | 'hover' \| 'click' | 'click' | Event that triggers the Floater.*Not used in controlled mode.* |
| eventDelay | number | 0.4 | Time in seconds before hiding on mouseLeave (only for hover). |
| footer | ReactNode | – | Footer area content. |
| getPopper | (popper: PopperInstance, origin: ‘floater’ \| ‘wrapper’) => void | – | Get the popper.js instance. |
| hideArrow | boolean | false | Hide the arrow (good for centered/modal). |
| offset | number | 15 | Distance (px) between Floater and target. |
| open | boolean | – | Switch to controlled mode. Disables normal event triggers. |
| modifiers | [PopperModifiers](#poppermodifiers-type-definition) | – | Customize popper.js modifiers. |
| placement | [Placement](#placement-type-definition) | 'bottom' | Floater’s position. |
| portalElement | string \| HTMLElement | – | Selector or element for rendering. |
| showCloseButton | boolean | false | Shows a close (×) button. |
| styles | [Styles](#styles-type-definition) | – | Customize UI styles. |
| target | string \| HTMLElement | – | Target element for position. Defaults to children. |
| title | ReactNode | – | Floater title. |
| wrapperOptions | [WrapperOptions](#wrapperoptions-type-definition) | – | Options for positioning the wrapper. Requires a target. |
<details>
<summary><b id="poppermodifiers-type-definition">PopperModifiers Type Definition</b></summary>
```typescript
interface PopperModifiers {
applyStyles?: Partial<ApplyStylesModifier>;
arrow?: Partial<ArrowModifier>;
computeStyles?: Partial<ComputeStylesModifier>;
eventListeners?: Partial<EventListenersModifier>;
flip?: Partial<FlipModifier>;
hide?: Partial<HideModifier>;
offset?: Partial<OffsetModifier>;
popperOffsets?: Partial<PopperOffsetsModifier>;
preventOverflow?: Partial<PreventOverflowModifier>;
}
```
</details>
> **Intended for advanced customization—use with caution.**
<details>
<summary><b id="placement-type-definition">Placement Type Definition</b></summary>
```typescript
type Placement =
| "auto" | "auto-start" | "auto-end"
| "top" | "top-start" | "top-end"
| "bottom" | "bottom-start" | "bottom-end"
| "right"| "right-start" | "right-end"
| "left" | "left-start" | "left-end"
| "center"
```
</details>
<details>
<summary><b id="styles-type-definition">Styles Type Definition</b></summary>
```typescript
interface Styles {
arrow: CSSProperties & {
size: number;
base: number;
};
close: CSSProperties;
container: CSSProperties;
content: CSSProperties;
floater: CSSProperties;
floaterCentered: CSSProperties;
floaterClosing: CSSProperties;
floaterOpening: CSSProperties;
floaterWithAnimation: CSSProperties;
floaterWithComponent: CSSProperties;
footer: CSSProperties;
options: {
zIndex: number;
};
title: CSSProperties;
wrapper: CSSProperties;
wrapperPosition: CSSProperties;
}
```
</details>
<details>
<summary><b id="wrapperoptions-type-definition">WrapperOptions Type Definition</b></summary>
```typescript
interface WrapperOptions {
offset: number; // The distance between the wrapper and the target. It can be a negative value.
placement: string; // the same options as above, except center
position: boolean; // Set to true to position the wrapper
}
```
</details>
## Modes
React Floater supports several modes for flexible positioning and control:
**Default**
The Floater is anchored to its child and triggers on event.
```tsx
<Floater content="This is the Floater content">
<span>click me</span>
</Floater>
```
**Proxy**
The Floater is triggered by the child, but positioned relative to the `target`.
```tsx
<div className="App">
<img src="some-path" />
<Floater content="This is the Floater content" target=".App img">
<span>click me</span>
</Floater>
</div>
```
**Beacon**
The Floater wrapper is positioned relative to the target (useful for guided tours or beacons).
```tsx
<div className="App">
<img
src="https://upload.wikimedia.org/wikipedia/commons/2/2d/Google-favicon-2015.png"
width="100"
className="my-super-image"
/>
<Floater
content="This is the Floater content"
target=".my-super-image"
wrapperOptions={{
offset: -22,
placement: 'top',
position: true,
}}
>
<span style={{ color: '#f04', fontSize: 34 }}>◉</span>
</Floater>
</div>
```
**Controlled**
You manage the Floater’s visibility with the `open` prop - no trigger events are needed.
In this mode, you don't even need to have `children`
```tsx
<div className="App">
<img src="some-path" />
<Floater content="This is the Floater content" open={true} target=".App img" />
</div>
```