{"id":27320241,"url":"https://github.com/rezasohrabi/headless-tooltip","last_synced_at":"2026-03-06T06:02:35.482Z","repository":{"id":283684894,"uuid":"952587716","full_name":"rezasohrabi/headless-tooltip","owner":"rezasohrabi","description":"Headless UI Component for building powerful React Tooltips!","archived":false,"fork":false,"pushed_at":"2025-12-26T17:35:04.000Z","size":5553,"stargazers_count":10,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-28T03:28:04.968Z","etag":null,"topics":["headless-tooltip","headless-ui","headlessui","headlessui-react","js-tooltip","react-tooltip","reactjs","tailwind","tailwind-css","tooltip","tooltip-component","tooltip-library"],"latest_commit_sha":null,"homepage":"https://rezasohrabi.github.io/headless-tooltip/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rezasohrabi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-21T14:29:51.000Z","updated_at":"2025-12-26T17:33:29.000Z","dependencies_parsed_at":"2025-03-21T15:32:21.003Z","dependency_job_id":"83d23fc7-c332-419f-8570-37ee71ba8be2","html_url":"https://github.com/rezasohrabi/headless-tooltip","commit_stats":null,"previous_names":["rezasohrabi/headlessui-tooltip","rezasohrabi/headless-tooltip"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/rezasohrabi/headless-tooltip","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rezasohrabi%2Fheadless-tooltip","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rezasohrabi%2Fheadless-tooltip/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rezasohrabi%2Fheadless-tooltip/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rezasohrabi%2Fheadless-tooltip/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rezasohrabi","download_url":"https://codeload.github.com/rezasohrabi/headless-tooltip/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rezasohrabi%2Fheadless-tooltip/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30164532,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T04:43:31.446Z","status":"ssl_error","status_checked_at":"2026-03-06T04:40:30.133Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["headless-tooltip","headless-ui","headlessui","headlessui-react","js-tooltip","react-tooltip","reactjs","tailwind","tailwind-css","tooltip","tooltip-component","tooltip-library"],"created_at":"2025-04-12T09:14:58.111Z","updated_at":"2026-03-06T06:02:35.460Z","avatar_url":"https://github.com/rezasohrabi.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# headless-tooltip\n\n[![npm version](https://img.shields.io/npm/v/headless-tooltip.svg)](https://www.npmjs.com/package/headless-tooltip) [![npm downloads](https://img.shields.io/npm/dm/headless-tooltip.svg)](https://www.npmjs.com/package/headless-tooltip) [![bundle size](https://img.shields.io/bundlephobia/minzip/headless-tooltip) ![minified](https://badgen.net/bundlephobia/min/headless-tooltip)](https://bundlephobia.com/package/headless-tooltip) [![license](https://img.shields.io/github/license/rezasohrabi/headless-tooltip)](LICENSE) [![TypeScript](https://img.shields.io/badge/TypeScript-4.0%2B-blue)](https://www.typescriptlang.org/) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/your-username/headless-tooltip/pulls)\n\nA lightweight, customizable tooltip component for React with zero styling opinions. Built with accessibility in mind.\n\nPerfect for modern web applications. Works seamlessly with React 17, 18, and 19. Built with TypeScript and accessibility in mind.\n\n[🎮 Live Demo](https://rezasohrabi.github.io/headless-tooltip/) | [📦 NPM Package](https://www.npmjs.com/package/headless-tooltip)\n\nIf you find **Headless-Tooltip** useful, please consider giving it a ⭐\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n- [API Reference](#api-reference)\n- [Accessibility](#accessibility)\n- [Advanced Usage](#advanced-usage)\n- [Animation Example](#animation-example)\n- [Contributing](#contributing)\n\n## Features\n\n- 🎨 **Truly headless**: No predefined styles, full control over tooltip appearance\n- ♿ **Accessible**: Follows [WAI-ARIA Tooltip Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/)\n- 🧩 **Flexible**: Supports custom content, including HTML and React components\n- 📱 **Responsive**: Automatically adapts to different screen sizes\n- 🔄 **Interactive mode**: Optional interactive tooltips that remain visible when hovering\n- 🏹 **Customizable arrow**: Optional arrow that can be styled and positioned\n- 🌐 **Placement options**: 12 different placement positions for tooltip\n- ⌨️ **Keyboard friendly**: Fully keyboard accessible with proper focus management\n- ✨ **Animation ready**: Built-in support for CSS transitions and animations\n- 🎭 **State-based styling**: CSS data attributes for different tooltip states\n\n## Installation\n\n### npm\n\n```bash\nnpm install headless-tooltip\n```\n\n### yarn\n\n```bash\nyarn add headless-tooltip\n```\n\n### pnpm\n\n```bash\npnpm add headless-tooltip\n```\n\n## Basic Usage\n\n```jsx\nimport { Tooltip } from 'headless-tooltip';\n\nfunction Example() {\n  return (\n    \u003cTooltip content=\"This is a tooltip message\"\u003e\n      \u003cbutton\u003eHover me\u003c/button\u003e\n    \u003c/Tooltip\u003e\n  );\n}\n```\n\n## Styled Example\n\n```jsx\nimport { Tooltip } from 'headless-tooltip';\n\nfunction StyledExample() {\n  return (\n    \u003cTooltip\n      content={\u003cspan\u003eThis is a tooltip message\u003c/span\u003e}\n      placement=\"bottom\"\n      arrow={true}\n      className=\"max-w-80 rounded-lg bg-gray-900 px-3 py-2 text-xs font-normal text-white\"\n      arrowClassName=\"bg-gray-900\"\n    \u003e\n      \u003cbutton className=\"px-4 py-2 bg-blue-500 text-white rounded\"\u003e\n        Hover me\n      \u003c/button\u003e\n    \u003c/Tooltip\u003e\n  );\n}\n```\n\n## API Reference\n\n### Props\n\n| Prop                       | Type                      | Default         | Description                                                  |\n| -------------------------- | ------------------------- | --------------- | ------------------------------------------------------------ |\n| `children`                 | `React.ReactNode`         | (required)      | The element that triggers the tooltip                        |\n| `content`                  | `React.ReactNode`         | (required)      | The content to be displayed in the tooltip                   |\n| `placement`                | `Placement`               | `'top'`         | Tooltip placement relative to the trigger element            |\n| `className`                | `string`                  | `''`            | Additional CSS classes to apply to the tooltip               |\n| `offset`                   | `number`                  | `4`             | Distance between tooltip and trigger element in pixels       |\n| `zIndex`                   | `number`                  | `undefined`     | Z-index value for the tooltip                                |\n| `open`                     | `boolean`                 | `undefined`     | Control tooltip visibility (makes it a controlled component) |\n| `openDelay`                | `number`                  | `300`           | Delay in ms before showing the tooltip                       |\n| `closeDelay`               | `number`                  | `200`           | Delay in ms before hiding the tooltip                        |\n| `disableInteractive`       | `boolean`                 | `false`         | If true, tooltip will close when mouse leaves trigger        |\n| `onOpenChange`             | `(open: boolean) =\u003e void` | `undefined`     | Callback when tooltip visibility changes                     |\n| `portalContainer`          | `HTMLElement`             | `document.body` | DOM element where tooltip portal will be rendered            |\n| `arrow`                    | `boolean`                 | `false`         | Whether to show an arrow pointing to the trigger             |\n| `arrowSize`                | `number`                  | `12`            | Size of the arrow in pixels                                  |\n| `arrowClassName`           | `string`                  | `undefined`     | Additional CSS classes to apply to the arrow                 |\n| `transition`               | `object`                  | `undefined`     | Configuration for tooltip enter/exit animations              |\n| `transition.enable`        | `boolean`                 | `false`         | Whether to enable transition animations                      |\n| `transition.enterDuration` | `number`                  | `300`           | Duration of the enter animation in milliseconds              |\n| `transition.exitDuration`  | `number`                  | `300`           | Duration of the exit animation in milliseconds               |\n\n### Placement Types\n\nThe `placement` prop accepts the following values:\n\n- `'top'`\n- `'right'`\n- `'bottom'`\n- `'left'`\n- `'top-start'`\n- `'top-end'`\n- `'right-start'`\n- `'right-end'`\n- `'bottom-start'`\n- `'bottom-end'`\n- `'left-start'`\n- `'left-end'`\n\n## Accessibility\n\nThis tooltip implementation follows the [WAI-ARIA Tooltip Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/) to ensure accessibility compliance:\n\n- Uses appropriate ARIA attributes (`role=\"tooltip\"`, `aria-describedby`)\n- Supports keyboard navigation with proper focus management\n- Dismissible with Escape key\n- Works with screen readers\n- Triggered by both hover and focus events\n\n## Browser Support\n\nThe component is compatible with all modern browsers:\n\n- Chrome (and Chromium-based browsers)\n- Firefox\n- Safari\n- Edge\n\n## Advanced Usage\n\n### Controlled Mode\n\n```jsx\nimport { useState } from 'react';\nimport { Tooltip } from 'headless-tooltip';\n\nfunction ControlledExample() {\n  const [isOpen, setIsOpen] = useState(false);\n\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={() =\u003e setIsOpen(!isOpen)}\u003eToggle Tooltip\u003c/button\u003e\n\n      \u003cTooltip\n        content=\"This is a controlled tooltip\"\n        open={isOpen}\n        onOpenChange={setIsOpen}\n      \u003e\n        \u003cbutton\u003eHover me too\u003c/button\u003e\n      \u003c/Tooltip\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n### Interactive Tooltip\n\n```jsx\nimport { Tooltip } from 'headless-tooltip';\n\nfunction InteractiveExample() {\n  return (\n    \u003cTooltip\n      content={\n        \u003cdiv\u003e\n          \u003cp\u003eInteractive tooltip with a button:\u003c/p\u003e\n          \u003cbutton onClick={() =\u003e alert('Clicked!')}\u003eClick me\u003c/button\u003e\n        \u003c/div\u003e\n      }\n      disableInteractive={false}\n    \u003e\n      \u003cbutton\u003eHover for interactive tooltip\u003c/button\u003e\n    \u003c/Tooltip\u003e\n  );\n}\n```\n\n### Animation Example\n\n```jsx\nimport { Tooltip } from 'headless-tooltip';\nimport './animations.css';\n\nfunction ZoomTooltip() {\n  return (\n    \u003cTooltip\n      content=\"This tooltip zooms in and out!\"\n      className=\"tooltip-base zoom-in-out\"\n      transition={{\n        enable: true,\n        enterDuration: 400,\n        exitDuration: 400,\n      }}\n    \u003e\n      \u003cbutton\u003eHover for zoom animation\u003c/button\u003e\n    \u003c/Tooltip\u003e\n  );\n}\n```\n\n```css\n/* animations.css */\n.tooltip-base {\n  background: #333;\n  color: white;\n  padding: 8px 12px;\n  border-radius: 6px;\n  font-size: 14px;\n}\n\n/* Zoom In/Out Animation */\n.zoom-in-out[data-enter] {\n  opacity: 0;\n}\n\n.zoom-in-out[data-entering] {\n  opacity: 1;\n  animation: zoomIn 400ms ease-out;\n}\n\n.zoom-in-out[data-exiting] {\n  animation: zoomOut 400ms ease-in;\n}\n\n/* Keyframe Animations */\n@keyframes zoomIn {\n  0% {\n    opacity: 0;\n    transform: scale(0.3);\n  }\n  50% {\n    opacity: 1;\n  }\n  100% {\n    opacity: 1;\n    transform: scale(1);\n  }\n}\n\n@keyframes zoomOut {\n  0% {\n    opacity: 1;\n    transform: scale(1);\n  }\n  50% {\n    opacity: 1;\n    transform: scale(0.3);\n  }\n  100% {\n    opacity: 0;\n    transform: scale(0.3);\n  }\n}\n```\n\n## Contributing\n\nContributions are always welcome! Please feel free to submit a Pull Request.\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frezasohrabi%2Fheadless-tooltip","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frezasohrabi%2Fheadless-tooltip","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frezasohrabi%2Fheadless-tooltip/lists"}