Tooltip
A label that provides information on hover or focus.
You can explore the tooltip component in the following curated examples.
Popover with Tooltip
Render a Popover with a Tooltip that shows upon hovering over the Popover Trigger.
Slider with Tooltip
Render a Slider with a Tooltip that shows the current value of the Slider.
Tooltip with following cursor
Render a Tooltip that follows the cursor when hovering over the target element.
Dialog with Tooltip
Render a Dialog with a Tooltip that shows upon hovering over the Dialog Trigger.
Anatomy
To set up the tooltip correctly, you'll need to understand its anatomy and how we name its parts.
Each part includes a
data-partattribute to help identify them in the DOM.
Examples
Learn how to use the Tooltip component in your project. Let's take a look at the most basic example:
import { Tooltip } from '@ark-ui/react/tooltip'
export const Basic = () => (
<Tooltip.Root>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
)
import { Tooltip } from '@ark-ui/solid/tooltip'
import { Portal } from 'solid-js/web'
export const Basic = () => (
<Tooltip.Root>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Portal>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Portal>
</Tooltip.Root>
)
<script setup lang="ts">
import { Tooltip } from '@ark-ui/vue/tooltip'
</script>
<template>
<Tooltip.Root>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
</template>
<script lang="ts">
import { Tooltip } from '@ark-ui/svelte/tooltip'
</script>
<Tooltip.Root id="tooltip">
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
Controlled Tooltip
To create a controlled Tooltip component, manage the state of whether the tooltip is open using the open prop:
import { Tooltip } from '@ark-ui/react/tooltip'
import { useState } from 'react'
export const Controlled = () => {
const [isOpen, setIsOpen] = useState(false)
return (
<>
<button type="button" onClick={() => setIsOpen(!isOpen)}>
Toggle
</button>
<Tooltip.Root open={isOpen} onOpenChange={({open}) => setIsOpen(open)}>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
</>
)
}
import { Tooltip } from '@ark-ui/solid/tooltip'
import { createSignal } from 'solid-js'
import { Portal } from 'solid-js/web'
export const Controlled = () => {
const [isOpen, setIsOpen] = createSignal(false)
return (
<>
<button type="button" onClick={() => setIsOpen(!isOpen())}>
Toggle
</button>
<Tooltip.Root open={isOpen()}>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Portal>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Portal>
</Tooltip.Root>
</>
)
}
<script setup lang="ts">
import { Tooltip } from '@ark-ui/vue/tooltip'
import { ref } from 'vue'
const isOpen = ref(false)
</script>
<template>
<button @click="isOpen = !isOpen">Toggle</button>
<Tooltip.Root v-model:open="isOpen">
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
</template>
<script lang="ts">
import { Tooltip } from '@ark-ui/svelte/tooltip'
let open = $state(false)
</script>
<div>
<pre>{JSON.stringify({ open }, null, 2)}</pre>
<button onclick={() => (open = !open)}>Toggle tooltip</button>
<Tooltip.Root id="controlled-tooltip" bind:open>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a controlled tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
</div>
Using a Render Function
For more control over the Tooltip's functionality, you can use a function as a child, which provides access to the Tooltip API:
import { Tooltip } from '@ark-ui/react/tooltip'
export const RenderFn = () => (
<Tooltip.Root>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Context>
{(tooltip) => <Tooltip.Content>This tooltip is open: {tooltip.open.toString()}</Tooltip.Content>}
</Tooltip.Context>
</Tooltip.Positioner>
</Tooltip.Root>
)
import { Tooltip } from '@ark-ui/solid/tooltip'
import { Portal } from 'solid-js/web'
export const RenderFn = () => (
<Tooltip.Root>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Portal>
<Tooltip.Positioner>
<Tooltip.Context>
{(context) => <Tooltip.Content>This tooltip is open: {context().open.toString()}</Tooltip.Content>}
</Tooltip.Context>
</Tooltip.Positioner>
</Portal>
</Tooltip.Root>
)
<script setup lang="ts">
import { Tooltip } from '@ark-ui/vue/tooltip'
</script>
<template>
<Tooltip.Root>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Context v-slot="tooltip">
<Tooltip.Content>This tooltip is open: {{ tooltip.open.toString() }}</Tooltip.Content>
</Tooltip.Context>
</Tooltip.Positioner>
</Tooltip.Root>
</template>
<script lang="ts">
import { Tooltip } from '@ark-ui/svelte/tooltip'
</script>
<Tooltip.Root id="tooltip-render-fn">
<Tooltip.Trigger>Hover for dynamic content</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>
Current time: {new Date().toLocaleTimeString()}
</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
Adding an Arrow
To display an arrow pointing to the trigger from the tooltip, use the Tooltip.Arrow and Tooltip.ArrowTip components:
import { Tooltip } from '@ark-ui/react/tooltip'
export const Arrow = () => (
<Tooltip.Root>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>
<Tooltip.Arrow>
<Tooltip.ArrowTip />
</Tooltip.Arrow>
I am a tooltip!
</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
)
import { Tooltip } from '@ark-ui/solid/tooltip'
import { Portal } from 'solid-js/web'
export const Arrow = () => (
<Tooltip.Root>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Portal>
<Tooltip.Positioner>
<Tooltip.Content>
<Tooltip.Arrow>
<Tooltip.ArrowTip />
</Tooltip.Arrow>
I am a tooltip!
</Tooltip.Content>
</Tooltip.Positioner>
</Portal>
</Tooltip.Root>
)
<script setup lang="ts">
import { Tooltip } from '@ark-ui/vue/tooltip'
</script>
<template>
<Tooltip.Root>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>
<Tooltip.Arrow>
<Tooltip.ArrowTip />
</Tooltip.Arrow>
I am a tooltip!
</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
</template>
<script lang="ts">
import { Tooltip } from '@ark-ui/svelte/tooltip'
</script>
<Tooltip.Root id="tooltip-arrow">
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>
<Tooltip.Arrow>
<Tooltip.ArrowTip />
</Tooltip.Arrow>
I am a tooltip with an arrow!
</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
Configuring Delay Timings
To configure the delay timings for the Tooltip, use the closeDelay and openDelay props:
import { Tooltip } from '@ark-ui/react/tooltip'
export const Timings = () => (
<Tooltip.Root closeDelay={0} openDelay={0}>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
)
import { Tooltip } from '@ark-ui/solid/tooltip'
import { Portal } from 'solid-js/web'
export const Timings = () => (
<Tooltip.Root closeDelay={0} openDelay={0}>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Portal>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Portal>
</Tooltip.Root>
)
<script setup lang="ts">
import { Tooltip } from '@ark-ui/vue/tooltip'
</script>
<template>
<Tooltip.Root :closeDelay="0" :openDelay="0">
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
</template>
<script lang="ts">
import { Tooltip } from '@ark-ui/svelte/tooltip'
</script>
<Tooltip.Root id="tooltip-timings" openDelay={1000} closeDelay={500}>
<Tooltip.Trigger>Hover Me (Slow)</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I have custom timing! Open delay: 1s, Close delay: 0.5s</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
Custom Positioning
To customize the position of the Tooltip relative to the trigger, use the positioning prop:
import { Tooltip } from '@ark-ui/react/tooltip'
export const Positioning = () => (
<Tooltip.Root
positioning={{
placement: 'left-start',
offset: { mainAxis: 12, crossAxis: 12 },
}}
>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
)
import { Tooltip } from '@ark-ui/solid/tooltip'
import { Portal } from 'solid-js/web'
export const Positioning = () => (
<Tooltip.Root
positioning={{
placement: 'left-start',
offset: { mainAxis: 12, crossAxis: 12 },
}}
>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Portal>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Portal>
</Tooltip.Root>
)
<script setup lang="ts">
import { Tooltip } from '@ark-ui/vue/tooltip'
</script>
<template>
<Tooltip.Root
:positioning="{
placement: 'left-start',
gutter: 16,
offset: { mainAxis: 12, crossAxis: 12 },
}"
>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
</template>
<script lang="ts">
import { Tooltip } from '@ark-ui/svelte/tooltip'
</script>
<div style="display: flex; gap: 1rem; justify-content: center; margin: 2rem;">
<Tooltip.Root id="tooltip-top" positioning={{ placement: 'top' }}>
<Tooltip.Trigger>Top</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>Tooltip on top</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
<Tooltip.Root id="tooltip-bottom" positioning={{ placement: 'bottom' }}>
<Tooltip.Trigger>Bottom</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>Tooltip on bottom</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
<Tooltip.Root id="tooltip-left" positioning={{ placement: 'left' }}>
<Tooltip.Trigger>Left</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>Tooltip on left</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
<Tooltip.Root id="tooltip-right" positioning={{ placement: 'right' }}>
<Tooltip.Trigger>Right</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>Tooltip on right</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.Root>
</div>
Using the Root Provider
The RootProvider component provides a context for the tooltip. It accepts the value of the useTooltip hook. You can
leverage it to access the component state and methods from outside the tooltip.
import { Tooltip, useTooltip } from '@ark-ui/react/tooltip'
export const RootProvider = () => {
const tooltip = useTooltip()
return (
<>
<button onClick={() => tooltip.setOpen(true)}>Open</button>
<Tooltip.RootProvider value={tooltip}>
<Tooltip.Trigger disabled>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.RootProvider>
</>
)
}
import { Tooltip, useTooltip } from '@ark-ui/solid/tooltip'
import { Portal } from 'solid-js/web'
export const RootProvider = () => {
const tooltip = useTooltip()
return (
<>
<button onClick={() => tooltip().setOpen(true)}>Open</button>
<Tooltip.RootProvider value={tooltip}>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Portal>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Portal>
</Tooltip.RootProvider>
</>
)
}
<script setup lang="ts">
import { Tooltip, useTooltip } from '@ark-ui/vue/tooltip'
const tooltip = useTooltip()
</script>
<template>
<button @click="tooltip.setOpen(true)">Open</button>
<Tooltip.RootProvider :value="tooltip">
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.RootProvider>
</template>
<script lang="ts">
import { Tooltip, useTooltip } from '@ark-ui/svelte/tooltip'
const tooltip = useTooltip({ id: 'tooltip-provider' })
</script>
<div>
<button onclick={() => tooltip().setOpen(true)}>Open tooltip</button>
<button onclick={() => tooltip().setOpen(false)}>Close tooltip</button>
<Tooltip.RootProvider value={tooltip}>
<Tooltip.Trigger>Hover Me</Tooltip.Trigger>
<Tooltip.Positioner>
<Tooltip.Content>I am a tooltip using root provider!</Tooltip.Content>
</Tooltip.Positioner>
</Tooltip.RootProvider>
</div>
If you're using the
RootProvidercomponent, you don't need to use theRootcomponent.
API Reference
Props
Root
| Prop | Default | Type |
|---|---|---|
aria-label | stringCustom label for the tooltip. | |
closeDelay | 500 | numberThe close delay of the tooltip. |
closeOnClick | true | booleanWhether the tooltip should close on click |
closeOnEscape | true | booleanWhether to close the tooltip when the Escape key is pressed. |
closeOnPointerDown | true | booleanWhether to close the tooltip on pointerdown. |
closeOnScroll | true | booleanWhether the tooltip should close on scroll |
defaultOpen | booleanThe initial open state of the tooltip when rendered. Use when you don't need to control the open state of the tooltip. | |
disabled | booleanWhether the tooltip is disabled | |
id | stringThe unique identifier of the machine. | |
ids | Partial<{ trigger: string; content: string; arrow: string; positioner: string }>The ids of the elements in the tooltip. Useful for composition. | |
immediate | booleanWhether to synchronize the present change immediately or defer it to the next frame | |
interactive | false | booleanWhether the tooltip's content is interactive. In this mode, the tooltip will remain open when user hovers over the content. |
lazyMount | false | booleanWhether to enable lazy mounting |
onExitComplete | VoidFunctionFunction called when the animation ends in the closed state | |
onOpenChange | (details: OpenChangeDetails) => voidFunction called when the tooltip is opened. | |
open | booleanThe controlled open state of the tooltip | |
openDelay | 1000 | numberThe open delay of the tooltip. |
positioning | PositioningOptionsThe user provided options used to position the popover content | |
present | booleanWhether the node is present (controlled by the user) | |
skipAnimationOnMount | false | booleanWhether to allow the initial presence animation. |
unmountOnExit | false | booleanWhether to unmount on exit. |
Arrow
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| CSS Variable | Description |
|---|---|
--arrow-size | The size of the arrow |
--arrow-size-half | Half the size of the arrow |
--arrow-background | Use this variable to style the arrow background |
--arrow-offset | The offset position of the arrow |
ArrowTip
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Content
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | tooltip |
[data-part] | content |
[data-state] | "open" | "closed" |
[data-placement] | The placement of the content |
Positioner
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| CSS Variable | Description |
|---|---|
--reference-width | The width of the reference element |
--reference-height | The height of the root |
--available-width | The available width in viewport |
--available-height | The available height in viewport |
--x | The x position for transform |
--y | The y position for transform |
--z-index | The z-index value |
--transform-origin | The transform origin for animations |
RootProvider
| Prop | Default | Type |
|---|---|---|
value | UseTooltipReturn | |
immediate | booleanWhether to synchronize the present change immediately or defer it to the next frame | |
lazyMount | false | booleanWhether to enable lazy mounting |
onExitComplete | VoidFunctionFunction called when the animation ends in the closed state | |
present | booleanWhether the node is present (controlled by the user) | |
skipAnimationOnMount | false | booleanWhether to allow the initial presence animation. |
unmountOnExit | false | booleanWhether to unmount on exit. |
Trigger
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | tooltip |
[data-part] | trigger |
[data-expanded] | Present when expanded |
[data-state] | "open" | "closed" |
Context
These are the properties available when using Tooltip.Context, useTooltipContext hook or useTooltip hook.
API
| Property | Type |
|---|---|
open | booleanWhether the tooltip is open. |
setOpen | (open: boolean) => voidFunction to open the tooltip. |
reposition | (options?: Partial<PositioningOptions>) => voidFunction to reposition the popover |
Accessibility
Complies with the Tooltip WAI-ARIA design pattern.
Keyboard Support
| Key | Description |
|---|---|
Tab | Opens/closes the tooltip without delay. |
Escape | If open, closes the tooltip without delay. |