npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@atom_design/tooltip

v1.0.0

Published

A customizable React Native tooltip component with smart positioning, animations, and rich content support.

Readme

@atom_design/tooltip

A highly customizable, accessible React Native Tooltip component with smart positioning, smooth animations, and support for rich content.

Features

  • 📍 4 Positions: top, bottom, left, right
  • 🎯 Smart Positioning: Auto-adjusts to stay within screen bounds
  • 🎬 Smooth Animations: Fade in/out with customizable duration
  • 📝 Rich Content: String, title+text, or custom components
  • 🎨 Fully Customizable: Colors, sizes, styles
  • Accessible: Full accessibility support
  • 🎯 TypeScript: Full TypeScript definitions included
  • 📱 Cross-Platform: Works on iOS and Android

Installation

npm install @atom_design/tooltip
# or
yarn add @atom_design/tooltip

Peer Dependencies

npm install react react-native prop-types

Usage

Basic Usage

import Tooltip from '@atom_design/tooltip';
import { Text } from 'react-native';

<Tooltip content="Hello, I am a tooltip!">
  <Text>ℹ️ Tap me</Text>
</Tooltip>

Positions

<Tooltip content="Top tooltip" position="top">
  <Text>Top</Text>
</Tooltip>

<Tooltip content="Bottom tooltip" position="bottom">
  <Text>Bottom</Text>
</Tooltip>

<Tooltip content="Left tooltip" position="left">
  <Text>Left</Text>
</Tooltip>

<Tooltip content="Right tooltip" position="right">
  <Text>Right</Text>
</Tooltip>

Rich Content (Title + Text)

<Tooltip
  content={{
    title: 'Popover Title',
    text: 'This is the detailed description that appears below the title.',
  }}
  position="bottom"
>
  <Text>ℹ️</Text>
</Tooltip>

Custom Component Content

<Tooltip
  content={{
    title: 'Actions',
    component: (
      <View style={{ flexDirection: 'row', gap: 10, marginTop: 10 }}>
        <Button title="Edit" onPress={() => {}} />
        <Button title="Delete" onPress={() => {}} />
      </View>
    ),
  }}
>
  <Text>⋮</Text>
</Tooltip>

Custom Colors

// Dark tooltip
<Tooltip
  content="Dark themed tooltip"
  backgroundColor="#333"
  textColor="#fff"
>
  <Text>Dark</Text>
</Tooltip>

// Brand colored
<Tooltip
  content="Brand tooltip"
  backgroundColor="#d9232d"
  textColor="#fff"
>
  <Text>Brand</Text>
</Tooltip>

Custom Styling

<Tooltip
  content="Styled tooltip"
  tooltipStyle={{
    borderRadius: 12,
    padding: 16,
    borderWidth: 1,
    borderColor: '#ddd',
  }}
  textStyle={{
    fontSize: 16,
    fontWeight: '500',
  }}
>
  <Text>Styled</Text>
</Tooltip>

Without Arrow

<Tooltip content="No arrow" showArrow={false}>
  <Text>No Arrow</Text>
</Tooltip>

With Overlay

<Tooltip
  content="Dimmed background"
  overlayColor="rgba(0,0,0,0.3)"
>
  <Text>With Overlay</Text>
</Tooltip>

Callbacks

<Tooltip
  content="Tracked tooltip"
  onShow={() => console.log('Tooltip shown')}
  onHide={() => console.log('Tooltip hidden')}
>
  <Text>Tracked</Text>
</Tooltip>

Disabled State

<Tooltip content="Won't show" disabled={true}>
  <Text>Disabled</Text>
</Tooltip>

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | children | ReactNode | - | Trigger element (required) | | content | string \| TooltipContent \| ReactNode | - | Tooltip content | | position | 'top' \| 'bottom' \| 'left' \| 'right' | 'top' | Tooltip position | | backgroundColor | string | '#fff' | Background color | | textColor | string | '#333' | Text color | | arrowSize | number | 6 | Arrow size in pixels | | maxWidth | number | 250 | Maximum tooltip width | | disabled | boolean | false | Disable tooltip | | showArrow | boolean | true | Show/hide arrow | | animationDuration | number | 200 | Animation duration (ms) | | onShow | () => void | - | Callback when shown | | onHide | () => void | - | Callback when hidden | | containerStyle | StyleProp<ViewStyle> | - | Container style | | tooltipStyle | StyleProp<ViewStyle> | - | Tooltip box style | | textStyle | StyleProp<TextStyle> | - | Text style | | titleStyle | StyleProp<TextStyle> | - | Title style | | overlayColor | string | 'transparent' | Overlay background | | closeOnOverlayPress | boolean | true | Close on overlay tap | | testID | string | - | Test ID | | accessibilityLabel | string | - | A11y label |

TooltipContent Interface

interface TooltipContent {
  title?: string;      // Bold title text
  text?: string;       // Body text
  component?: ReactNode; // Custom component
}

Accessibility

The Tooltip component is fully accessible:

  • Uses accessibilityRole="button" for trigger
  • Uses accessibilityRole="tooltip" for content
  • Announces expanded state
  • Provides interaction hints
  • Uses accessibilityLiveRegion="polite" for content

Full Test Screen Example

Copy this complete screen to test all tooltip variations in your app:

import React, { useState } from 'react';
import { ScrollView, View, Text, StyleSheet, Button } from 'react-native';
import Tooltip from '@atom_design/tooltip';

const TooltipTestScreen = () => {
  const [showCount, setShowCount] = useState(0);

  return (
    <ScrollView style={styles.container} contentContainerStyle={styles.content}>
      <Text style={styles.title}>@atom_design/tooltip</Text>
      <Text style={styles.subtitle}>Complete Component Test</Text>

      {/* POSITIONS SECTION */}
      <Text style={styles.sectionTitle}>Positions</Text>
      <View style={styles.positionsGrid}>
        <View style={styles.positionRow}>
          <Tooltip content="Tooltip on Top" position="top">
            <View style={styles.trigger}>
              <Text style={styles.triggerText}>Top</Text>
            </View>
          </Tooltip>
        </View>

        <View style={styles.positionRow}>
          <Tooltip content="Tooltip on Left" position="left">
            <View style={styles.trigger}>
              <Text style={styles.triggerText}>Left</Text>
            </View>
          </Tooltip>

          <View style={{ width: 60 }} />

          <Tooltip content="Tooltip on Right" position="right">
            <View style={styles.trigger}>
              <Text style={styles.triggerText}>Right</Text>
            </View>
          </Tooltip>
        </View>

        <View style={styles.positionRow}>
          <Tooltip content="Tooltip on Bottom" position="bottom">
            <View style={styles.trigger}>
              <Text style={styles.triggerText}>Bottom</Text>
            </View>
          </Tooltip>
        </View>
      </View>

      {/* CONTENT TYPES SECTION */}
      <Text style={styles.sectionTitle}>Content Types</Text>

      <View style={styles.row}>
        <Tooltip content="Simple text tooltip">
          <View style={styles.iconTrigger}>
            <Text style={styles.icon}>ℹ️</Text>
            <Text style={styles.label}>Simple Text</Text>
          </View>
        </Tooltip>

        <Tooltip
          content={{
            title: 'Popover Title',
            text: 'This is the detailed description that provides more context.',
          }}
        >
          <View style={styles.iconTrigger}>
            <Text style={styles.icon}>📋</Text>
            <Text style={styles.label}>Title + Text</Text>
          </View>
        </Tooltip>
      </View>

      <Text style={styles.label}>Long Text Content</Text>
      <Tooltip
        content="This is a much longer tooltip text that demonstrates how the tooltip handles wrapping and stays within screen boundaries. It should be easy to read and not overflow."
        position="bottom"
      >
        <View style={styles.longTrigger}>
          <Text>Tap to see long tooltip</Text>
        </View>
      </Tooltip>

      <Text style={styles.label}>Custom Component</Text>
      <Tooltip
        content={{
          title: 'Quick Actions',
          component: (
            <View style={styles.customContent}>
              <Text style={styles.customAction}>✏️ Edit</Text>
              <Text style={styles.customAction}>📋 Copy</Text>
              <Text style={styles.customAction}>🗑️ Delete</Text>
            </View>
          ),
        }}
        position="bottom"
        maxWidth={180}
      >
        <View style={styles.longTrigger}>
          <Text>⋮ More Actions</Text>
        </View>
      </Tooltip>

      {/* COLORS SECTION */}
      <Text style={styles.sectionTitle}>Custom Colors</Text>
      <View style={styles.row}>
        <Tooltip
          content="Dark tooltip"
          backgroundColor="#333"
          textColor="#fff"
        >
          <View style={[styles.trigger, { backgroundColor: '#333' }]}>
            <Text style={[styles.triggerText, { color: '#fff' }]}>Dark</Text>
          </View>
        </Tooltip>

        <Tooltip
          content="Brand tooltip"
          backgroundColor="#d9232d"
          textColor="#fff"
        >
          <View style={[styles.trigger, { backgroundColor: '#d9232d' }]}>
            <Text style={[styles.triggerText, { color: '#fff' }]}>Brand</Text>
          </View>
        </Tooltip>

        <Tooltip
          content="Success tooltip"
          backgroundColor="#34C759"
          textColor="#fff"
        >
          <View style={[styles.trigger, { backgroundColor: '#34C759' }]}>
            <Text style={[styles.triggerText, { color: '#fff' }]}>Success</Text>
          </View>
        </Tooltip>
      </View>

      <View style={styles.row}>
        <Tooltip
          content="Info tooltip"
          backgroundColor="#007AFF"
          textColor="#fff"
        >
          <View style={[styles.trigger, { backgroundColor: '#007AFF' }]}>
            <Text style={[styles.triggerText, { color: '#fff' }]}>Info</Text>
          </View>
        </Tooltip>

        <Tooltip
          content="Warning tooltip"
          backgroundColor="#FF9500"
          textColor="#fff"
        >
          <View style={[styles.trigger, { backgroundColor: '#FF9500' }]}>
            <Text style={[styles.triggerText, { color: '#fff' }]}>Warning</Text>
          </View>
        </Tooltip>
      </View>

      {/* STYLING SECTION */}
      <Text style={styles.sectionTitle}>Styling Options</Text>

      <View style={styles.row}>
        <Tooltip content="No arrow pointer" showArrow={false}>
          <View style={styles.trigger}>
            <Text style={styles.triggerText}>No Arrow</Text>
          </View>
        </Tooltip>

        <Tooltip content="Large arrow" arrowSize={10}>
          <View style={styles.trigger}>
            <Text style={styles.triggerText}>Big Arrow</Text>
          </View>
        </Tooltip>
      </View>

      <View style={styles.row}>
        <Tooltip
          content="With overlay background"
          overlayColor="rgba(0,0,0,0.3)"
        >
          <View style={styles.trigger}>
            <Text style={styles.triggerText}>Overlay</Text>
          </View>
        </Tooltip>

        <Tooltip
          content="Custom styled tooltip"
          tooltipStyle={{
            borderRadius: 16,
            borderWidth: 2,
            borderColor: '#d9232d',
          }}
          textStyle={{
            fontWeight: 'bold',
            color: '#d9232d',
          }}
        >
          <View style={styles.trigger}>
            <Text style={styles.triggerText}>Styled</Text>
          </View>
        </Tooltip>
      </View>

      {/* CALLBACKS SECTION */}
      <Text style={styles.sectionTitle}>Callbacks</Text>
      <Text style={styles.info}>Tooltip shown: {showCount} times</Text>
      <Tooltip
        content="This tooltip tracks when it's shown"
        onShow={() => setShowCount(prev => prev + 1)}
        onHide={() => console.log('Hidden')}
      >
        <View style={styles.longTrigger}>
          <Text>Tap to increment counter</Text>
        </View>
      </Tooltip>

      {/* STATES SECTION */}
      <Text style={styles.sectionTitle}>States</Text>
      <View style={styles.row}>
        <Tooltip content="Normal tooltip">
          <View style={styles.trigger}>
            <Text style={styles.triggerText}>Normal</Text>
          </View>
        </Tooltip>

        <Tooltip content="Won't show" disabled={true}>
          <View style={[styles.trigger, styles.disabledTrigger]}>
            <Text style={[styles.triggerText, { color: '#999' }]}>Disabled</Text>
          </View>
        </Tooltip>
      </View>

      {/* EDGE CASES SECTION */}
      <Text style={styles.sectionTitle}>Edge Cases</Text>

      <Text style={styles.label}>Near Screen Edge (Left)</Text>
      <View style={{ alignItems: 'flex-start' }}>
        <Tooltip content="This tooltip adjusts to stay on screen" position="top">
          <View style={styles.trigger}>
            <Text style={styles.triggerText}>Edge</Text>
          </View>
        </Tooltip>
      </View>

      <Text style={styles.label}>Near Screen Edge (Right)</Text>
      <View style={{ alignItems: 'flex-end' }}>
        <Tooltip content="This tooltip adjusts to stay on screen" position="top">
          <View style={styles.trigger}>
            <Text style={styles.triggerText}>Edge</Text>
          </View>
        </Tooltip>
      </View>

      <View style={{ height: 100 }} />
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  content: {
    padding: 20,
  },
  title: {
    fontSize: 28,
    fontWeight: 'bold',
    textAlign: 'center',
    marginBottom: 5,
    color: '#333',
  },
  subtitle: {
    fontSize: 16,
    textAlign: 'center',
    marginBottom: 30,
    color: '#666',
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    marginTop: 30,
    marginBottom: 15,
    color: '#333',
    borderBottomWidth: 1,
    borderBottomColor: '#ddd',
    paddingBottom: 5,
  },
  label: {
    fontSize: 14,
    color: '#666',
    marginBottom: 8,
    marginTop: 15,
  },
  info: {
    fontSize: 14,
    color: '#666',
    marginBottom: 10,
    fontFamily: 'monospace',
  },
  row: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    gap: 15,
    marginBottom: 10,
  },
  positionsGrid: {
    alignItems: 'center',
    gap: 20,
    paddingVertical: 20,
  },
  positionRow: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  trigger: {
    backgroundColor: '#e0e0e0',
    paddingVertical: 10,
    paddingHorizontal: 16,
    borderRadius: 8,
    alignItems: 'center',
    justifyContent: 'center',
  },
  triggerText: {
    fontSize: 14,
    fontWeight: '600',
    color: '#333',
  },
  iconTrigger: {
    alignItems: 'center',
    gap: 5,
  },
  icon: {
    fontSize: 30,
  },
  longTrigger: {
    backgroundColor: '#e0e0e0',
    padding: 16,
    borderRadius: 8,
    alignItems: 'center',
  },
  disabledTrigger: {
    backgroundColor: '#f0f0f0',
    opacity: 0.6,
  },
  customContent: {
    marginTop: 10,
    gap: 8,
  },
  customAction: {
    fontSize: 14,
    paddingVertical: 4,
  },
});

export default TooltipTestScreen;

Usage in Your App

// App.js or navigation screen
import TooltipTestScreen from './TooltipTestScreen';

// In your navigator or directly
<TooltipTestScreen />

License

MIT © Atom Design