Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s
126 lines
4.8 KiB
Plaintext
126 lines
4.8 KiB
Plaintext
---
|
|
title: Tooltip
|
|
description: Show supplementary information when a trigger is hovered or focused.
|
|
---
|
|
|
|
import { StoryEmbed } from '/snippets/ui/StoryEmbed.mdx';
|
|
|
|
import TooltipReference from '/snippets/ui/generated/surfaces/tooltip.mdx';
|
|
|
|
Use `Tooltip` for a short explanation of a control or truncated text. Keep essential information visible, give controls an accessible name, and use [Popover](/ui/primitives/surfaces/popover) when the content contains links, buttons, or other controls.
|
|
|
|
<StoryEmbed storyId="ui-surfaces-tooltip--default" title="Tooltip example" />
|
|
|
|
## Single trigger
|
|
|
|
```tsx
|
|
import { Button } from 'twenty-ui/primitives/input';
|
|
import { Tooltip } from 'twenty-ui/primitives/surfaces';
|
|
|
|
export const ExportHelp = () => (
|
|
<Tooltip content="Download the visible records as a CSV file" side="top">
|
|
<span>
|
|
<Button>Export records</Button>
|
|
</span>
|
|
</Tooltip>
|
|
);
|
|
```
|
|
|
|
The convenience component accepts one trigger element as `children`. Native elements receive the trigger attributes, event handlers, and ref directly. Custom trigger components must forward all of them. A wrapper element also works with a component that does not forward every trigger prop.
|
|
|
|
Hover opens the tooltip after `delay` milliseconds, which defaults to `600`. Keyboard focus opens it immediately. `closeDelay` defaults to `0`; hovering over the popup keeps it open unless `disableHoverablePopup` is set. Escape dismisses it.
|
|
|
|
## Controlled state
|
|
|
|
Use `open` and `onOpenChange` together when the application owns visibility. Use `defaultOpen` only to set the initial visibility of an uncontrolled tooltip.
|
|
|
|
```tsx
|
|
import { useState } from 'react';
|
|
import { Button } from 'twenty-ui/primitives/input';
|
|
import { Tooltip } from 'twenty-ui/primitives/surfaces';
|
|
|
|
export const ControlledExportHelp = () => {
|
|
const [open, setOpen] = useState(false);
|
|
|
|
return (
|
|
<Tooltip
|
|
content="Download the visible records as a CSV file"
|
|
open={open}
|
|
onOpenChange={setOpen}
|
|
delay={300}
|
|
>
|
|
<span>
|
|
<Button>Export records</Button>
|
|
</span>
|
|
</Tooltip>
|
|
);
|
|
};
|
|
```
|
|
|
|
## Rich content and composition
|
|
|
|
`Tooltip.Content` provides a title, optional description, and optional leading icon. Use it as `content` or inside `Tooltip.Popup`.
|
|
|
|
```tsx
|
|
import { IconInfoCircle } from 'twenty-ui/icon';
|
|
import { Button } from 'twenty-ui/primitives/input';
|
|
import { Tooltip } from 'twenty-ui/primitives/surfaces';
|
|
|
|
export const ExportDetails = () => (
|
|
<Tooltip.Root>
|
|
<Tooltip.Trigger render={<span />}>
|
|
<Button>Export records</Button>
|
|
</Tooltip.Trigger>
|
|
<Tooltip.Popup side="right" align="start" arrow>
|
|
<Tooltip.Content
|
|
startIcon={<IconInfoCircle />}
|
|
description="Only the records matching your current filters are included."
|
|
>
|
|
Export visible records
|
|
</Tooltip.Content>
|
|
</Tooltip.Popup>
|
|
</Tooltip.Root>
|
|
);
|
|
```
|
|
|
|
| Part | Purpose |
|
|
| ---------- | ------------------------------------------------------------- |
|
|
| `Root` | Coordinates visibility and trigger interactions. |
|
|
| `Trigger` | Renders the element that opens the tooltip on hover or focus. |
|
|
| `Popup` | Renders positioned content in a portal. |
|
|
| `Content` | Styles primary text, a description, and an icon. |
|
|
| `Provider` | Coordinates opening delays across a group of tooltips. |
|
|
|
|
`Tooltip.createHandle()` connects detached triggers to a shared `Root` through their `handle` prop. Keep each popup's content supplementary even when several triggers share it.
|
|
|
|
## Disabled controls
|
|
|
|
Native disabled buttons cannot receive keyboard focus. Wrap one in a focusable trigger so users can discover why the action is unavailable.
|
|
|
|
```tsx
|
|
import { Button } from 'twenty-ui/primitives/input';
|
|
import { Tooltip } from 'twenty-ui/primitives/surfaces';
|
|
|
|
export const UnavailableExport = () => (
|
|
<Tooltip content="Select at least one record to export">
|
|
<span tabIndex={0} aria-label="Export records unavailable">
|
|
<Button disabled>Export records</Button>
|
|
</span>
|
|
</Tooltip>
|
|
);
|
|
```
|
|
|
|
Setting `disabled` on `Tooltip` suppresses the tooltip itself. It does not disable the control.
|
|
|
|
## Placement and overflowing text
|
|
|
|
The popup defaults to `side="top"`, `align="center"`, `sideOffset={10}`, and a maximum width of `300` pixels. Placement adjusts to available space. Use `arrow` for an arrow and `container` to override the theme's portal destination; see [theming](/ui/theming).
|
|
|
|
Use `OverflowingTextWithTooltip` when a text label should show its full value only when truncated. Its existing `text`, `tooltipContent`, and `tooltipPlace` props remain available.
|
|
|
|
## Props
|
|
|
|
The reference is generated from the public component types. Native popup attributes and event handlers are also accepted.
|
|
|
|
<TooltipReference />
|