Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# These are supported funding model platforms

github: galangel
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: galangel
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
10 changes: 1 addition & 9 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,7 @@ const preview: Preview = {
options: {
// Sort stories with Welcome first
storySort: {
order: [
'Welcome',
'Tooltip',
'Flows',
'Keyboard Shortcuts',
'Transitions',
'Examples',
'*',
],
order: ['Welcome', 'The Tooltip', 'The Tourtip', 'The TipAdvisor', 'Tooltip', '*'],
},
},
},
Expand Down
289 changes: 148 additions & 141 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
# React Tip Magic ✨

A sophisticated, elegant, and performant tooltip library for React with an intelligent floating helper system.
A thoughtfully crafted tooltip library for React—simple to use, delightful to experience.

![npm version](https://img.shields.io/npm/v/@galangel/react-tip-magic)
![bundle size](https://img.shields.io/bundlephobia/minzip/@galangel/react-tip-magic)
![license](https://img.shields.io/npm/l/@galangel/react-tip-magic)

## Features
## Why React Tip Magic?

- 🎯 **Zero-config tooltips** - Just add `data-tip="Hello"` to any element
- 🚀 **High performance** - Single global instance, minimal re-renders
- 🎨 **Smooth transitions** - Tooltips gracefully move between elements
- 🤖 **Intelligent Helper** - Floating assistant with multiple states and actions
- 📱 **Accessible** - Full keyboard navigation and screen reader support
- 🎭 **Customizable** - Extensive theming and configuration options
- 📦 **Lightweight** - Tree-shakeable, minimal dependencies
Tooltips seem simple, but getting them right takes care. They should appear when needed, stay out of the way when not, and feel natural as users navigate your interface.

## Quick Start
React Tip Magic handles the details so you don't have to—positioning, transitions, accessibility, keyboard support—all with a clean, declarative API.

### Installation
## Quick Start

```bash
npm install @galangel/react-tip-magic
```

### Basic Setup

```tsx
import { TipMagicProvider } from '@galangel/react-tip-magic';
import '@galangel/react-tip-magic/styles.css';
Expand All @@ -39,185 +31,200 @@ function App() {
}
```

### Simple Tooltip
That's it. Now add `data-tip` to any element:

```tsx
<button data-tip="Click to save your changes">Save</button>
<button data-tip="Save your changes">Save</button>
```

### Tooltip with Keyboard Shortcut
---

```tsx
<button data-tip="Copy; ⌘+C">Copy</button>
```
## Tooltips

The core of React Tip Magic. One tooltip instance that gracefully moves between elements, providing a smooth, cohesive experience.

### Advanced Options
### Basic Usage

```tsx
<p
data-tip="This is a long description that will be truncated..."
data-tip-ellipsis
data-tip-max-lines="2"
data-tip-word-wrap
>
Hover me
</p>
<button data-tip="Click to save">Save</button>
<button data-tip="Undo last action">Undo</button>
```

### Transition Behavior
### With Keyboard Shortcuts

Control how tooltips transition when moving between elements:
Display shortcuts alongside your tooltips using the `data-tip-shortcut` attribute:

```tsx
{/* Smooth move transition (default) */}
<button data-tip="Moves smoothly" data-tip-move>Button 1</button>
<button data-tip="Moves smoothly" data-tip-move>Button 2</button>

{/* Jump transition (fade out/in) */}
<button data-tip="Jumps" data-tip-jump>Button 3</button>
<button data-tip="Copy" data-tip-shortcut="⌘C">Copy</button>
<button data-tip="Paste" data-tip-shortcut="⌘V">Paste</button>
<button data-tip="Save" data-tip-shortcut="⌘S">Save</button>
```

### Tooltip Groups

Use `data-tip-group` to control move transitions between grouped elements. Tooltips will only smoothly move between elements in the **same group**:
### Positioning & Behavior

```tsx
{/* Group A - tooltips move smoothly within this group */}
<button data-tip="Group A" data-tip-move data-tip-group="A">A1</button>
<button data-tip="Group A" data-tip-move data-tip-group="A">A2</button>

{/* Group B - tooltips move smoothly within this group */}
<button data-tip="Group B" data-tip-move data-tip-group="B">B1</button>
<button data-tip="Group B" data-tip-move data-tip-group="B">B2</button>
{
/* Position control */
}
<button data-tip="Below the button" data-tip-placement="bottom">
Hover me
</button>;

{/* Moving from Group A to Group B will jump, not move */}
{
/* Smooth transitions between grouped elements */
}
<nav>
<a data-tip="Home" data-tip-move data-tip-group="nav">
Home
</a>
<a data-tip="About" data-tip-move data-tip-group="nav">
About
</a>
<a data-tip="Contact" data-tip-move data-tip-group="nav">
Contact
</a>
</nav>;

{
/* Interactive tooltips that stay visible on hover */
}
<span data-tip="Click <a href='#'>here</a> to learn more" data-tip-html data-tip-interactive>
More info
</span>;
```

**Group transition rules:**
---

- **Same group** → Smooth move transition
- **Different groups** → Jump transition (tooltip appears at new position)
- **Grouped to ungrouped** (or vice versa) → Smooth move transition
## Guided Tours

## Helper System

The Helper is an optional floating element that provides contextual information and actions.

### Onboarding Flow Example
Walk users through your interface with step-by-step tours. Helpful for onboarding, feature introductions, or contextual guidance.

```tsx
import { useTipMagic } from '@galangel/react-tip-magic';
import { useTour } from '@galangel/react-tip-magic';

function OnboardingFlow() {
const { helper } = useTipMagic();

useEffect(() => {
helper.startFlow([
{
targetId: 'welcome-1',
message: 'Welcome! This is your dashboard.',
actions: [{ label: 'Next', action: 'next' }],
},
{
targetId: 'welcome-2',
message: 'Click here to create your first project.',
actions: [{ label: 'Got it!', action: 'complete' }],
},
]);
}, []);
function App() {
const tour = useTour({
steps: [
{ target: 'dashboard', title: 'Welcome', message: 'This is your dashboard.' },
{ target: 'create-btn', title: 'Create', message: 'Click here to get started.' },
],
});

return (
<div>
<nav data-tip-id="welcome-1">Dashboard</nav>
<button data-tip-id="welcome-2">New Project</button>
<nav data-tip-id="dashboard">Dashboard</nav>
<button data-tip-id="create-btn" onClick={tour.start}>
New Project
</button>
</div>
);
}
```

### Helper States
Tours include navigation controls, progress indicators, keyboard support, and backdrop highlighting—all configurable to fit your needs.

---

## Tip Advisor

A keyboard shortcut discovery menu. Press a key (F1 by default) to reveal all available shortcuts in your interface, with fuzzy search to quickly find what you need.

```tsx
// Show thinking state
helper.setState('thinking');

// Show working state with message
helper.show({
state: 'working',
message: 'Processing your request...',
});

// Show call to action
helper.show({
state: 'cta',
message: 'Ready to continue?',
actions: [
{ label: 'Yes', onClick: () => {} },
{ label: 'No', onClick: () => {} },
],
});
import { TipAdvisor } from '@galangel/react-tip-magic';

function App() {
return (
<TipMagicProvider>
<div className="toolbar">
<button data-tip="Copy" data-tip-shortcut="⌘C">
Copy
</button>
<button data-tip="Paste" data-tip-shortcut="⌘V">
Paste
</button>
<button data-tip="Save" data-tip-shortcut="⌘S">
Save
</button>
</div>

{/* Press F1 to open the advisor */}
<TipAdvisor />
</TipMagicProvider>
);
}
```

Features:

- Fuzzy search with highlighted matches
- Keyboard navigation (arrow keys + Enter)
- Hover to preview tooltip locations
- Click to trigger the associated element

---

## Data Attributes

| Attribute | Description | Example |
| ---------------------- | ----------------------------------- | ----------------------------- |
| `data-tip` | Tooltip content | `data-tip="Hello"` |
| `data-tip-shortcut` | Keyboard shortcut badge | `data-tip-shortcut="⌘S"` |
| `data-tip-id` | Element identifier for tours | `data-tip-id="welcome"` |
| `data-tip-placement` | Position (top, bottom, left, right) | `data-tip-placement="bottom"` |
| `data-tip-delay` | Show delay in ms | `data-tip-delay="500"` |
| `data-tip-hide-delay` | Hide delay in ms | `data-tip-hide-delay="100"` |
| `data-tip-disabled` | Disable tooltip | `data-tip-disabled` |
| `data-tip-html` | Parse content as HTML | `data-tip-html` |
| `data-tip-interactive` | Keep tooltip on hover | `data-tip-interactive` |
| `data-tip-move` | Smooth move transition | `data-tip-move` |
| `data-tip-group` | Group for transitions | `data-tip-group="nav"` |
| `data-tip-no-arrow` | Hide tooltip arrow | `data-tip-no-arrow` |

---

## Programmatic API

Use the `useTipMagic` hook for full programmatic control:
For more control, use the `useTipMagic` hook:

```tsx
import { useTipMagic } from '@galangel/react-tip-magic';

function MyComponent() {
const { tooltip, helper, config } = useTipMagic();

// Show tooltip programmatically
tooltip.show('#my-element', 'Custom content');
const { tooltip } = useTipMagic();

// Hide tooltip
tooltip.hide();
const handleClick = () => {
tooltip.show('#my-element', 'Dynamic content');
};

// Update content dynamically
tooltip.updateContent('New content');

return <div id="my-element">Hover me</div>;
return (
<button id="my-element" onClick={handleClick}>
Click me
</button>
);
}
```

## Data Attributes
---

## Built With

- **React 18+** with modern hooks
- **TypeScript** for type safety
- **Floating UI** for positioning
- **Storybook** for documentation

| Attribute | Description | Example |
| ------------------------- | ----------------------------------------- | ----------------------------- |
| `data-tip` | Tooltip content | `data-tip="Hello"` |
| `data-tip-id` | Element identifier for flows | `data-tip-id="welcome"` |
| `data-tip-placement` | Position (top, bottom, left, right, etc.) | `data-tip-placement="bottom"` |
| `data-tip-delay` | Show delay in ms | `data-tip-delay="500"` |
| `data-tip-hide-delay` | Hide delay in ms | `data-tip-hide-delay="100"` |
| `data-tip-disabled` | Disable tooltip | `data-tip-disabled` |
| `data-tip-ellipsis` | Enable text truncation | `data-tip-ellipsis` |
| `data-tip-max-lines` | Max lines before truncation | `data-tip-max-lines="2"` |
| `data-tip-word-wrap` | Enable word wrapping | `data-tip-word-wrap` |
| `data-tip-max-width` | Maximum width in pixels | `data-tip-max-width="300"` |
| `data-tip-html` | Parse content as HTML | `data-tip-html` |
| `data-tip-interactive` | Keep tooltip on hover | `data-tip-interactive` |
| `data-tip-move` | Smooth move transition | `data-tip-move` |
| `data-tip-jump` | Jump transition | `data-tip-jump` |
| `data-tip-group` | Group identifier for transitions | `data-tip-group="nav"` |
| `data-tip-no-arrow` | Hide tooltip arrow | `data-tip-no-arrow` |
| `data-tip-always-visible` | Keep element visible during tour focus | `data-tip-always-visible` |

## Documentation

- [Architecture](./docs/ARCHITECTURE.md) - Technical design and decisions
- [API Reference](./docs/API.md) - Complete API documentation
- [Roadmap](./docs/ROADMAP.md) - Planned features and milestones

## Tech Stack

- **React 18+** - Modern React with hooks
- **TypeScript** - Full type safety
- **Floating UI** - Robust positioning engine
- **Vite** - Fast development and building
- **Vitest** - Unit and integration testing
- **Storybook** - Component documentation and showcase
---

## License

Apache-2.0

---

<p align="center">
Made with care for the React community
</p>

<p align="center">
<a href="https://www.buymeacoffee.com/galangel"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="50" /></a>
</p>
Loading
Loading