Tooltip
A popup that displays information when its trigger receives keyboard focus or the mouse hovers over it. It uses the awesome Floating UI library in the background for positioning and allows you to fully customize its behavior.
import { Star } from '@examples/primitives/tooltip/icons'
import Tooltip from '@corvu/tooltip'
import type { VoidComponent } from 'solid-js'
const TooltipExample: VoidComponent = () => {
return (
<Tooltip
placement="top"
openDelay={200}
floatingOptions={{
offset: 13,
flip: true,
shift: true,
}}
>
<Tooltip.Trigger
as="a"
class="my-auto rounded-full bg-corvu-100 p-3 transition-all duration-100 hover:bg-corvu-200 active:translate-y-0.5"
href="https://github.com/corvudev/corvu/"
target="_blank"
>
<Star size="26" />
<span class="sr-only">corvu on GitHub</span>
</Tooltip.Trigger>
<Tooltip.Portal>
<Tooltip.Content class="rounded-lg bg-corvu-100 px-3 py-2 font-medium corvu-open:animate-in corvu-open:fade-in-50 corvu-open:slide-in-from-bottom-1 corvu-closed:animate-out corvu-closed:fade-out-50 corvu-closed:slide-out-to-bottom-1">
Give corvu a star! ⭐️
<Tooltip.Arrow class="text-corvu-100" />
</Tooltip.Content>
</Tooltip.Portal>
</Tooltip>
)
}
export default TooltipExample
import animatePlugin from 'tailwindcss-animate'
import corvuPlugin from '@corvu/tailwind'
import formsPlugin from '@tailwindcss/forms'
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{ts,tsx}'],
theme: {
extend: {
colors: {
corvu: {
bg: '#f3f1fe',
100: '#e6e2fd',
200: '#d4cbfb',
300: '#bcacf6',
400: '#a888f1',
text: '#180f24',
},
},
},
},
plugins: [animatePlugin, corvuPlugin, formsPlugin],
}
import './index.css'
import { Star } from '@examples/primitives/tooltip/icons'
import Tooltip from '@corvu/tooltip'
import type { VoidComponent } from 'solid-js'
const TooltipExample: VoidComponent = () => {
return (
<Tooltip
placement="top"
openDelay={200}
floatingOptions={{
offset: 13,
flip: true,
shift: true,
}}
>
<Tooltip.Trigger
as="a"
href="https://github.com/corvudev/corvu/"
target="_blank"
>
<Star size="26" />
<span class="sr-only">corvu on GitHub</span>
</Tooltip.Trigger>
<Tooltip.Portal>
<Tooltip.Content>
Give corvu a star! ⭐️
<Tooltip.Arrow />
</Tooltip.Content>
</Tooltip.Portal>
</Tooltip>
)
}
export default TooltipExample
[data-corvu-tooltip-trigger] {
margin-top: auto;
margin-bottom: auto;
border-radius: 9999px;
background-color: hsl(249, 87%, 94%);
padding: 0.75rem;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 100ms;
}
[data-corvu-tooltip-trigger]:hover {
background-color: hsl(251, 86%, 89%);
}
[data-corvu-tooltip-trigger]:active {
transform: translate(0, 0.125rem);
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
[data-corvu-tooltip-content] {
border-radius: 0.5rem;
background-color: hsl(249, 87%, 94%);
padding-left: 0.75rem;
padding-right: 0.75rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
font-weight: 500;
}
@keyframes enter {
from {
opacity: var(--tw-enter-opacity, 1);
transform: translate3d(var(--tw-enter-translate-x, 0), var(--tw-enter-translate-y, 0), 0) scale3d(var(--tw-enter-scale, 1), var(--tw-enter-scale, 1), var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0))
}
}
@keyframes exit {
to {
opacity: var(--tw-exit-opacity, 1);
transform: translate3d(var(--tw-exit-translate-x, 0), var(--tw-exit-translate-y, 0), 0) scale3d(var(--tw-exit-scale, 1), var(--tw-exit-scale, 1), var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0))
}
}
[data-corvu-tooltip-content][data-open] {
animation-name: enter;
animation-duration: 150ms;
--tw-enter-opacity: initial;
--tw-enter-scale: initial;
--tw-enter-rotate: initial;
--tw-enter-translate-x: initial;
--tw-enter-translate-y: initial;
--tw-enter-opacity: 0.5;
--tw-enter-translate-y: 0.25rem;
}
[data-corvu-tooltip-content][data-closed] {
animation-name: exit;
animation-duration: 150ms;
--tw-exit-opacity: initial;
--tw-exit-scale: initial;
--tw-exit-rotate: initial;
--tw-exit-translate-x: initial;
--tw-exit-translate-y: initial;
--tw-exit-opacity: 0.5;
--tw-exit-translate-y: 0.25rem;
}
[data-corvu-tooltip-arrow] {
color: hsl(249, 87%, 94%);
}
Features Section titled Features
- Customizable positioning behavior
- Safe area between the trigger and content for better usability
- Custom open and close delays
- Optional arrow component
Installation Section titled Installation
npm install @corvu/tooltip
The tooltip is also included in the main corvu
package under corvu/tooltip
.
Usage Section titled Usage
import Tooltip from '@corvu/tooltip' // 'corvu/tooltip'
// or
// import { Root, Trigger, ... } from '@corvu/tooltip'
Anatomy Section titled Anatomy
<Tooltip>
<Tooltip.Anchor>
<Tooltip.Trigger />
</Tooltip.Anchor>
<Tooltip.Portal>
<Tooltip.Content>
<Tooltip.Arrow />
</Tooltip.Content>
</Tooltip.Portal>
</Tooltip>
The anchor component can optionally be used to make the tooltip anchor itself to another element than the trigger.
Floating UI Section titled Floating UI
The initial placement of the tooltip can be configured with the placement
property on the Root
component. Refer to the Floating UI placement option to see all available placements.
You can configure the positioning strategy with the strategy
property on the Root
component. Valid options are absolute
or fixed
. In most cases, it’s recommended to leave this property at the default setting absolute
, as this requires the browser to do the least work when updating the position.
FloatingOptions Section titled FloatingOptions
Middlewares can be configured with the floatingOptions
property on the Root
component. Check out the FloatingOptions
type in the API Reference.
If you want to enable a middleware with default options, you can pass true
as the value.
The option types are directly taken from the Floating UI middlewares. Check out Floating UI’s middleware documentation.
FloatingState Section titled FloatingState
The tooltip also provides a you with a floatingState
property that contains the current state of the tooltip. You can use this property to override a specific behavior according to your needs. Check out the FloatingState
type in the API Reference.
Accessibility Section titled Accessibility
Adheres to the Tooltip WAI-ARIA design pattern.
Keyboard navigation Section titled Keyboard navigation
Key | Behavior |
---|---|
Tab | Opens/closes the tooltip without delay. |
Space | Closes the tooltip without delay. |
Enter | Closes the tooltip without delay. |
Escape | Closes the tooltip without delay. |
API reference Section titled API reference
Context wrapper for the tooltip. Is required for every tooltip you create.
Props
Property | Default | Type/Description |
---|---|---|
open | - | boolean Whether the tooltip is open. |
onOpenChange | - | (open: boolean) => void Callback fired when the open state changes. |
initialOpen | false | boolean Whether the tooltip is open initially. |
placement | 'bottom' | Placement The initial placement of the tooltip. |
strategy | 'absolute' | Strategy The strategy to use when positioning the tooltip. |
floatingOptions | { flip: true, shift: true } | FloatingOptions | null Floating options of the tooltip. |
openDelay | 500 | number The delay in milliseconds before the tooltip opens after the mouse pointer is moved over the trigger. |
closeDelay | 0 | number The delay in milliseconds before the tooltip closes after the mouse pointer leaves. |
skipDelayDuration | 0 | number The duration in milliseconds that the tooltip should ignore the openDelay when the mouse pointer leaves and re-enters. |
hoverableContent | true | boolean Whether the tooltip content should be hoverable. |
group | - | 'true' | string Optionally add this tooltip to a group. With the same group property will close when another tooltip in the same group opens. |
openOnFocus | true | boolean Whether the tooltip should open when the trigger is focused. |
onFocus | - | (event: FocusEvent) => void Callback fired when the trigger is focused and openOnFocus is true . Can be prevented by calling event.preventDefault . |
onBlur | - | (event: FocusEvent) => void Callback fired when the trigger is blurred and openOnFocus is true . Can be prevented by calling event.preventDefault . |
openOnHover | true | boolean Whether the tooltip should open when the mouse pointer is moved over the trigger. |
onHover | - | (event: MouseEvent) => void Callback fired when the mouse pointer is moved over the trigger and openOnHover is true . Can be prevented by calling event.preventDefault . |
onLeave | - | (event: MouseEvent) => void Callback fired when the mouse pointer leaves the tooltip and openOnHover is true . Can be prevented by calling event.preventDefault . |
closeOnEscapeKeyDown | true | boolean Whether the tooltip should close when the user presses the Escape key. |
onEscapeKeyDown | - | (event: KeyboardEvent) => void Callback fired when the user presses the Escape key. Can be prevented by calling event.preventDefault . |
closeOnPointerDown | true | boolean Whether the tooltip should close when the user presses on the trigger. |
onPointerDown | - | (event: MouseEvent) => void Callback fired when the user presses on the trigger and closeOnPointerDown is true . Can be prevented by calling event.preventDefault . |
closeOnScroll | true | boolean Whether the tooltip should close when the user scrolls. |
onScroll | - | (event: Event) => void Callback fired when the user scrolls and the tooltip is about to close. Can be prevented by calling event.preventDefault . |
tooltipId | createUniqueId() | string The id attribute of the tooltip element. |
contextId | - | string The id of the tooltip context. Useful if you have nested tooltips and want to create components that belong to a tooltip higher up in the tree. |
Anchor element to override the floating reference.
Props
Property | Default | Type/Description |
---|---|---|
as | div | ValidComponent Component to render the dynamic component as. |
contextId | - | string The id of the tooltip context to use. |
Data attributes
Data attributes present on <Anchor />
components.
Property | Description |
---|---|
data-corvu-tooltip-anchor | Present on every tooltip anchor element. |
Button that opens the tooltip when focused or hovered.
Props
Property | Default | Type/Description |
---|---|---|
as | button | ValidComponent Component to render the dynamic component as. |
contextId | - | string The id of the tooltip context to use. |
Data attributes
Data attributes present on <Trigger />
components.
Property | Description |
---|---|
data-corvu-tooltip-trigger | Present on every tooltip trigger element. |
data-open | Present when the tooltip is open. |
data-closed | Present when the tooltip is closed. |
data-placement | Current placement of the tooltip. Only present when the tooltip is open. |
Portals its children at the end of the body element to ensure that the tooltip always rendered on top.
Props
Property | Default | Type/Description |
---|---|---|
forceMount | false | boolean Whether the tooltip portal should be forced to render. Useful when using third-party animation libraries. |
contextId | - | string The id of the tooltip context to use. |
Content of the tooltip. Can be animated.
Props
Property | Default | Type/Description |
---|---|---|
forceMount | false | boolean Whether the tooltip content should be forced to render. Useful when using third-party animation libraries. |
as | div | ValidComponent Component to render the dynamic component as. |
contextId | - | string The id of the tooltip context to use. |
Data attributes
Data attributes present on <Content />
components.
Property | Description |
---|---|
data-corvu-tooltip-content | Present on every tooltip content element. |
data-open | Present when the tooltip is open. |
data-closed | Present when the tooltip is closed. |
data-placement | Current placement of the tooltip. |
Arrow element that automatically points towards the floating reference. Comes with a default arrow svg, but can be overridden by providing your own as the children.
Props
Property | Default | Type/Description |
---|---|---|
size | 16 | number Size of the arrow in px. |
as | div | ValidComponent Component to render the dynamic component as. |
contextId | - | string The id of the tooltip context to use. |
Data attributes
Data attributes present on <Arrow />
components.
Property | Description |
---|---|
data-corvu-tooltip-arrow | Present on every tooltip arrow element. |
Context which exposes various properties to interact with the tooltip. Optionally provide a contextId to access a keyed context.
Returns
Property | Type/Description |
---|---|
open | Accessor<boolean> Whether the tooltip is open. |
setOpen | Setter<boolean> Change the open state of the tooltip. |
placement | Accessor<Placement> The initial placement of the tooltip. |
strategy | Accessor<Strategy> The strategy to use when positioning the tooltip. |
floatingOptions | Accessor<FloatingOptions | null> Floating options of the tooltip. |
floatingState | Accessor<FloatingState> The current floating state of the tooltip. |
openDelay | Accessor<number> The delay in milliseconds before the tooltip opens after the mouse pointer is moved over the trigger. |
closeDelay | Accessor<number> The delay in milliseconds before the tooltip closes after the mouse pointer leaves. |
skipDelayDuration | Accessor<number> The duration in milliseconds that the tooltip should ignore the openDelay when the mouse pointer leaves and re-enters. |
hoverableContent | Accessor<boolean> Whether the tooltip content should be hoverable. |
group | Accessor<'true' | string | null> The group this tooltip is in. |
openOnFocus | Accessor<boolean> Whether the tooltip should open when the trigger is focused. |
openOnHover | Accessor<boolean> Whether the tooltip should open when the mouse pointer is moved over the trigger. |
closeOnEscapeKeyDown | Accessor<boolean> Whether the tooltip should close when the user presses the Escape key. |
closeOnPointerDown | Accessor<boolean> Whether the tooltip should close when the user presses on the trigger. |
contentPresent | Accessor<boolean> Whether the tooltip content is present in the DOM. |
contentRef | Accessor<HTMLElement | null> The tooltip content element. |
tooltipId | Accessor<string> The id of the tooltip element. |
Props that are passed to the Root component children callback.
Props
Property | Type/Description |
---|---|
open | boolean Whether the tooltip is open. |
setOpen | Setter<boolean> Change the open state of the tooltip. |
placement | Placement The initial placement of the tooltip. |
strategy | Strategy The strategy to use when positioning the tooltip. |
floatingOptions | FloatingOptions | null Floating options of the tooltip. |
floatingState | FloatingState The current floating state of the tooltip. |
openDelay | number The delay in milliseconds before the tooltip opens after the mouse pointer is moved over the trigger. |
closeDelay | number The delay in milliseconds before the tooltip closes after the mouse pointer leaves. |
skipDelayDuration | number The duration in milliseconds that the tooltip should ignore the openDelay when the mouse pointer leaves and re-enters. |
hoverableContent | boolean Whether the tooltip content should be hoverable. |
group | 'true' | string | null The group this tooltip is in. |
openOnFocus | boolean Whether the tooltip should open when the trigger is focused. |
openOnHover | boolean Whether the tooltip should open when the mouse pointer is moved over the trigger. |
closeOnEscapeKeyDown | boolean Whether the tooltip should close when the user presses the Escape key. |
closeOnPointerDown | boolean Whether the tooltip should close when the user presses on the trigger. |
contentPresent | boolean Whether the tooltip content is present in the DOM. |
contentRef | HTMLElement | null The tooltip content element. |
tooltipId | string The id of the tooltip element. |
type FloatingOptions = {
arrow: Padding,
autoPlacement: boolean | AutoPlacementOptions,
flip: boolean | FlipOptions,
hide: boolean | HideOptions,
inline: boolean | InlineOptions,
offset: OffsetOptions,
shift: boolean | ShiftOptions,
size: DetectOverflowOptions & {
fitViewPort: boolean,
matchSize: boolean,
},
}
type FloatingState = {
arrowX: number | null,
arrowY: number | null,
height: number | null,
maxHeight: number | null,
maxWidth: number | null,
placement: Placement,
width: number | null,
x: number,
y: number,
}
Developed and designed by Jasmin