Tooltip

A popup that displays related information when a button receives keyboard focus or the mouse hovers over it.

Features

  • Opens when the trigger is focused or hovered.
  • Closes when the trigger is activated or when pressing escape.
  • Provider to control display delay globally.

Keyboard interactions

KeyDescription
TabOpens/closes the tooltip without delay.
SpaceIf open, closes the tooltip without delay.
EnterIf open, closes the tooltip without delay.
EscapeIf open, closes the tooltip without delay.

Usage

TooltipExample.tsx
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
<Text className="mt-4">
Here's the{' '}
<Tooltip content="This is a tooltip">
<button className="bg-green-500">tooltip component</button>
</Tooltip>{' '}
in action.
</Text>

Here's the in action.

Props

PropTypeDefault
contentstring''

Installation

You can follow the global installation guide that will install everything you need to use all the components or you can install the tooltip component by itself by installing its dependencies and wrap your app with the tooltip provider.

Either way, you'll need the to add 'tooltip' to the spacing key on the extendTailwindMerge() function, so twMerge() knows that the tooltip's custom class text-size-tooltip belongs to the sizing category, so it won't conflict with color classes like text-tooltip-foreground, bg-tooltip-background, or text-green-500 for example.

tailwind-merge.ts
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
import { type ClassValue, clsx } from 'clsx'
import { extendTailwindMerge } from 'tailwind-merge'
const twMerge = extendTailwindMerge({
classGroups: {
spacing: [{ 'text-size': ['tooltip'] }],
},
})
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}

Provider

Additionally, the tooltip component's display delay is controlled globally by a tooltip provider, so you'll need to add the provider to your app's root component. A slight delay (300-500 milliseconds) is recommended to prevent accidental hover-triggered tooltips from appearing too quickly and becoming distracting.

root.tsx
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
import * as TooltipPrimitive from '@radix-ui/react-tooltip'
...
function App() {
return (
<html>
<head>
...
</head>
<body>
<TooltipPrimitive.Provider delayDuration={300}>
<Header />
<Outlet />
<Footer />
...
</TooltipPrimitive.Provider>
</body>
</html>
)
}

Dependencies

~
npm i @radix-ui/react-tooltip

Source

tooltip.tsx
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
import * as TooltipPrimitive from '@radix-ui/react-tooltip'
import { type ElementRef, forwardRef, type ComponentPropsWithoutRef, useState } from 'react'
import { cn } from '~/utils/tailwind-merge.ts'
type TooltipProps = ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
const Tooltip = forwardRef<ElementRef<typeof TooltipPrimitive.Content>, TooltipProps>(({ content, className, children }, ref) => {
const [isOpen, setIsOpen] = useState(false)
return (
<TooltipPrimitive.Root open={isOpen} onOpenChange={setIsOpen}>
<TooltipPrimitive.Trigger asChild>{children}</TooltipPrimitive.Trigger>
<TooltipPrimitive.Portal /* container={container} forceMount={forceMount} */>
<TooltipPrimitive.Content
sideOffset={4}
collisionPadding={10}
ref={ref}
className={cn('rounded-md bg-tooltip-background px-2 text-size-tooltip text-tooltip-foreground', className)}
>
{content}
<TooltipPrimitive.Arrow className="fill-tooltip-background" />
</TooltipPrimitive.Content>
</TooltipPrimitive.Portal>
</TooltipPrimitive.Root>
)
})
export { Tooltip }

Styling

The tooltip's styling is controlled through CSS variables.

tailwind.css
  1. 1
  2. 2
  3. 3
--tooltip-color-background: var(--color-foreground);
--tooltip-color-foreground: var(--color-background);
--tooltip-text-size: var(--text-size-sm);