Tooltip
A tooltip displays a brief description of an element on hover or focus.
import { Button, Tooltip, TooltipTrigger } from "@opengovsg/oui"export const Example = () => { return ( <TooltipTrigger> <Button>Hover me</Button> <Tooltip>This is a tooltip</Tooltip> </TooltipTrigger> )}Usage
Use Tooltip for short, non-blocking hints shown on hover or focus. Use Modal when content requires interaction. Use the field's description prop for inline help text on form inputs.
import { Button, Tooltip, TooltipTrigger } from "@opengovsg/oui"<TooltipTrigger>
<Button>Hover me</Button>
<Tooltip>This is a tooltip</Tooltip>
</TooltipTrigger>Alternatively, install the component as local source via the shadcn CLI:
npx shadcn@latest add https://oui.open.gov.sg/r/tooltip.jsonpnpm dlx shadcn@latest add https://oui.open.gov.sg/r/tooltip.jsonnpx shadcn@latest add https://oui.open.gov.sg/r/tooltip.jsonbunx --bun shadcn@latest add https://oui.open.gov.sg/r/tooltip.jsonOUI exports 2 tooltip-related components:
- TooltipTrigger: Wraps a trigger element and a
Tooltip. Handles showing and hiding the tooltip on hover, focus, and keyboard interactions. - Tooltip: The tooltip overlay that displays the content.
Note: Tooltips are not shown on touch screen interactions. Ensure that your UI is usable without tooltips, or use an alternative component such as a Popover to show information in an adjacent element.
Examples
Placement
Use the placement prop on Tooltip to control the position of the tooltip relative to its trigger. Supported values include top, bottom, start, end, and their combinations (e.g., top start, bottom end).
Defaults to top.
import { Button, Tooltip, TooltipTrigger } from "@opengovsg/oui"export const Example = () => { return ( <div className="flex flex-wrap gap-6"> <TooltipTrigger> <Button variant="outline">Top</Button> <Tooltip placement="top">Tooltip on top</Tooltip> </TooltipTrigger> <TooltipTrigger> <Button variant="outline">Bottom</Button> <Tooltip placement="bottom">Tooltip on bottom</Tooltip> </TooltipTrigger> <TooltipTrigger> <Button variant="outline">Start</Button> <Tooltip placement="start">Tooltip on start</Tooltip> </TooltipTrigger> <TooltipTrigger> <Button variant="outline">End</Button> <Tooltip placement="end">Tooltip on end</Tooltip> </TooltipTrigger> </div> )}Without Arrow
Set showArrow={false} to hide the arrow indicator on the tooltip.
import { Button, Tooltip, TooltipTrigger } from "@opengovsg/oui"export const Example = () => { return ( <TooltipTrigger> <Button>Hover me</Button> <Tooltip showArrow={false}>Tooltip without arrow</Tooltip> </TooltipTrigger> )}Offset
Use the offset prop to control the distance between the tooltip and the trigger element. The default offset is 10.
import { Button, Tooltip, TooltipTrigger } from "@opengovsg/oui"export const Example = () => { return ( <div className="flex flex-wrap gap-6"> <TooltipTrigger> <Button variant="outline">Default offset (10)</Button> <Tooltip>Default offset</Tooltip> </TooltipTrigger> <TooltipTrigger> <Button variant="outline">Offset 0</Button> <Tooltip offset={0}>No offset</Tooltip> </TooltipTrigger> <TooltipTrigger> <Button variant="outline">Offset 20</Button> <Tooltip offset={20}>Larger offset</Tooltip> </TooltipTrigger> </div> )}Controlled
You can control the tooltip's open state using the isOpen and onOpenChange props on TooltipTrigger.
import { useState } from "react"import { Button, Tooltip, TooltipTrigger } from "@opengovsg/oui"export const Example = () => { const [isOpen, setIsOpen] = useState(false) return ( <div className="flex flex-col items-center gap-4"> <TooltipTrigger isOpen={isOpen} onOpenChange={setIsOpen}> <Button>Trigger</Button> <Tooltip>Controlled tooltip</Tooltip> </TooltipTrigger> <p className="text-base-content-medium text-sm"> Tooltip is {isOpen ? "open" : "closed"} </p> </div> )}Slots
- base: The main container of the tooltip.
- arrow: The arrow indicator pointing to the trigger element.
Custom Styles
You can customize the Tooltip component by passing custom Tailwind CSS classes to the component slots via the classNames prop.
import { Button, Tooltip, TooltipTrigger } from "@opengovsg/oui"export const Example = () => { return ( <TooltipTrigger> <Button>Hover me</Button> <Tooltip classNames={{ base: "bg-gradient-to-br from-indigo-500 to-pink-500 text-white border-none px-4 py-2", arrow: "fill-indigo-500", }} > Custom styled tooltip </Tooltip> </TooltipTrigger> )}Accessibility
- Tooltip is shown on hover and keyboard focus of the trigger element.
- Tooltips have a warmup delay (300ms) before appearing. Once a tooltip is shown, subsequent tooltips in the same group appear instantly.
- Content outside the tooltip is not blocked — tooltips are non-modal.
- The trigger element must have a proper ARIA role or use a semantic HTML element (e.g.,
<button>) so that screen readers can announce the tooltip. - Press the Esc key to dismiss the tooltip.
Props
Tooltip
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | The content of the tooltip |
placement | Placement | "top" | The placement of the tooltip relative to the trigger |
offset | number | 10 | The additional offset along the main axis from the trigger |
crossOffset | number | 0 | The additional offset along the cross axis |
shouldFlip | boolean | true | Whether the tooltip flips when insufficient space is available |
containerPadding | number | 12 | The spacing between the tooltip and the edge of the surrounding container |
showArrow | boolean | true | Whether to show the arrow pointing to the trigger element |
variant | "default" | "unstyled" | "default" | The visual variant of the tooltip |
radius | "none" | "sm" | "default" | "md" | "lg" | "full" | "sm" | The border radius of the tooltip |
classNames | SlotsToClasses<TooltipSlots> | - | Custom CSS classes for component slots |
TooltipTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | The trigger element and tooltip |
delay | number | 300 | The delay (in ms) before the tooltip opens on hover |
closeDelay | number | 0 | The delay (in ms) before the tooltip closes |
isOpen | boolean | - | Whether the tooltip is open (controlled) |
defaultOpen | boolean | - | Whether the tooltip is open by default (uncontrolled) |
isDisabled | boolean | - | Whether the tooltip trigger is disabled |
onOpenChange | (isOpen: boolean) => void | - | Callback when the tooltip open state changes |