Building a Custom Tooltip Component in React with Hover State Management

Building a Custom Tooltip Component in React with Hover State Management

Building a Custom Tooltip Component in React A Step-by-Step Guide

Feb 18th, 2025

By, Editorial Team

ReactJS

Tooltips are an essential part of modern UI design, providing contextual information to users without cluttering the interface. Whether you’re explaining a button’s purpose, offering additional details about an icon, or guiding users through complex workflows, tooltips enhance usability and user experience.

While third-party libraries like Material-UI or Bootstrap offer tooltip components, building a custom tooltip gives you full control over functionality, styling, and performance. In this tutorial, we’ll walk you through creating a lightweight, reusable, and accessible tooltip component in React. By the end, you’ll have a production-ready tooltip with hover-based visibility, dynamic positioning, accessibility enhancements, and smooth animations.

Let’s dive in!

1. Why Build a Custom Tooltip?

Before diving into the code, let’s take a moment to explore why building a custom tooltip might be a better choice than relying on third-party libraries. While pre-built solutions like Material-UI or Bootstrap offer ready-to-use tooltip components, they often come with trade-offs that can impact your project’s performance, flexibility, and maintainability. Here’s why crafting your own tooltip from scratch is worth the effort:

1.1 Lightweight and Performance-Focused

Third-party libraries are incredibly powerful, but they often include a wide range of features that you may never use. For example, a tooltip library might bundle support for advanced animations, complex positioning logic, or even internationalization—features that could bloat your application’s bundle size unnecessarily. By building a custom tooltip, you can keep things lean and focused, including only the functionality you actually need. This ensures your app remains lightweight and performs optimally, especially in scenarios where every kilobyte counts.

1.2 Complete Control Over Customization

One of the biggest advantages of building a custom tooltip is the ability to tailor every aspect of its behavior and appearance to match your design system. Want a tooltip with a unique animation, specific padding, or a custom font? With a third-party library, you’d need to override default styles or fight against predefined constraints. A custom solution gives you full creative freedom, allowing you to design a tooltip that seamlessly integrates with your brand identity and user experience goals.

1.3 Enhanced Learning Opportunity

Building a tooltip from scratch isn’t just about solving an immediate problem—it’s also a fantastic learning opportunity. Tooltips involve several fundamental React concepts, such as state management (useState), event handling (onMouseEnter, onMouseLeave), and DOM manipulation (dynamic positioning). By creating your own tooltip, you’ll deepen your understanding of these core principles while gaining hands-on experience in solving real-world UI challenges. Plus, the skills you develop here can be applied to other custom components, making you a more versatile developer.

1.4 Avoid Dependency Fatigue

Relying on third-party libraries can sometimes lead to dependency fatigue, where managing updates, compatibility issues, and breaking changes becomes a burden. By building your own tooltip, you eliminate the need to depend on external packages, giving you greater control over your codebase and reducing the risk of unexpected bugs or vulnerabilities. You’ll also avoid the frustration of debugging issues caused by library-specific quirks or limitations.

1.5 Tailored Accessibility and User Experience

Accessibility is a critical aspect of modern web development, and not all third-party tooltips are created equal when it comes to inclusivity. By building your own tooltip, you can ensure it meets accessibility standards (e.g., ARIA attributes, keyboard navigation) and provides the best possible experience for all users, including those using screen readers or assistive technologies. You can also fine-tune interactions like hover delays, click triggers, and responsive behavior to cater to your specific audience.

2. Key Features of Our Tooltip

Our custom tooltip is designed to be both functional and user-friendly, offering a seamless experience for developers and end-users alike. Let’s take a closer look at the standout features we’ll be implementing:

2.1 Hover-Based Visibility: Effortless Interactivity

One of the core functionalities of our tooltip is its ability to appear and disappear dynamically based on user interaction. When a user hovers over the target element—such as a button, icon, or link—the tooltip will instantly display relevant contextual information. As soon as the user moves their cursor away, the tooltip will vanish, ensuring it doesn’t clutter the interface unnecessarily. This hover-based visibility strikes the perfect balance between providing helpful information and maintaining a clean, distraction-free design.

2.2 Dynamic Positioning: Precision and Flexibility

Positioning is key to ensuring that tooltips are both visible and intuitive. Our tooltip will support dynamic positioning , allowing it to appear in multiple locations relative to the target element:

  • Above : Ideal for elements near the bottom of the screen.
  • Below : Perfect for elements near the top of the screen.
  • Left : Useful for right-aligned elements or compact layouts.
  • Right : Great for left-aligned elements or when space is limited.

We’ll calculate the tooltip’s position dynamically using JavaScript’s getBoundingClientRect, ensuring it adjusts intelligently to avoid being cut off by screen edges or overlapping with other UI elements. This flexibility ensures the tooltip always appears exactly where it’s needed, regardless of the layout or screen size.

2.3 Accessibility Considerations: Inclusive Design for All Users

Accessibility is a cornerstone of modern web development, and our tooltip will be no exception. We’ll incorporate ARIA attributes (such as aria-describedby) to ensure the tooltip content is accessible to users relying on screen readers or assistive technologies. Additionally, we’ll explore ways to make the tooltip usable via keyboard navigation, catering to users who navigate interfaces without a mouse. By prioritizing accessibility, we’ll create a tooltip that’s not only functional but also inclusive, ensuring no user is left behind.

2.4 TSmooth Animations and Transitions: Polished and Professional

A well-designed tooltip shouldn’t just be functional—it should also feel polished and professional. To achieve this, we’ll add smooth animations and transitions to enhance the user experience. Instead of abruptly appearing or disappearing, the tooltip will fade in and out gracefully, creating a sense of fluidity and refinement. We’ll implement these animations using CSS transitions or libraries like Framer Motion , giving you the flexibility to customize the timing, easing, and style of the animations. This subtle touch will make your tooltip stand out and feel like a natural part of your application.

2.5 Responsive Design: Optimized for Every Device

In today’s multi-device world, responsiveness is non-negotiable. Our tooltip will be designed to adapt seamlessly to different screen sizes, ensuring it remains usable and visually appealing on both desktops and mobile devices. For smaller screens, we’ll adjust the tooltip’s width, font size, and positioning to prevent it from being cut off or becoming too small to read. We’ll also explore click-triggered tooltips as an alternative to hover-based interactions, making the component more accessible on touch-enabled devices.

3. Step-by-Step Implementation

Now that we’ve outlined the key features of our custom tooltip, it’s time to bring it to life! In this section, we’ll walk you through the implementation process step by step. From setting up the basic structure to adding advanced enhancements, you’ll learn how to build a fully functional, reusable tooltip component in React. Let’s get coding!

3.1 Step 1: Setting Up the Basic Structure

We’ll start by creating a simple Tooltip component that wraps around any child element (e.g., a button or icon) and displays a tooltip when hovered.

Here’s the basic structure:

import React, { useState } from ‘react’;

const Tooltip = ({ content, position = ‘top’, children }) => {

  const [isVisible, setIsVisible] = useState(false);

  return (

    <div 

      onMouseEnter={() => setIsVisible(true)} 

      onMouseLeave={() => setIsVisible(false)}

      style={{ position: ‘relative’, display: ‘inline-block’ }}

    >

      {children}

      {isVisible && (

        <div 

          style={{

            position: ‘absolute’,

            top: position === ‘top’ ? ‘-30px’ : ‘auto’,

            bottom: position === ‘bottom’ ? ‘-30px’ : ‘auto’,

            left: ‘50%’,

            transform: ‘translateX(-50%)’,

            padding: ‘8px’,

            backgroundColor: ‘#333’,

            color: ‘#fff’,

            borderRadius: ‘4px’,

            whiteSpace: ‘nowrap’,

          }}

        >

          {content}

        </div>

      )}

    </div>

  );

};

export default Tooltip;

What’s Happening Here?

  • The Tooltip component accepts three props:
    • content: The text to display in the tooltip.
    • position: Where the tooltip should appear relative to the target element (top, bottom, etc.).
    • children: The element that triggers the tooltip (e.g., a button or icon).
  • We use useState to manage the visibility of the tooltip (isVisible).
  • Event handlers (onMouseEnter and onMouseLeave) toggle the tooltip’s visibility when the user hovers over the target element.

3.2 Step 2: Managing Hover State

The next step is to manage the tooltip’s visibility using React’s useState hook. We’ve already implemented this in the basic structure, but let’s break it down further.

  • When the user hovers over the target element, onMouseEnter sets isVisible to true.
  • When the user moves the mouse away, onMouseLeave sets isVisible to false.

This ensures the tooltip appears and disappears dynamically based on user interaction.

3.3 Step 3: Positioning Logic

Right now, the tooltip only appears above the target element (position=”top”). Let’s make it more flexible by supporting multiple positions: top, bottom, left, and right.

Update the positioning logic in the tooltip’s styles:

const getPositionStyles = (position) => {

  switch (position) {

    case ‘top’:

      return { bottom: ‘100%’, left: ‘50%’, transform: ‘translateX(-50%)’ };

    case ‘bottom’:

      return { top: ‘100%’, left: ‘50%’, transform: ‘translateX(-50%)’ };

    case ‘left’:

      return { right: ‘100%’, top: ‘50%’, transform: ‘translateY(-50%)’ };

    case ‘right’:

      return { left: ‘100%’, top: ‘50%’, transform: ‘translateY(-50%)’ };

    default:

      return { bottom: ‘100%’, left: ‘50%’, transform: ‘translateX(-50%)’ };

  }

};

Now, you can pass the position prop to control where the tooltip appears:

<Tooltip content=”Click me!” position=”bottom”>

  <button>Hover over me</button>

</Tooltip>

3.4 Step 4: Adding Animations

To make the tooltip feel polished, let’s add a fade-in/fade-out animation using CSS transitions:

<div 

  style={{

    position: ‘absolute’,

    …getPositionStyles(position),

    padding: ‘8px’,

    backgroundColor: ‘#333’,

    color: ‘#fff’,

    borderRadius: ‘4px’,

    whiteSpace: ‘nowrap’,

    opacity: isVisible ? 1 : 0,

    transition: ‘opacity 0.3s ease-in-out’,

    pointerEvents: isVisible ? ‘auto’ : ‘none’,

  }}

>

  {content}

</div>

The opacity property controls the visibility, while transition handles the smooth fade effect.

3.5 Step 5: Accessibility Enhancements

Accessibility is crucial for creating inclusive experiences. Let’s add ARIA attributes to ensure screen readers can interpret the tooltip.

Update the Tooltip component to include aria-describedby:

<div 

  onMouseEnter={() => setIsVisible(true)} 

  onMouseLeave={() => setIsVisible(false)}

  style={{ position: ‘relative’, display: ‘inline-block’ }}

  aria-describedby=”tooltip-content”

>

  {children}

  {isVisible && (

    <div 

      id=”tooltip-content”

      style={{

        position: ‘absolute’,

        …getPositionStyles(position),

        padding: ‘8px’,

        backgroundColor: ‘#333’,

        color: ‘#fff’,

        borderRadius: ‘4px’,

        whiteSpace: ‘nowrap’,

      }}

    >

      {content}

    </div>

  )}

</div>

This ensures that screen readers announce the tooltip content when the user interacts with the target element.

4. Advanced Enhancements

To take our custom tooltip to the next level, we’ll explore advanced enhancements that add even more functionality and polish. From click-triggered tooltips for mobile devices to handling edge cases like screen edges, these improvements will ensure your tooltip is robust, responsive, and production-ready. Let’s dive into these powerful upgrades!

4.1 Adding Support for Click-Triggered Tooltips

Tooltips are typically triggered by hover, but you can also make them appear on click for better mobile support. Update the event handlers to toggle visibility on click:

const [isVisible, setIsVisible] = useState(false);

const handleClick = () => {

  setIsVisible(!isVisible);

};

return (

  <div 

    onClick={handleClick}

    style={{ position: ‘relative’, display: ‘inline-block’ }}

  >

    {children}

    {isVisible && (

      <div 

        style={{

          position: ‘absolute’,

          …getPositionStyles(position),

          padding: ‘8px’,

          backgroundColor: ‘#333’,

          color: ‘#fff’,

          borderRadius: ‘4px’,

          whiteSpace: ‘nowrap’,

        }}

      >

        {content}

      </div>

    )}

  </div>

);

4.2 Handling Edge Cases

To handle edge cases like tooltips near screen edges, use JavaScript’s getBoundingClientRect to calculate the tooltip’s position dynamically:

const adjustPosition = (targetRect, tooltipRect) => {

  const viewportWidth = window.innerWidth;

  const viewportHeight = window.innerHeight;

  let adjustedTop = targetRect.top – tooltipRect.height;

  let adjustedLeft = targetRect.left + targetRect.width / 2 – tooltipRect.width / 2;

  // Adjust if tooltip goes off-screen

  if (adjustedTop < 0) adjustedTop = targetRect.bottom;

  if (adjustedLeft < 0) adjustedLeft = 0;

  if (adjustedLeft + tooltipRect.width > viewportWidth) {

    adjustedLeft = viewportWidth – tooltipRect.width;

  }

  return { top: adjustedTop, left: adjustedLeft };

};

4.3 Making the Tooltip Responsive

For mobile devices, ensure the tooltip adjusts its size and font based on the screen width:

const getResponsiveStyles = () => {

  if (window.innerWidth < 600) {

    return {

      maxWidth: ‘200px’,

      fontSize: ’12px’,

    };

  }

  return {

    maxWidth: ‘300px’,

    fontSize: ’14px’,

  };

};

5. FAQs

Can I Use This Tooltip on Mobile Devices?

Yes, absolutely! While tooltips are traditionally hover-based, we’ve included enhancements to make them work seamlessly on touch devices. For mobile users, you can implement click-triggered visibility instead of hover. Additionally, the tooltip’s responsive design ensures it adapts to smaller screens, providing an optimal experience across all devices.

How Do I Handle Tooltips Near the Edge of the Screen?

Great question! To prevent tooltips from being cut off near screen edges, we use JavaScript’s getBoundingClientRect to dynamically calculate and adjust their position. If the tooltip would extend beyond the viewport, it automatically repositions itself (e.g., flipping from top to bottom or adjusting horizontally) to stay fully visible.

Is This Tooltip Accessible for Users with Disabilities?

Yes, accessibility is a key focus of this implementation. We’ve added ARIA attributes like aria-describedby to ensure screen readers can interpret the tooltip content. Additionally, you can extend the functionality to support keyboard navigation, making the tooltip usable for individuals who rely on assistive technologies or navigate without a mouse.

6. Conclusion

By following this guide, you’ve built a fully functional, customizable tooltip component in React. It’s lightweight, accessible, and easy to integrate into any project. Plus, you now have a deeper understanding of React concepts like state management, event handling, and DOM manipulation.

Feel free to experiment with the code and add your own enhancements—like keyboard navigation or advanced animations. Happy coding!

Ready to Build Your Own Custom Tooltip?

WHAT'S YOUR TAKE?

Your email address will not be published. Required fields are marked *

We encompass a wide range of solutions, including eCommerce development, WordPress development, mobile app development, and digital marketing.

SUBSCRIBE NOW

Subscribe to AssaptR, our monthly look.
You have been successfully Subscribed! Oops! Something went wrong, please try again.

Contact info

Chat With Us
1
💭Need Help
Caught You! 👋🏻
Seeking For A Quick Assistance? We're Right Here!