---
title: "टूलटिप"
description: "जब व्यक्ति किसी एलिमेंट पर पॉइंटर ले जाता है, उसे कीबोर्ड से फ़ोकस करता है या देर तक दबाता है, तब उसे कुछ शब्दों में बताता है, बिना फ़ोकस लिए और बिना किसी चीज़ को रोके।"
url: "https://tanrei.chnotchy.com/hi/components/tooltip/"
last_updated: 2026-10-23T21:17:12.000Z
---

# टूलटिप

> जब व्यक्ति किसी एलिमेंट पर पॉइंटर ले जाता है, उसे कीबोर्ड से फ़ोकस करता है या देर तक दबाता है, तब उसे कुछ शब्दों में बताता है, बिना फ़ोकस लिए और बिना किसी चीज़ को रोके।

## अवलोकन

### इस्तेमाल

ऐंकर आपका अपना एलिमेंट है: सिर्फ़ आइकन वाला बटन, कटा हुआ लेबल, चार्ट का कोई निशान। टूलटिप उसमें एक विवरण जोड़ता है और उसकी कोई और चीज़ नहीं बदलता। वेब, Compose, Flutter और React Native पर वह ऐंकर को अपने भीतर लपेटता है, और SwiftUI पर वह ऐंकर पर लगा एक मॉडिफ़ायर है।

टूलटिप होवर, कीबोर्ड फ़ोकस और देर तक दबाने पर ख़ुद खुलता और बंद होता है, और इसकी सूचना `toggle` से देता है। `open` आप सिर्फ़ तब सेट करते हैं जब उसे अपनी ओर से दिखाना हो, जैसे पहली बार के इस्तेमाल का संकेत। उसे सेट करने से कुछ एमिट नहीं होता, और टूलटिप उसके बाद भी ख़ुद खुलता और बंद होता रहता है।

`describes` (डिफ़ॉल्ट रूप से true) टेक्स्ट को ऐंकर का एक्सेसिबल विवरण बनाता है। जब टेक्स्ट ऐंकर का अपना नाम दोहराता हो, जैसा उस आइकन बटन के साथ होता है जिसका टूलटिप उसका लेबल दिखाता है, तब इसे false करें, ताकि स्क्रीन रीडर वही शब्द दो बार न पढ़ें।

Web और React के उदाहरण मौजूदा स्पेक दिखाते हैं। SwiftUI, Compose, Flutter और React Native पीछे हैं: वे अभी टूलटिप का पिछला संशोधन देते हैं, जिसमें बीच में रखे चार स्थान हैं, हर टूलटिप की अपनी देरी, ऑफ़सेट, तीर, दूसरा रूप या शॉर्टकट नहीं हैं, और जो बिना बढ़े फ़ेड होता है। जब तक वे बराबरी पर नहीं आते, उनके उदाहरण वही संशोधन दिखाते हैं।

**Web**

```html
<!-- टूलटिप अपने ऐंकर को लपेटता है। no-describe का मतलब है describes को false करना: टेक्स्ट लेबल को दोहराता है। -->
<tanrei-tooltip text="ट्रैश में डालें" no-describe>
  <tanrei-button variant="text" label="ट्रैश में डालें"><span slot="icon">delete</span></tanrei-button>
</tanrei-tooltip>

<!-- एक घना टूलबार, जिसे अपने नाम जल्दी चाहिए। देरी मिलीसेकंड में होती है। -->
<tanrei-tooltip text="बोल्ड" show-delay="150" no-describe>
  <tanrei-button variant="text" label="बोल्ड"><span slot="icon">format_bold</span></tanrei-button>
</tanrei-tooltip>

<!-- कमांड के नाम के बाद उसकी कुंजियाँ। सहायक तकनीक के लिए उन्हें ऐंकर रखता है। -->
<tanrei-tooltip text="बोल्ड" shortcut="mod+b" no-describe>
  <tanrei-button variant="text" label="बोल्ड"><span slot="icon">format_bold</span></tanrei-button>
</tanrei-tooltip>

<!-- कंट्रोल के नीचे, उसके शुरुआती किनारे की सीध में, तीर के साथ, इनवर्स की जगह सरफ़ेस पर। -->
<tanrei-tooltip text="तारीख़ या मालिक के अनुसार फ़िल्टर करें" placement="bottom-start" arrow inverse="false">
  <tanrei-button variant="text" label="फ़िल्टर"><span slot="icon">filter_list</span></tanrei-button>
</tanrei-tooltip>

<tanrei-tooltip id="storage" variant="rich" headline="स्टोरेज" placement="bottom"
                text="ट्रैश की फ़ाइलें हटाए जाने तक आपके स्टोरेज में गिनी जाती हैं।">
  <tanrei-button variant="text" label="स्टोरेज के बारे में"><span slot="icon">info</span></tanrei-button>
</tanrei-tooltip>

<script type="module">
  import '@tanrei/web/components/tooltip';
  const storage = document.querySelector('#storage');
  // पहली बार के इस्तेमाल का संकेत। open सेट करने से कुछ एमिट नहीं होता।
  storage.open = true;
  // toggle वह बताता है जो टूलटिप ने ख़ुद किया: होवर, फ़ोकस, देर तक दबाना, Escape, टाइमआउट, कोई दूसरा टूलटिप।
  storage.addEventListener('toggle', (e) => console.log(e.detail.open));
</script>
```

**React**

```tsx
import { Button, Tooltip } from '@tanrei/react';

<Tooltip text="ट्रैश में डालें" describes={false}>
  <Button variant="text" label="ट्रैश में डालें" onClick={trash}><span slot="icon">delete</span></Button>
</Tooltip>
{/* कमांड के नाम के बाद उसकी कुंजियाँ: हर स्ट्रिंग में एक कॉर्ड। */}
<Tooltip text="बोल्ड" shortcut={['mod+b']} describes={false}>
  <Button variant="text" label="बोल्ड" onClick={bold}><span slot="icon">format_bold</span></Button>
</Tooltip>
{/* कंट्रोल के नीचे, उसके शुरुआती किनारे की सीध में, तीर के साथ, इनवर्स की जगह सरफ़ेस पर। */}
<Tooltip text="तारीख़ या मालिक के अनुसार फ़िल्टर करें" placement="bottom-start" arrow inverse={false}>
  <Button variant="text" label="फ़िल्टर" onClick={filter}><span slot="icon">filter_list</span></Button>
</Tooltip>
<Tooltip
  variant="rich"
  headline="स्टोरेज"
  text="ट्रैश की फ़ाइलें हटाए जाने तक आपके स्टोरेज में गिनी जाती हैं।"
  placement="bottom"
  touchTimeout={4000} // देर तक दबाने के बाद कुछ वाक्य पढ़ने में ज़्यादा समय लगता है
  onToggle={(e) => log(e.detail.open)}
>
  <Button variant="text" label="स्टोरेज के बारे में"><span slot="icon">info</span></Button>
</Tooltip>
```

**SwiftUI**

```swift
import Tanrei

// ऐंकर पर लगा एक मॉडिफ़ायर। उसके ऊपर का .tanreiTheme(_:) वह लेयर देता है जिसमें टूलटिप बनता है।
// विवरण ऐंकर का accessibilityHint बन जाता है।
TanreiIconButton("ट्रैश में डालें", action: trash) { Image(systemName: "trash") }
    .tanreiTooltip("ट्रैश में डालें", describes: false)

// isPresented ही open है; टूलटिप जब ख़ुद खुलता या बंद होता है तो इसे लिखता है।
TanreiIconButton("स्टोरेज के बारे में", action: {}) { Image(systemName: "info.circle") }
    .tanreiTooltip("ट्रैश की फ़ाइलें हटाए जाने तक आपके स्टोरेज में गिनी जाती हैं।",
                   title: "स्टोरेज", variant: .rich, placement: .bottom, isPresented: $showHint)
```

**Compose**

```kotlin
import io.github.chnotchy.tanrei.components.TanreiIconButton
import io.github.chnotchy.tanrei.components.TanreiTooltip
import io.github.chnotchy.tanrei.components.TanreiTooltipPlacement
import io.github.chnotchy.tanrei.components.TanreiTooltipVariant
import io.github.chnotchy.tanrei.components.rememberTanreiTooltipState
import io.github.chnotchy.tanrei.primitives.TanreiText

// Material के TooltipBox की तरह: टूलटिप अपने ऐंकर को लपेटता है।
TanreiTooltip(text = "ट्रैश में डालें", describes = false) {
    TanreiIconButton(onClick = ::trash, contentDescription = "ट्रैश में डालें") { TanreiText("delete") }
}

// स्टेट ही open है। onToggle वह सुनता है जो टूलटिप ख़ुद करता है; show() और dismiss() कुछ एमिट नहीं करते।
val hint = rememberTanreiTooltipState(onToggle = { open -> log(open) })
TanreiTooltip(
    text = "ट्रैश की फ़ाइलें हटाए जाने तक आपके स्टोरेज में गिनी जाती हैं।",
    variant = TanreiTooltipVariant.Rich,
    title = "स्टोरेज",
    placement = TanreiTooltipPlacement.Bottom,
    state = hint,
) {
    TanreiIconButton(onClick = {}, contentDescription = "स्टोरेज के बारे में") { TanreiText("info") }
}
LaunchedEffect(Unit) { hint.show() } // पहली बार के इस्तेमाल का संकेत
```

**Flutter**

```dart
import 'package:tanrei/tanrei.dart';

// show() और hide() open सेट करते हैं, और किसी को सूचित नहीं करते। लिसनर वह सुनते हैं जो टूलटिप ख़ुद करता है।
final TanreiTooltipController hint = TanreiTooltipController();
hint.addListener(() => log(hint.isOpen));

// Flutter के Tooltip की तरह: message टेक्स्ट है, और excludeFromSemantics उलटा किया हुआ describes है।
TanreiTooltip(
  message: 'ट्रैश में डालें',
  excludeFromSemantics: true, // टेक्स्ट बटन का अपना नाम दोहराता है
  child: TanreiIconButton(onPressed: trash, icon: const Icon(AppSymbols.delete), semanticLabel: 'ट्रैश में डालें'),
);
TanreiTooltip(
  variant: TanreiTooltipVariant.rich,
  title: 'स्टोरेज',
  message: 'ट्रैश की फ़ाइलें हटाए जाने तक आपके स्टोरेज में गिनी जाती हैं।',
  placement: TanreiTooltipPlacement.bottom,
  controller: hint, // पहली बार के इस्तेमाल के संकेत के लिए hint.show()
  child: TanreiIconButton(onPressed: info, icon: const Icon(AppSymbols.info), semanticLabel: 'स्टोरेज के बारे में'),
);
```

**React Native**

```tsx
import { IconButton, Tooltip } from '@tanrei/react-native';

// ऐंकर एक ही चाइल्ड है, जो Pressable की प्रॉपर्टी लेता है। टूलटिप अपने हैंडलर जोड़ता है, और पहले ऐंकर के अपने हैंडलर कॉल करता है।
<Tooltip text="ट्रैश में डालें" describes={false}>
  <IconButton accessibilityLabel="ट्रैश में डालें" onPress={trash}>delete</IconButton>
</Tooltip>

// open इसे आपके कोड से दिखाता है और कुछ एमिट नहीं करता; onOpenChange वह सुनता है जो यह ख़ुद करता है।
<Tooltip
  variant="rich"
  headline="स्टोरेज"
  text="ट्रैश की फ़ाइलें हटाए जाने तक आपके स्टोरेज में गिनी जाती हैं।"
  placement="bottom"
  open={showHint}
  onOpenChange={setShowHint}
>
  <IconButton accessibilityLabel="स्टोरेज के बारे में">info</IconButton>
</Tooltip>
```

## स्पेक

- Category: Communication
- Level: base
- Listing: default
- Page: https://tanrei.chnotchy.com/components/tooltip/
- Spec: https://github.com/chnotchy/tanrei/blob/main/specs/tooltip.spec.json

### Availability

| Design system | Has it | Notes |
| --- | --- | --- |
| Tanrei (`tanrei`) | Yes | — |
| Cupertino (Apple HIG-inspired) (`cupertino`) | Yes | — |
| M3 Expressive-like (Material 3 Expressive-inspired) (`m3-expressive-like`) | Yes | — |
| M3-like (Material 3-inspired) (`m3-like`) | Yes | — |

### Platforms

- Web: the element `<tanrei-tooltip>`, registered by importing `@tanrei/web` (or only its own module, `@tanrei/web/components/tooltip`).
- React: `Tooltip` from `@tanrei/react`.

| Platform | Name | Status |
| --- | --- | --- |
| Web | `tanrei-tooltip` | lagging |
| SwiftUI | `tanreiTooltip` | lagging |
| Jetpack Compose | `TanreiTooltip` | lagging |
| Flutter | `TanreiTooltip` | lagging |
| React Native | `Tooltip` | lagging |

Names a platform gives in its own idiom:

| Spec | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
| --- | --- | --- | --- | --- | --- |
| `text` (prop) | `text` | `text` | `text` | `message` | `text` |
| `title` (prop) | `headline` | `title` | `title` | `title` | `title` |
| `describes` (prop) | `describes` | `describes` | `describes` | `excludeFromSemantics` | `describes` |
| `open` (prop) | `open` | `isPresented` | `state` | `controller` | `open` |
| `showDelay` (prop) | `showDelay` | `showDelay` | `showDelayMillis` | `waitDuration` | `showDelay` |
| `hideDelay` (prop) | `hideDelay` | `hideDelay` | `hideDelayMillis` | `exitDuration` | `hideDelay` |
| `touchTimeout` (prop) | `touchTimeout` | `touchTimeout` | `touchTimeoutMillis` | `showDuration` | `touchTimeout` |
| `toggle` (event) | `toggle` | `isPresented` | `state` | `controller` | `onOpenChange` |

Statuses: `planned` — In the inventory. Nothing shippable exists yet. `lagging` — An implementation of an earlier spec exists; it has not caught up with the current one. `alpha` — Implemented with tests. The API may still change. `beta` — Feature complete and at parity. Only fixes are expected. `stable` — Covered by semantic versioning. `deprecated` — Still shipped; scheduled for removal.

### Anatomy

- `anchor`: The element the tooltip describes: the product's own (an icon-only Button, a truncated label, a chart mark). The tooltip adds a description to it and changes nothing else about it.
- `container`: The surface that holds the text, placed on one side of the anchor and aligned along it.
- `arrow` (optional): A triangle on the container's edge that faces the anchor, pointing at it; one shape with the container.
- `title` (optional): A short heading above the supporting text. Rich tooltips only.
- `supporting-text`: The description. A plain tooltip holds nothing else.
- `shortcut` (optional): The keys that perform the anchor's command, after the text. Plain tooltips only.

### Props

| Prop | Type | Default | Web attribute | Description |
| --- | --- | --- | --- | --- |
| `variant` | `enum`: `plain`, `rich` | `"plain"` | `variant` | Plain is one short phrase, by default on the inverse surface, for naming what an icon does. Rich is an optional title and a few sentences, by default on a raised surface, for explaining a term or a setting. A structural choice drawn by code, not a token axis: a design system cannot add a form by values. |
| `text` | `string` | `""` | `text` | The description. Required. |
| `title` | `string` | `""` | — | A heading for a rich tooltip. Ignored by a plain one. |
| `shortcut` | `strings` | `` | `shortcut` | The keyboard shortcut of the anchor's command, in the keyboard shortcut component's key names: one chord per string, pressed in order (["mod+b"]). A plain tooltip draws it after the text for the keyboard the person uses and exposes it as the anchor's keyboard shortcut (TIP-27); a rich one ignores it. It does not make the keys work; the product binds them. |
| `placement` | `enum`: `top`, `top-start`, `top-end`, `bottom`, `bottom-start`, `bottom-end`, `start`, `start-top`, `start-bottom`, `end`, `end-top`, `end-bottom`, `auto` | `"top"` | `placement` | Where the tooltip prefers to stand: a side of the anchor, and how it lines up along that side (TIP-22). top and bottom centre it above or below the anchor; with -start or -end its start or end edge meets the anchor's. start and end centre it beside the anchor; with -top or -bottom its top or bottom edge meets the anchor's. auto takes the first side with room (TIP-23). Start and end follow the layout direction. The tooltip flips to the opposite side when the preferred one has no room, keeping the alignment (TIP-9). |
| `offset` | `number` | — | `offset` | The distance between the anchor's edge and the tooltip, in the platform's layout units; 0 lets them touch. Null takes comp.tooltip.offset, the system's answer for every tooltip. Set it only where one anchor's box is not what the eye takes for its edge (a control with a large invisible hit area, a mark of a chart). |
| `crossOffset` | `number` | `0` | `cross-offset` | How far the tooltip moves along the side it stands on, in the platform's layout units, from where placement puts it: positive towards the end for a tooltip above or below, towards the bottom for one beside. For lining an aligned tooltip up with what is drawn inside the anchor rather than with the anchor's box. It never moves the tooltip off the anchor's side (TIP-24). |
| `arrow` | `boolean` | — | `arrow` | Whether the tooltip draws an arrow that points at the anchor. Null, the default, takes comp.tooltip.arrow.visible, the system's choice, which is off in the default system (TIP-25). |
| `inverse` | `boolean` | — | `inverse` | Whether this tooltip is drawn inverse: in the opposite scheme's colors, so that it stands apart from whatever it lands on. False draws it on a surface of the scheme. Null, the default, takes its form's choice: comp.tooltip.plain.container.inverse (on in the default system) or comp.tooltip.rich.container.inverse (off). It changes colors and elevation only (TIP-26). |
| `describes` | `boolean` | `true` | `no-describe` (turns it off) | Whether assistive technology reads the text as the anchor's description. Set it to false when the text repeats the anchor's own accessible name (an icon-only Button whose tooltip shows its label), so that it is not read twice. |
| `open` | `boolean` | `false` | `open` | Whether the tooltip is showing. The tooltip opens and closes itself on hover, focus and long-press and reports it (toggle). A product sets it to show a tooltip on its own (a first-run hint); a snapshot harness sets it to draw a fixture. |
| `showDelay` | `number` | — | `show-delay` | How long, in milliseconds, a fine pointer rests on the anchor before this tooltip opens; 0 opens it at once. Null takes comp.tooltip.motion.show-delay, the system's answer for every tooltip. Set it only where one tooltip needs another pace than the rest (a dense toolbar that wants its names sooner, a chart whose marks the pointer sweeps across and should not flash). It applies to hover alone: keyboard focus still opens at once. |
| `hideDelay` | `number` | — | `hide-delay` | How long, in milliseconds, this tooltip waits after the pointer has left the anchor, the gap and the tooltip before it closes; 0 closes it at once. Null takes comp.tooltip.motion.hide-delay. The tooltip stays hoverable at any value, 0 included, because the gap between the anchor and the tooltip counts as hover (TIP-1). |
| `touchTimeout` | `number` | — | `touch-timeout` | How long, in milliseconds, a tooltip opened by a long-press stays after the finger lifts; 0 closes it as the finger lifts, so it shows for as long as the press lasts. Null takes comp.tooltip.timeout.touch. Set it only where one tooltip needs more or less reading time on touch than the rest (a rich tooltip of a few sentences, a one-word name). |

### Events

| Event | Description |
| --- | --- |
| `toggle` | The tooltip opened or closed by itself (hover, focus, long-press, Escape, the touch timeout, another tooltip opening); carries the new open value. |

### Slots

| Slot | Description |
| --- | --- |
| `default` | The anchor. |

### States

`enabled`

### Accessibility

- Role: `tooltip`
- Labeling: The tooltip names nothing. The anchor keeps its own accessible name and role; while describes is true the text (after the title, for a rich tooltip) is the anchor's description, available whether or not the tooltip is showing. An icon-only Button's label is its name (BTN-16) and is never replaced by a tooltip: a tooltip that shows the same words sets describes to false. A shortcut is the anchor's keyboard shortcut where the platform has that property, and the end of its description otherwise (TIP-27); the drawn keys and the arrow are hidden.
- Minimum target size: yes

| Keys | Action |
| --- | --- |
| Tab | Moving focus to the anchor opens its tooltip at once; moving focus away closes it. The tooltip itself is never a tab stop. |
| Escape | Closes an open tooltip without moving focus, and goes no further (an enclosing dialog stays open). |

- The tooltip takes no input, so it has no target of its own: minimumTarget applies to the anchor, which keeps its own hit area.
- WCAG 1.4.13 (content on hover or focus): the tooltip can be dismissed without moving the pointer or focus (Escape, TIP-4), can be hovered (TIP-1: the gap between the anchor and the tooltip counts as hover — at any offset, with or without an arrow — so this holds at any hideDelay, 0 included), and stays until hover or focus ends or it is dismissed (TIP-5). Placement, the arrow and the motion change none of the three: a tooltip that flips, shifts or follows its anchor is the same open tooltip, and the gap is measured to wherever it stands.
- A tooltip is invisible to touch users until they long-press, and to screen-reader users it is only a description. Nothing a person needs to finish a task may live only in a tooltip. A note that needs a link or a button is not a tooltip; that form belongs to a separate non-modal popover component.
- Do not put a tooltip on a disabled anchor to explain why it is disabled: a disabled control cannot be focused, and on the web it may receive no pointer events. Put the reason in visible text.
- Web: the description reaches the anchor's focusable element as aria-description, because aria-describedby cannot point across shadow roots. The anchor is the first focusable element slotted into the tooltip; a Tanrei component forwards aria-description from its host to the native element in its shadow root. The drawn tooltip has role tooltip and aria-hidden while describes carries the text.
- The motion is short, small and never the only sign of anything; where motion is reduced nothing grows or travels (TIP-15). A tooltip that is leaving is already closed for input (TIP-29), so nothing invisible is ever in the pointer's way.
- The inverse look and the surface look are two looks of one thing, not two meanings: neither says that a tooltip matters more. Choose by what the tooltip lands on.
- A shortcut in a tooltip is a reminder for people who see it. It must also work for those who do not: the product binds the keys, and the anchor carries the shortcut for assistive technology (TIP-27).

### Behaviour

Requirements in EARS form, each with its stable id.

- **TIP-1** WHEN a fine pointer enters the anchor and stays on it for the show delay (TIP-17) THE tooltip SHALL open; WHEN the pointer leaves the anchor THE tooltip SHALL stay open while the pointer crosses the gap to the tooltip or moves onto the tooltip itself, and SHALL close once the pointer has been off the anchor, the gap and the tooltip for the hide delay (TIP-17). The gap is the strip between the anchor's edge and the container — the offset deep (TIP-24), and comp.tooltip.arrow.height deeper while an arrow is drawn (TIP-25) — as wide as the container along that side; it counts for hover alone, is not drawn and takes no press.
- **TIP-2** WHEN the anchor receives keyboard focus THE tooltip SHALL open without delay, and WHEN the anchor loses focus THE tooltip SHALL close; focus gained by pointer or touch SHALL NOT open it.
- **TIP-3** WHEN the user long-presses the anchor by touch THE tooltip SHALL open without activating the anchor, and WHEN the finger lifts SHALL stay open for the touch timeout (TIP-17) and then close; a touch anywhere else SHALL close it sooner.
- **TIP-4** WHILE the tooltip is open, WHEN the user presses Escape THE tooltip SHALL close without moving focus and SHALL consume the key, so that it does not also close an enclosing dialog; it SHALL stay closed until the anchor is entered by the pointer or focused again.
- **TIP-5** WHILE the pointer is over the anchor or the tooltip, or the anchor has keyboard focus, THE tooltip SHALL stay open with no time limit, until Escape (TIP-4), an activation of the anchor (TIP-6) or another tooltip opening (TIP-8) closes it.
- **TIP-6** WHEN the anchor is activated (a click, a tap, Enter or Space) THE tooltip SHALL close, and SHALL NOT open again from the same hover until the pointer has left the anchor and entered it again.
- **TIP-7** WHEN the tooltip opens or closes by itself (TIP-1 to TIP-6, TIP-8) THE tooltip SHALL emit toggle with the new value; WHEN the product sets open THE tooltip SHALL show or hide accordingly without emitting toggle, and SHALL then keep following TIP-1 to TIP-6.
- **TIP-8** WHEN a tooltip opens while another tooltip is open THE other tooltip SHALL close at once, and the new one SHALL open without waiting for its show delay (TIP-17), because the person is already reading tooltips; at most one tooltip SHALL be open in a window.
- **TIP-9** THE tooltip SHALL place its container on the side of the anchor and with the alignment that placement names (TIP-22, TIP-23), the offset away from the anchor's edge and moved along the side by crossOffset (TIP-24), and SHALL keep it at least comp.tooltip.window-margin inside the window's safe area by these steps, in this order: WHEN the preferred side has no room for the container and the opposite side has, it SHALL flip to the opposite side, keeping the alignment; WHEN neither has room it SHALL use the one of the two with more room; it SHALL then shift along the side as far as the margin asks and no farther; and WHERE the container is still larger than the room on its side (a window smaller than the tooltip) it SHALL move the container back into the margin over the anchor, its top and start edges first, rather than leave the window. It SHALL follow the anchor when the anchor moves (scrolling, resizing, layout), taking these steps again from the side it is on, which it SHALL keep for as long as that side has room, so that a page that scrolls does not throw the tooltip from side to side; and it SHALL close WHEN the anchor is removed, hidden, scrolled out of the window, or scrolled out of sight inside a scrolling ancestor so that no part of it can be seen.
- **TIP-10** WHILE variant is plain THE tooltip SHALL draw text in comp.tooltip.plain.supporting-text.typescale and comp.tooltip.plain.supporting-text.color on a container of comp.tooltip.plain.container.color with comp.tooltip.plain.container.shape corners and comp.tooltip.plain.container.elevation — or, WHILE it is drawn on a surface, in the colors and the elevation TIP-26 names in their place — padded by comp.tooltip.plain.container.padding-inline and comp.tooltip.plain.container.padding-block, at least comp.tooltip.plain.container.min-height tall and at most comp.tooltip.plain.container.max-width wide, wrapping longer text onto further lines; it SHALL draw its shortcut as TIP-27 says and SHALL ignore title.
- **TIP-11** WHILE variant is rich THE tooltip SHALL draw title in comp.tooltip.rich.title.typescale and comp.tooltip.rich.title.color above text in comp.tooltip.rich.supporting-text.typescale and comp.tooltip.rich.supporting-text.color, comp.tooltip.rich.container.gap apart, on a container of comp.tooltip.rich.container.color with comp.tooltip.rich.container.shape corners and comp.tooltip.rich.container.elevation — or, WHILE it is drawn inverse, in the colors and the elevation TIP-26 names in their place — padded by comp.tooltip.rich.container.padding-inline and comp.tooltip.rich.container.padding-block and at most comp.tooltip.rich.container.max-width wide; WHILE title is empty it SHALL draw the supporting text alone. THE tooltip SHALL set the title's letter-spacing by the script of its text, as every title is set (PRS-20): no negative letter-spacing WHERE its language is Chinese, Japanese or Korean, and none WHERE its script joins its letters or stacks marks on them.
- **TIP-12** THE tooltip SHALL ease its container corners by sys.shape.corner-smoothing (0 is a quarter circle, 0.6 the iOS continuous corner; a platform with only the OS curve draws it for any amount above 0), SHALL grow with enlarged text without clipping it, and SHALL start-align its text by the layout direction.
- **TIP-13** THE tooltip SHALL NOT take focus, SHALL hold nothing focusable or pressable, SHALL NOT make anything inert or dimmed, and SHALL be drawn above every other layer of its window, including an open dialog and its scrim; a press on the tooltip SHALL close it and SHALL NOT reach what lies under it.
- **TIP-14** WHILE describes is true THE tooltip SHALL expose text — preceded by title for a rich tooltip — as the anchor's accessible description, whether or not the tooltip is open, and SHALL keep the drawn tooltip from being read a second time; WHILE describes is false it SHALL add nothing to the anchor's semantics. In both cases it SHALL NOT change the anchor's accessible name or role.
- **TIP-15** WHEN the tooltip opens THE tooltip SHALL appear as every surface appears: from sys.motion.appear.opacity, sys.motion.appear.scale, sys.motion.appear.distance toward its anchor and sys.motion.appear.blur to whole, grown from the middle of its edge that faces the anchor — from its own centre WHERE sys.motion.appear.origin is center, and WHILE it covers its anchor (TIP-9) — over comp.tooltip.motion.enter-duration with comp.tooltip.motion.enter-easing, so that it comes out of the anchor's side whichever side it is on; WHEN it closes THE tooltip SHALL take it back the same way to where it started, over comp.tooltip.motion.exit-duration with comp.tooltip.motion.exit-easing. WHERE sys.behavior.appearance is unfold the scale SHALL apply along the axis that leaves the anchor only. The motion SHALL be drawn only: the place TIP-9 gives, the gap of TIP-1 and the room the tooltip is measured for are those of the tooltip at rest. WHERE motion is reduced THE tooltip SHALL only fade in and out, over sys.motion.role.reduced, with no scale, distance or blur, or appear and disappear at once on a platform whose reduced-motion setting removes every animation (Android's). WHEN it is mounted with open true THE tooltip SHALL appear without its motion while the document has not yet been first painted, and with it when it is mounted after that. A tooltip that takes over from another SHALL NOT move at all (TIP-28).
- **TIP-16** WHILE text is empty THE tooltip SHALL NOT open and SHALL add nothing to the anchor's semantics, and in debug builds SHALL report the empty text; WHILE variant is plain and title is set it SHALL report the ignored title in debug builds.
- **TIP-17** THE tooltip SHALL take its show delay from showDelay, its hide delay from hideDelay and its touch timeout from touchTimeout, each a number of milliseconds used as given (the motion dial does not scale it), so that 0 opens or closes at once: a show delay of 0 opens as the pointer enters, a hide delay of 0 closes as the pointer leaves the anchor, the gap and the tooltip, and a touch timeout of 0 closes as the finger lifts, after the tooltip has shown for the whole long-press. WHILE one of them is null THE tooltip SHALL use comp.tooltip.motion.show-delay, comp.tooltip.motion.hide-delay or comp.tooltip.timeout.touch in its place, and IF one is negative or not a finite number THE tooltip SHALL use that token likewise and in debug builds report the value it ignored.
- **TIP-18** THE tooltip SHALL treat its show delay, hide delay and touch timeout as waiting times, not motion: WHERE motion is reduced it SHALL keep them, on every platform, including one whose reduced-motion setting removes every animation. The show and hide delays SHALL govern hover alone (TIP-1), and the touch timeout the time after a long-press alone (TIP-3): keyboard focus (TIP-2), another tooltip being open (TIP-8) and the product setting open (TIP-7) SHALL NOT wait for any of them, and the long-press itself SHALL take the platform's own duration. WHEN showDelay, hideDelay or touchTimeout changes while that wait is running THE tooltip SHALL finish the running wait and use the new value from the next time that wait starts.
- **TIP-19** THE tooltip SHALL take its layout direction from where it is used — the direction of the nearest ancestor that sets one, and the platform's own where none does — and SHALL have no direction setting of its own; WHEN that direction changes while the tooltip is shown THE tooltip SHALL draw itself for the new direction at once, without a motion of its own, keeping its open state, the container placed again by the new direction (TIP-20).
- **TIP-20** WHEN the layout direction is right-to-left THE tooltip SHALL take the side start as the anchor's right side and the side end as its left, SHALL take the alignments -start and -end of a tooltip above or below as the right and the left edges, and a positive crossOffset of such a tooltip as a move towards the left, flipping and shifting from there as TIP-9 says; it SHALL leave the sides top and bottom, the alignments -top and -bottom, a crossOffset beside the anchor and the centring on the anchor as they are, SHALL keep auto's order of sides by their names (TIP-23), SHALL start-align a rich tooltip's title and text at the right (TIP-12) and SHALL draw a plain tooltip's shortcut at the left of its text (TIP-27).
- **TIP-21** THE tooltip SHALL lay out its title and its text as text of its own direction, isolated from the text around it: each takes the base direction of its first strong character, or the layout direction where it has none, so that a left-to-right word, a number with its sign or unit, a telephone number and an address keep their own order in a right-to-left layout and reorder nothing beside them; THE tooltip SHALL still place each and align its lines by the layout direction, not by the text's own.
- **TIP-22** THE tooltip SHALL read placement as a side and an alignment along that side: top and bottom SHALL put the container above or below the anchor with its centre on the anchor's, top-start and bottom-start with its start edge on the anchor's start edge, and top-end and bottom-end with its end edge on the anchor's end edge; start and end SHALL put it beside the anchor, on the side the layout direction gives that name, with its centre on the anchor's, start-top and end-top with its top edge on the anchor's top edge, and start-bottom and end-bottom with its bottom edge on the anchor's bottom edge. WHEN placement names a value the tooltip does not define THE tooltip SHALL place itself as the default value says and in debug builds report the unknown value; WHEN placement changes while the tooltip is shown THE tooltip SHALL take its new place at once, without a motion.
- **TIP-23** WHILE placement is auto THE tooltip SHALL try the sides in the order top, bottom, end, start and SHALL take the first that has room for the container within comp.tooltip.window-margin, or the one with the most room WHEN none has, with its centre on the anchor's, and SHALL then shift, hold and follow as TIP-9 says, keeping the side it took for as long as that side has room.
- **TIP-24** THE tooltip SHALL take the distance between the anchor's edge and the nearest part of itself — the container's edge, or the arrow's tip while an arrow is drawn — from offset, a number of the platform's layout units used as given, so that 0 lets the two touch, and from comp.tooltip.offset WHILE offset is null; it SHALL then move the container along its side by crossOffset, before the shift of TIP-9, and by no more than leaves comp.tooltip.arrow.width of the container beside the anchor, so that the tooltip still stands on the anchor's side and an arrow can still reach the anchor. IF offset is negative or not a finite number THE tooltip SHALL use comp.tooltip.offset in its place, IF crossOffset is not a finite number THE tooltip SHALL use 0, and in debug builds it SHALL report the value it ignored.
- **TIP-25** THE tooltip SHALL draw an arrow WHILE arrow is true, and WHILE arrow is null and comp.tooltip.arrow.visible is on, and none otherwise. WHILE it draws one THE tooltip SHALL draw a triangle comp.tooltip.arrow.width wide at its base and comp.tooltip.arrow.height tall on the container's edge that faces the anchor, as one shape with the container — the container's color and elevation, with no seam and no shadow between the two — its tip pointing at the middle of the part of the anchor's edge that the container stands beside, and SHALL keep its base at least comp.tooltip.arrow.inset, and at least the corner's radius, from each end of that edge, standing at the edge's middle where the edge is too short for both; the container SHALL stand comp.tooltip.arrow.height farther from the anchor, so that the tip keeps the offset (TIP-24). WHEN the container flips, shifts or follows the anchor (TIP-9) the arrow SHALL move with it to the edge that now faces the anchor and point at the anchor again, and WHILE the container covers the anchor (TIP-9) THE tooltip SHALL draw no arrow.
- **TIP-26** THE tooltip SHALL draw itself inverse — in the opposite scheme's colors — WHILE inverse is true, on a surface of the scheme WHILE inverse is false, and WHILE inverse is null as its form's choice says: comp.tooltip.plain.container.inverse for a plain tooltip and comp.tooltip.rich.container.inverse for a rich one. The tokens TIP-10 and TIP-27 name are a plain tooltip's inverse look: WHILE drawn on a surface a plain tooltip SHALL take comp.tooltip.plain.surface.container.color, comp.tooltip.plain.surface.container.elevation, comp.tooltip.plain.surface.supporting-text.color and comp.tooltip.plain.surface.shortcut.color in their place. The tokens TIP-11 names are a rich tooltip's surface look: WHILE drawn inverse a rich one SHALL take comp.tooltip.rich.inverse.container.color, comp.tooltip.rich.inverse.container.elevation, comp.tooltip.rich.inverse.title.color and comp.tooltip.rich.inverse.supporting-text.color in place of those TIP-11 names; its shape, padding, sizes, typescales, arrow, placement, motion and timing SHALL be the same either way, and WHEN inverse changes while the tooltip is shown THE tooltip SHALL draw the other look at once, keeping its open state.
- **TIP-27** WHILE variant is plain and shortcut is not empty THE tooltip SHALL draw the shortcut after the text, comp.tooltip.plain.container.gap from it and on the text's first line, with the keyboard shortcut component hosted as KBS-13 says: in its plain form, at size small, with convention auto, its legends and separators in comp.tooltip.plain.supporting-text.typescale and comp.tooltip.plain.shortcut.color; the shortcut SHALL stay whole on one line while the text wraps beside it, and the two with the gap SHALL fit within comp.tooltip.plain.container.max-width. THE tooltip SHALL expose the shortcut as the anchor's keyboard shortcut in the form KBS-12 gives (aria-keyshortcuts on the web) where the platform has that property and the anchor does not state one itself, and otherwise, WHILE describes is true, SHALL add the text KBS-10 gives to the end of the anchor's description; it SHALL NOT make the keys work. WHILE variant is rich THE tooltip SHALL ignore shortcut and in debug builds report it.
- **TIP-28** WHEN a tooltip opens while another tooltip of its window is open or still fading out, or within comp.tooltip.motion.warm-duration after one closed because the pointer or the keyboard focus left its anchor THE tooltip SHALL appear whole in its place at once, without the motion of TIP-15, and the other SHALL disappear at once, without its own; WHEN it is a pointer that opens it within that time THE tooltip SHALL NOT wait for its show delay either, as TIP-8 says of a tooltip that opens while another is open. A tooltip closed by Escape (TIP-4), by an activation of its anchor (TIP-6) or by a press on it (TIP-13) SHALL start no such time, so that the next tooltip waits and moves as a first one does. The time is a waiting time: WHERE motion is reduced it SHALL still apply (TIP-18).
- **TIP-29** WHEN the tooltip is told to close while it is still entering, or to open while it is still leaving THE tooltip SHALL turn round from the opacity, the size and the position it has reached, without first jumping to the start or the end of either motion, and SHALL take no longer over the rest than the whole duration of the motion it turns to. WHILE the tooltip is closed or leaving THE tooltip SHALL take no pointer input — a press reaches what lies under it, and the pointer on it is not hover (TIP-1) — and WHILE it is closed it SHALL take no room in the layout and draw nothing, so that a tooltip nobody can see never stands in the way of what is under it.

### Tokens

As written in the token documents (DTCG): an alias in braces names the token it takes its value from, which each design system resolves. On the web each token is a CSS custom property: `--tanrei` and the name after `tanrei`, joined by hyphens (`tanrei.comp.tooltip.…` → `--tanrei-comp-tooltip-…`).

#### `tanrei.comp.tooltip`

| Token | Type | Value |
| --- | --- | --- |
| `comp.tooltip.offset` | `dimension` | `{tanrei.sys.space.space50}` |
| `comp.tooltip.window-margin` | `dimension` | `{tanrei.sys.space.space100}` |
| `comp.tooltip.arrow.visible` | `number` | `0` |
| `comp.tooltip.arrow.width` | `dimension` | `{tanrei.sys.space.space150}` |
| `comp.tooltip.arrow.height` | `dimension` | `{tanrei.sys.space.space75}` |
| `comp.tooltip.arrow.inset` | `dimension` | `{tanrei.sys.space.space100}` |
| `comp.tooltip.plain.container.inverse` | `number` | `1` |
| `comp.tooltip.plain.container.color` | `color` | `{tanrei.sys.color.inverse-surface}` |
| `comp.tooltip.plain.container.elevation` | `shadow` | `{tanrei.sys.elevation.level0}` |
| `comp.tooltip.plain.container.shape` | `dimension` | `{tanrei.sys.shape.corner.small}` |
| `comp.tooltip.plain.container.padding-inline` | `dimension` | `{tanrei.sys.space.space100}` |
| `comp.tooltip.plain.container.padding-block` | `dimension` | `{tanrei.sys.space.space50}` |
| `comp.tooltip.plain.container.min-height` | `dimension` | `24px` |
| `comp.tooltip.plain.container.max-width` | `dimension` | `200px` |
| `comp.tooltip.plain.container.gap` | `dimension` | `{tanrei.sys.space.space100}` |
| `comp.tooltip.plain.supporting-text.color` | `color` | `{tanrei.sys.color.inverse-on-surface}` |
| `comp.tooltip.plain.supporting-text.typescale` | `typography` | `{tanrei.sys.typescale.body-small}` |
| `comp.tooltip.plain.shortcut.color` | `color` | `{tanrei.sys.color.inverse-on-surface}` |
| `comp.tooltip.plain.surface.container.color` | `color` | `{tanrei.sys.color.surface-bright}` |
| `comp.tooltip.plain.surface.container.elevation` | `shadow` | `{tanrei.sys.elevation.level2}` |
| `comp.tooltip.plain.surface.supporting-text.color` | `color` | `{tanrei.sys.color.on-surface}` |
| `comp.tooltip.plain.surface.shortcut.color` | `color` | `{tanrei.sys.color.on-surface-variant}` |
| `comp.tooltip.rich.container.inverse` | `number` | `0` |
| `comp.tooltip.rich.container.color` | `color` | `{tanrei.sys.color.surface-bright}` |
| `comp.tooltip.rich.container.elevation` | `shadow` | `{tanrei.sys.elevation.level2}` |
| `comp.tooltip.rich.container.shape` | `dimension` | `{tanrei.sys.shape.corner.medium}` |
| `comp.tooltip.rich.container.padding-inline` | `dimension` | `{tanrei.sys.space.space200}` |
| `comp.tooltip.rich.container.padding-block` | `dimension` | `{tanrei.sys.space.space150}` |
| `comp.tooltip.rich.container.gap` | `dimension` | `{tanrei.sys.space.space50}` |
| `comp.tooltip.rich.container.max-width` | `dimension` | `320px` |
| `comp.tooltip.rich.title.color` | `color` | `{tanrei.sys.color.on-surface}` |
| `comp.tooltip.rich.title.typescale` | `typography` | `{tanrei.sys.typescale.heading-6}` |
| `comp.tooltip.rich.supporting-text.color` | `color` | `{tanrei.sys.color.on-surface-variant}` |
| `comp.tooltip.rich.supporting-text.typescale` | `typography` | `{tanrei.sys.typescale.body}` |
| `comp.tooltip.rich.inverse.container.color` | `color` | `{tanrei.sys.color.inverse-surface}` |
| `comp.tooltip.rich.inverse.container.elevation` | `shadow` | `{tanrei.sys.elevation.level0}` |
| `comp.tooltip.rich.inverse.title.color` | `color` | `{tanrei.sys.color.inverse-on-surface}` |
| `comp.tooltip.rich.inverse.supporting-text.color` | `color` | `{tanrei.sys.color.inverse-on-surface}` |
| `comp.tooltip.motion.show-delay` | `duration` | `{tanrei.sys.motion.duration.long2}` |
| `comp.tooltip.motion.hide-delay` | `duration` | `{tanrei.sys.motion.duration.short2}` |
| `comp.tooltip.motion.warm-duration` | `duration` | `{tanrei.sys.motion.duration.medium2}` |
| `comp.tooltip.motion.enter-duration` | `duration` | `{tanrei.sys.motion.role.appear.hint.enter}` |
| `comp.tooltip.motion.enter-easing` | `cubicBezier` | `{tanrei.sys.motion.easing.enter}` |
| `comp.tooltip.motion.exit-duration` | `duration` | `{tanrei.sys.motion.role.appear.hint.exit}` |
| `comp.tooltip.motion.exit-easing` | `cubicBezier` | `{tanrei.sys.motion.easing.exit}` |
| `comp.tooltip.timeout.touch` | `duration` | `1500ms` |

## दिशानिर्देश

### कब इस्तेमाल करें

टूलटिप का इस्तेमाल उस व्यक्ति के लिए आइकन वाली क्रिया का नाम बताने के लिए करें जो ग्लिफ़ नहीं पहचानता, या किसी शब्द, सीमा या सेटिंग को वहीं समझाने के लिए। यह एक विवरण है, जो चलते-चलते पढ़ा जाता है।

टच इस्तेमाल करने वाले लोगों को टूलटिप तब तक नहीं दिखता जब तक वे देर तक न दबाएँ, और स्क्रीन रीडर उसे सिर्फ़ एक विवरण के रूप में सुनता है। जो चीज़ व्यक्ति को कोई काम पूरा करने के लिए चाहिए, उसे कभी सिर्फ़ टूलटिप में न रखें: उसे स्क्रीन पर टेक्स्ट के रूप में दिखाएँ। जिस टिप्पणी को लिंक या बटन चाहिए, वह टूलटिप नहीं है। उसके लिए डायलॉग इस्तेमाल करें, या टेक्स्ट को उस चीज़ के बग़ल में रखें जिसे वह समझाता है।

### वेरिएंट चुनना

| वेरिएंट | यह क्या है | किसके लिए |
| --- | --- | --- |
| Plain | एक छोटा वाक्यांश, डिफ़ॉल्ट रूप से इनवर्स सरफ़ेस पर। यह `headline` को अनदेखा करता है, और अपने टेक्स्ट के बाद कीबोर्ड शॉर्टकट दिखा सकता है। | यह बताना कि आइकन क्या करता है: “ट्रैश में डालें”, “शेयर करें”। |
| Rich | कुछ वाक्यों के ऊपर एक वैकल्पिक शीर्षक, डिफ़ॉल्ट रूप से उठी हुई सरफ़ेस पर। यह `shortcut` को अनदेखा करता है। | किसी शब्द या सेटिंग को समझाना: “स्टोरेज” और उसमें क्या गिना जाता है। |

वेरिएंट संरचना का चुनाव है, टोकन का कोई अक्ष नहीं। डिज़ाइन सिस्टम दोनों रूपों की स्टाइल बदल सकता है, पर मानों के ज़रिए तीसरा रूप नहीं जोड़ सकता।

### स्थान

`placement` बताता है कि टूलटिप ऐंकर की किस ओर रहना पसंद करता है और उस ओर के साथ-साथ कैसे सीध में आता है। डिफ़ॉल्ट `top` है।

| ओर | ऐंकर के बीच में | पहले किनारे साथ-साथ | दूसरे किनारे साथ-साथ |
| --- | --- | --- | --- |
| ऊपर | `top` | `top-start` | `top-end` |
| नीचे | `bottom` | `bottom-start` | `bottom-end` |
| ऐंकर से पहले | `start` | `start-top` | `start-bottom` |
| ऐंकर के बाद | `end` | `end-top` | `end-bottom` |

- **सीध का मतलब है किनारे पर किनारा।** `top-start` टूलटिप के शुरुआती किनारे को ऐंकर के शुरुआती किनारे पर रखता है, और `end-bottom` उसके निचले किनारे को ऐंकर के निचले किनारे पर। सीध वाला स्थान तब इस्तेमाल करें जब पैनल के किनारे के पास के छोटे ऐंकर पर चौड़ा टूलटिप हो, या टूलटिप को टेक्स्ट की किसी पंक्ति की सीध में लाना हो।
- **शुरू और अंत लेआउट की दिशा के साथ चलते हैं।** दाएँ से बाएँ वाले लेआउट में `start` दाईं ओर है और `top-start` दाएँ किनारों को सीध में लाता है। ऊपर और नीचे मिरर नहीं होते।
- **`auto`** ऊपर, नीचे, अंत और शुरू को इसी क्रम में आज़माता है और वह पहली ओर लेता है जहाँ जगह हो, बीच की सीध में। इसे उस ऐंकर के लिए इस्तेमाल करें जिसके आस-पास का आपको पता नहीं हो सकता, जैसे ऐसे पैनल का कंट्रोल जो किसी भी किनारे पर डॉक हो सकता है।
- **जब जगह न हो।** टूलटिप उलटी ओर पलट जाता है और अपनी सीध बनाए रखता है, फिर विंडो के सेफ़ एरिया के भीतर रहने के लिए उस ओर के साथ-साथ खिसकता है। टूलटिप से छोटी विंडो में वह विंडो के भीतर रहता है, ज़रूरी हो तो ऐंकर के ऊपर। एक बार पलटने के बाद वह तब तक वही ओर रखता है जब तक उस ओर जगह है, ताकि स्क्रॉल होता पेज उसे इधर-उधर न उछाले।
- **`offset` और `crossOffset`।** `offset` ऐंकर के किनारे से दूरी है, और 0 दोनों को छूने देता है; सेट न करने पर यह सिस्टम की दूरी होती है। `crossOffset` टूलटिप को उसकी ओर के साथ-साथ खिसकाता है, ऐंकर के ऊपर या नीचे होने पर अंत की ओर और उसके बग़ल में होने पर नीचे की ओर, और उसे कभी ऐंकर की उस ओर से बाहर नहीं ले जाता। दोनों प्लैटफ़ॉर्म की लेआउट इकाइयों में हैं। इन्हें सिर्फ़ वहाँ सेट करें जहाँ ऐंकर का बॉक्स वह नहीं है जिसे आँख उसका किनारा मानती है, जैसे बड़े अदृश्य हिट एरिया वाला कंट्रोल या चार्ट का कोई निशान।
- **दिखते समय बदलाव।** नया `placement` या ऑफ़सेट टूलटिप को तुरंत खिसका देता है, बिना मोशन के।

### तीर

`arrow` टूलटिप के किनारे पर एक छोटा त्रिकोण बनाता है जो ऐंकर की ओर इशारा करता है। डिफ़ॉल्ट सिस्टम में यह बंद है। सेट न करने पर यह डिज़ाइन सिस्टम का चुनाव लेता है; `true` और `false` इसे एक टूलटिप के लिए तय करते हैं। वेब पर ऐट्रिब्यूट true के लिए `arrow` और false के लिए `arrow="false"` है।

तीर और टूलटिप एक ही शेप हैं, एक ही रंग में। तीर ऐंकर की ओर इशारा करता है, टूलटिप के बीच की ओर नहीं, टूलटिप के पलटने या खिसकने के बाद भी, और कोनों से दूर रहता है। टूलटिप तीर की ऊँचाई जितना और दूर रहता है, इसलिए जो गैप आप देखते हैं वह तीर के साथ और उसके बिना बराबर होता है।

तीर वहाँ इस्तेमाल करें जहाँ सिर्फ़ ओर से पता नहीं चलता कि किस कंट्रोल की बात हो रही है: उदाहरण के लिए, भरे हुए टूलबार के ऊपर का वह संकेत जिसे आप ख़ुद खोलते हैं। होवर पर दिखने वाले नामों को इसकी ज़रूरत कम ही पड़ती है।

### दो रूप

दोनों में से कोई भी रूप इनवर्स बनाया जा सकता है, यानी उलटी स्कीम के रंगों में, या स्कीम की उठी हुई सरफ़ेस पर।

| `inverse` | Plain | Rich |
| --- | --- | --- |
| सेट नहीं (डिफ़ॉल्ट) | जैसा डिज़ाइन सिस्टम सादे टूलटिप के लिए चुने: डिफ़ॉल्ट सिस्टम में इनवर्स। | जैसा डिज़ाइन सिस्टम रिच टूलटिप के लिए चुने: डिफ़ॉल्ट सिस्टम में सरफ़ेस। |
| `true` | इनवर्स। | इनवर्स। |
| `false` | सरफ़ेस पर। | सरफ़ेस पर। |

वेब पर ऐट्रिब्यूट true के लिए `inverse` और false के लिए `inverse="false"` है, जैसे [स्नैकबार](https://tanrei.chnotchy.com/hi/components/snackbar/) का है।

सिर्फ़ रंग और एलिवेशन बदलते हैं। शेप, साइज़, टेक्स्ट स्टाइल, तीर, स्थान और मोशन दोनों रूपों में वही हैं, और कोई भी रूप यह नहीं कहता कि टूलटिप महत्वपूर्ण है। इसे उस एक टूलटिप के लिए सेट करें जो वरना अपने पीछे की चीज़ से अलग नहीं दिखता: गहरे इमेज व्यूअर के ऊपर या इनवर्स बार पर गहरा लेबल, या भरी-भरी उठी हुई सरफ़ेस के ऊपर एक लंबी टिप्पणी।

### कीबोर्ड शॉर्टकट

`shortcut` सादे टूलटिप के टेक्स्ट के बाद ऐंकर के कमांड की कुंजियाँ दिखाता है, उस कीबोर्ड के लिए लिखी हुई जिसे व्यक्ति इस्तेमाल करता है। यह [कीबोर्ड शॉर्टकट](https://tanrei.chnotchy.com/hi/components/keyboard-shortcut/) कंपोनेंट के कुंजी-नाम लेता है, हर स्ट्रिंग में एक कॉर्ड; वेब पर ऐट्रिब्यूट में कॉर्ड स्पेस से अलग किए जाते हैं।

टूलटिप कुंजियाँ सिर्फ़ दिखाता है। वह उन्हें काम करने लायक़ नहीं बनाता: उन्हें आपका प्रॉडक्ट बाइंड करता है। कुंजियाँ एक पंक्ति में पूरी रहती हैं, जबकि लंबा टेक्स्ट उनके बग़ल में अगली पंक्ति में जाता है। रिच टूलटिप `shortcut` को अनदेखा करता है और डीबग बिल्ड में इसकी रिपोर्ट करता है।

### खुलना, फ़ोकस और बंद होना

टूलटिप पढ़ा जाने वाला ओवरले है। लोग उससे जानकारी लेते हैं और उसके भीतर कभी कुछ नहीं करते, इसलिए वह कभी फ़ोकस नहीं लेता।

| इनपुट | खुलता है | बंद होता है |
| --- | --- | --- |
| पॉइंटर | जब वह दिखाने की देरी तक ऐंकर पर टिका रहे, उसके बाद। | जब वह छिपाने की देरी तक ऐंकर, गैप और टूलटिप से बाहर रहे, उसके बाद। पॉइंटर टूलटिप को पढ़ने के लिए गैप पार करके उस पर जा सकता है। |
| कीबोर्ड फ़ोकस | तुरंत, जब ऐंकर को कीबोर्ड फ़ोकस मिलता है। पॉइंटर या टच से मिला फ़ोकस इसे नहीं खोलता। | जब फ़ोकस ऐंकर से हटता है। |
| टच से देर तक दबाना | तुरंत, ऐंकर को सक्रिय किए बिना। | उँगली उठने के बाद टच टाइमआउट बीतने पर, या कहीं और टच होने पर उससे पहले। |

- **इस्तेमाल के दौरान कोई समय सीमा नहीं।** जब तक पॉइंटर ऐंकर, टूलटिप या उनके बीच के गैप के ऊपर है, या ऐंकर पर कीबोर्ड फ़ोकस है, वह खुला रहता है। गैप दिखाया नहीं जाता और दबाना नहीं लेता: वह सिर्फ़ होवर के रूप में गिना जाता है।
- **Escape।** Escape इसे फ़ोकस ले जाए बिना बंद करती है, और उससे आगे नहीं जाती, इसलिए उसे घेरने वाला डायलॉग खुला रहता है। वह तब तक बंद रहता है जब तक पॉइंटर ऐंकर पर फिर से न आए या ऐंकर फिर से फ़ोकस न हो।
- **सक्रिय करना।** ऐंकर को सक्रिय करना (क्लिक, टैप, Enter या Space) इसे बंद कर देता है, और वही होवर इसे दोबारा नहीं खोलता।
- **एक समय में एक।** जब कोई टूलटिप खुलता है, तो विंडो का कोई भी दूसरा टूलटिप बंद हो जाता है, और नया बिना देरी के खुलता है, क्योंकि व्यक्ति पहले से टूलटिप पढ़ रहा है।
- **एक टूलटिप से दूसरे पर जाना।** जो टूलटिप किसी दूसरे की जगह लेता है, या किसी ऐसे टूलटिप के थोड़ी देर बाद खुलता है जो पॉइंटर या फ़ोकस के अपने ऐंकर से हटने पर बंद हुआ था, वह तुरंत पूरा दिखता है: न देरी, न मोशन। इसलिए टूलबार पर फिरता हुआ पॉइंटर एक के बाद एक नाम पढ़ता है। जो टूलटिप Escape से, अपने ऐंकर को सक्रिय करने से या उस पर दबाने से बंद हुआ हो, वह यह समय शुरू नहीं करता।
- **फ़ोकस नहीं लेता, कुछ नहीं रोकता।** उसमें फ़ोकस करने या दबाने लायक़ कुछ नहीं होता, वह किसी चीज़ को निष्क्रिय नहीं करता और कोई स्क्रिम नहीं बनाता। टूलटिप पर दबाना उसे बंद कर देता है और उसके नीचे की चीज़ तक नहीं पहुँचता।
- **सबसे ऊपर।** वह अपनी विंडो की हर दूसरी लेयर के ऊपर बनता है, खुले डायलॉग और उसके स्क्रिम के भी ऊपर, इसलिए डायलॉग के भीतर का टूलटिप दिखता है।
- **स्थान।** वह वहाँ रहता है जहाँ `placement` कहता है; [स्थान](https://tanrei.chnotchy.com/hi/components/tooltip/#%E0%A4%B8%E0%A5%8D%E0%A4%A5%E0%A4%BE%E0%A4%A8) देखें। ऐंकर के हिलने पर वह उसके साथ चलता है, और तब बंद हो जाता है जब ऐंकर हटा दिया जाए, छिपा दिया जाए, स्क्रॉल होकर विंडो से बाहर चला जाए, या किसी स्क्रॉल होने वाले हिस्से के भीतर स्क्रॉल होकर नज़र से ओझल हो जाए।
- **मोशन।** वह ऐंकर की ओर से उसी तरह निकलता है जैसे डिज़ाइन सिस्टम की हर सतह दिखती है: डिफ़ॉल्ट रूप से वह ऐंकर की ओर वाले किनारे के बीच से थोड़ा बढ़ते हुए फ़ेड होकर आता है, और उसी तरह वापस जाता है। बीच में रोका गया मोशन जहाँ है वहीं से पलट जाता है। बंद होते समय टूलटिप कोई पॉइंटर नहीं लेता, इसलिए वह कभी अपने नीचे की चीज़ के रास्ते में नहीं आता। जहाँ मोशन कम किया गया है, वहाँ वह सिर्फ़ फ़ेड होता है।
- **पढ़कर सुनाना।** टूलटिप के दिखने पर कुछ पढ़कर नहीं सुनाया जाता। जब तक `describes` true है, उसका टेक्स्ट, रिच टूलटिप में शीर्षक के बाद, ऐंकर का विवरण है, टूलटिप खुला हो या नहीं, और बने हुए टूलटिप को दूसरी बार पढ़े जाने से रोका जाता है।

### एक टूलटिप के लिए देरी

डिज़ाइन सिस्टम दिखाने की देरी, छिपाने की देरी और टच टाइमआउट हर टूलटिप के लिए एक साथ सेट करता है। कोई एक टूलटिप `showDelay`, `hideDelay` और `touchTimeout` से अपने मान सेट कर सकता है, मिलीसेकंड में। सेट न करने पर हर एक सिस्टम का मान लेता है।

- **इन्हें कब सेट करें।** जिस घने टूलबार को अपने नाम जल्दी चाहिए, उसमें दिखाने की देरी कम करें, और जिस चार्ट के निशानों पर पॉइंटर फिरता है, उस पर बढ़ाएँ, ताकि कोई टूलटिप झलककर ग़ायब न हो। कुछ वाक्यों वाले रिच टूलटिप पर टच टाइमआउट बढ़ाएँ, और एक शब्द के नाम पर घटाएँ।
- **0 का मतलब है तुरंत।** दिखाने की देरी 0 होने पर टूलटिप पॉइंटर के ऐंकर में आते ही खुलता है, और छिपाने की देरी 0 होने पर पॉइंटर के ऐंकर, गैप और टूलटिप से निकलते ही बंद होता है। टूलटिप पर तब भी होवर किया जा सकता है, क्योंकि गैप होवर के रूप में गिना जाता है। टच टाइमआउट 0 होने पर वह देर तक दबाने के पूरे दौरान दिखता है और उँगली उठते ही बंद हो जाता है।
- **जैसा लिखा, वैसा इस्तेमाल।** आपका सेट किया हुआ मान मोशन डायल से स्केल नहीं होता, और कम मोशन में भी बना रहता है: देरी एक इंतज़ार है, ऐनिमेशन नहीं। ऋणात्मक या ग़ैर-संख्या मान सिस्टम का मान लेता है और डीबग बिल्ड में रिपोर्ट किया जाता है। वेब पर ख़ाली ऐट्रिब्यूट भी संख्या नहीं है।
- **सिर्फ़ होवर और टच।** कीबोर्ड फ़ोकस तब भी टूलटिप को तुरंत खोलता है, किसी दूसरे के दिखते समय खुला टूलटिप तब भी अपनी दिखाने की देरी छोड़ देता है, और `open` सेट करना तब भी उसे तुरंत दिखाता या छिपाता है। देर तक दबाना ख़ुद प्लैटफ़ॉर्म की अपनी अवधि लेता है।
- **इंतज़ार के दौरान बदलाव।** जो इंतज़ार पहले से चल रहा है, वह वैसे ही पूरा होता है जैसे शुरू हुआ था। नया मान अगली बार लागू होता है।

आज ये प्रॉपर्टी सिर्फ़ वेब और React लेते हैं। जब बाक़ी प्लैटफ़ॉर्म बराबरी पर आएँगे, तो स्पेक इन्हें हर प्लैटफ़ॉर्म के अपने तरीक़े से नाम देता है: Compose पर `showDelayMillis`, `hideDelayMillis` और `touchTimeoutMillis`, Flutter के `Tooltip` के `waitDuration`, `exitDuration` और `showDuration`, और SwiftUI और React Native पर स्पेक के अपने नाम।

हर प्लैटफ़ॉर्म एक नॉन-मोडल प्रस्तुति इस्तेमाल करता है: वेब पर टॉप लेयर में एक `popover="manual"` एलिमेंट, SwiftUI पर विंडो के ऊपर एक ओवरले (`.popover` नहीं, जो कॉम्पैक्ट चौड़ाइयों पर मोडल होता है), Compose पर ऐसा `Popup` जो फ़ोकस नहीं ले सकता, Flutter पर एक `OverlayPortal`, और React Native पर `TanreiProvider` की ओवरले लेयर (`Modal` नहीं, जो हर टच ले लेता है)।

### करें

- सादे टूलटिप कुछ शब्दों तक रखें, और रिच टूलटिप कुछ वाक्यों तक।
- एक स्क्रीन पर एक ही तरह के ऐंकर को एक ही स्थान दें, जैसे टूलबार के हर आइकन के नीचे।
- ज़्यादातर टूलटिप के लिए `inverse` और `arrow` डिज़ाइन सिस्टम पर छोड़ें, और उस एक के लिए सेट करें जिसे इसकी ज़रूरत है।
- कमांड की कुंजियाँ `shortcut` से दिखाएँ, उन्हें टेक्स्ट में टाइप करके नहीं।
- ऐंकर के एक ग्रुप के टूलटिप को एक जैसी देरी दें, ताकि वे एक ही रफ़्तार रखें।
- जब टूलटिप ऐंकर का अपना लेबल दिखाता हो, तो `describes` को false करें।

### न करें

- टूलटिप को आइकन बटन के नाम के रूप में इस्तेमाल न करें। बटन का `label` ही उसका नाम है।
- अक्षम ऐंकर पर यह समझाने के लिए टूलटिप न रखें कि वह अक्षम क्यों है। अक्षम कंट्रोल फ़ोकस नहीं हो सकता और हो सकता है कि उसे पॉइंटर के कोई इवेंट न मिलें। कारण दिखने वाले टेक्स्ट में रखें।
- टूलटिप में लिंक, बटन या कोई और इंटरैक्टिव चीज़ न रखें।
- जो बात ऐंकर दिखने वाले टेक्स्ट में पहले से कहता है, उसे टूलटिप में न दोहराएँ।
- टूलटिप को ज़्यादा महत्वपूर्ण दिखाने के लिए इनवर्स रूप या तीर का इस्तेमाल न करें।

## सुलभता

### कंपोनेंट क्या सँभालता है

- जब तक `describes` true है, टेक्स्ट, रिच टूलटिप में शीर्षक के बाद, ऐंकर का एक्सेसिबल विवरण है, और टूलटिप दिख रहा हो या नहीं, वह उपलब्ध रहता है। ऐंकर अपना नाम और रोल बनाए रखता है। जब तक `describes` false है, टूलटिप ऐंकर में कुछ नहीं जोड़ता।
- बने हुए टूलटिप को दो बार पढ़े जाने से रोका जाता है। वह कभी फ़ोकस नहीं लेता और उसमें फ़ोकस करने लायक़ कुछ नहीं होता।
- ऐंकर पर कीबोर्ड फ़ोकस इसे तुरंत खोलता है, और फ़ोकस हटाना इसे बंद करता है। टूलटिप ख़ुद कभी Tab स्टॉप नहीं होता।
- Escape इसे फ़ोकस ले जाए बिना बंद करती है, और साथ में उसे घेरने वाला डायलॉग बंद नहीं करती।
- यह WCAG 1.4.13 (होवर या फ़ोकस पर कॉन्टेंट) पूरा करता है: इसे पॉइंटर या फ़ोकस हटाए बिना ख़ारिज किया जा सकता है, छिपाने की किसी भी देरी पर, 0 पर भी, इस पर होवर किया जा सकता है, क्योंकि ऐंकर और टूलटिप के बीच का गैप होवर के रूप में गिना जाता है, और यह तब तक रहता है जब तक होवर या फ़ोकस ख़त्म न हो या इसे ख़ारिज न किया जाए।
- यह बड़े टेक्स्ट के साथ बढ़ता है और उसे काटता नहीं, और इसका टेक्स्ट लेआउट की दिशा के शुरू की ओर सीध में रहता है।
- शॉर्टकट ऐंकर के कीबोर्ड शॉर्टकट के रूप में दिया जाता है (वेब पर `aria-keyshortcuts`, उस एलिमेंट पर जो फ़ोकस लेता है), और बनी हुई कुंजियाँ सहायक तकनीक से छिपी रहती हैं। जहाँ ऐंकर पहले से अपना कोई शॉर्टकट बताता है, वहाँ टूलटिप की कुंजियाँ उसकी जगह विवरण के अंत में शब्दों में लिखी जाती हैं, जब तक `describes` true है।
- तीर सजावट है और सहायक तकनीक से छिपा रहता है। दोनों रूप टेक्स्ट और कंटेनर के रंगों की ऐसी जोड़ियाँ इस्तेमाल करते हैं जिनका कंट्रास्ट बिल्ड हर स्कीम में जाँचता है।
- इसका मोशन छोटा है: डिफ़ॉल्ट रूप से एक फ़ेड और थोड़ा-सा बढ़ना। जहाँ मोशन कम किया गया है, वहाँ यह बिना बढ़े और बिना सफ़र किए फ़ेड होता है, Android को छोड़कर, जिसकी सेटिंग हर ऐनिमेशन हटा देती है। देरी, टच टाइमआउट और वह समय जिसके दौरान अगला टूलटिप तुरंत खुलता है, इंतज़ार हैं, मोशन नहीं, और हर जगह बने रहते हैं।
- जिस टूलटिप का टेक्स्ट ख़ाली है, वह कभी नहीं खुलता और कुछ नहीं जोड़ता। डीबग बिल्ड इसकी रिपोर्ट करते हैं, और सादे टूलटिप के अनदेखे किए गए शीर्षक की भी।

प्लैटफ़ॉर्म की ज्ञात कमियाँ:

- SwiftUI, Compose, Flutter और React Native अभी `showDelay`, `hideDelay` या `touchTimeout` नहीं लेते, और गैप को होवर के रूप में नहीं गिनते: वहाँ हर टूलटिप सिस्टम की देरी लेता है, और पॉइंटर छिपाने की देरी के भीतर गैप पार करता है। उनके पास बीच में रखे सिर्फ़ चार स्थान हैं (`top`, `bottom`, `start`, `end`), और `offset`, `crossOffset`, `arrow`, `inverse` या `shortcut` नहीं हैं; उनके टूलटिप बिना बढ़े और बिना सफ़र किए फ़ेड होते हैं।
- Web: टच से देर तक दबाना टूलटिप सिर्फ़ वहाँ खोलता है जहाँ ब्राउज़र उसे कॉन्टेक्स्ट मेन्यू के रूप में रिपोर्ट करता है। iOS Safari ऐसा नहीं करता, इसलिए वहाँ टूलटिप टच से नहीं खुलता।
- Web: रिच टूलटिप का शीर्षक `headline` ऐट्रिब्यूट है। `<tanrei-tooltip>` पर `title` ऐट्रिब्यूट ब्राउज़र का अपना है, और ब्राउज़र उसके लिए अपना नेटिव टूलटिप बनाता है: इसे न लगाएँ।
- SwiftUI में टूलटिप का कोई रोल नहीं है। विवरण ऐंकर का एक्सेसिबिलिटी हिंट है।
- iOS पर SwiftUI: फ़ोकस वाले ऐंकर पर Return या Space टूलटिप को बंद नहीं करती, और Escape उसे सिर्फ़ तब बंद करती है जब ऐंकर पर फ़ोकस हो। जो ऐंकर टैप से फ़ोकस लेता है, जैसे टेक्स्ट फ़ील्ड, वह अपना टूलटिप खोल देता है। जो ऐंकर पारदर्शी कर दिया गया हो या ढक गया हो, वह छिपा हुआ नहीं माना जाता।
- SwiftUI टूलटिप उस लेयर में बनाता है जो `.tanreiTheme(_:)` और Tanrei का डायलॉग देते हैं। जो कॉन्टेंट SwiftUI अलग से प्रस्तुत करता है, जैसे आपका अपना `.sheet` या `.popover`, उसे अपने टूलटिप दिखाने के लिए `.tanreiTooltipLayer()` चाहिए।
- Compose में विवरण की कोई प्रॉपर्टी नहीं है। टेक्स्ट ऐंकर का स्टेट विवरण बन जाता है, जो उसके नाम और रोल के बाद पढ़ा जाता है। Tanrei का कंट्रोल इसे अपने नोड पर रखता है; किसी और ऐंकर का विवरण सिर्फ़ तब मिलता है जब कोई मर्ज करने वाला पूर्वज उसे उठा ले। टॉगल ऐंकर पर, जैसे टॉगल आइकन बटन, यह चालू या बंद की जगह ले लेता है।
- Compose: जो टूलटिप आप किसी खुले डायलॉग के पीछे के ऐंकर पर कोड से दिखाते हैं, वह डायलॉग की विंडो के नीचे बनता है।
- Compose: जब फ़ोकस विंडो में कहीं और हो और ऐंकर पर सिर्फ़ होवर किया गया हो, तब Escape टूलटिप तक सिर्फ़ Android 9 (API 28) और उसके बाद के वर्शन पर पहुँचती है।
- Compose: असली माउस का होवर, बाहर का टच, Escape का लिसनर और TalkBack का ऐंकर का स्टेट विवरण पढ़ना सिर्फ़ Robolectric पर जाँचे गए हैं, अभी किसी डिवाइस पर नहीं।
- Flutter: बना हुआ टूलटिप हमेशा सिमैंटिक्स से बाहर रखा जाता है, क्योंकि Flutter का टूलटिप रोल अभी इस्तेमाल नहीं किया जा सकता। ऐंकर पर का विवरण इससे प्रभावित नहीं होता।
- Flutter: Escape सिर्फ़ तब ले ली जाती है जब फ़ोकस ऐंकर में हो, या जब Tanrei का डायलॉग उसे ले ले। Escape सँभालने वाला कोई और पूर्वज, जैसे Material का डायलॉग रूट, फ़ोकस कहीं और होने पर उसे तब भी पाता है।
- React Native: विवरण ऐंकर का `accessibilityHint` है, ऐंकर के अपने हिंट के बाद।
- React Native: कहीं और का टच देर तक दबाकर खोले गए टूलटिप को पहले बंद नहीं करता। टच टाइमआउट उसे तब भी बंद करता है।
- React Native: टूलटिप स्क्रॉल होने वाले ऐंकर के साथ नहीं चलता, और ऐंकर के स्क्रॉल होकर नज़र से बाहर जाने पर बंद नहीं होता। वह सेफ़ एरिया के भीतर सिर्फ़ तब रहता है जब आप विंडो के इनसेट `TanreiProvider` को देते हैं।
- React Native: होवर, पॉइंटर को टूलटिप पर ले जाना, देर तक दबाना और Escape अभी किसी डिवाइस पर नहीं जाँचे गए हैं।

### आपको क्या करना है

- ऐंकर को उसका अपना एक्सेसिबल नाम दें। टूलटिप कभी उसकी जगह नहीं लेता।
- जब टेक्स्ट वही नाम दोहराता हो, तो `describes` को false करें।
- `shortcut` से दिखाई गई कुंजियाँ ख़ुद बाइंड करें, और जहाँ भी वह कमांड और कहीं दिखता हो, जैसे किसी मेन्यू में, वहाँ वही कुंजियाँ दिखाएँ।
- ऐंकर को फ़ोकस करने लायक़ बनाएँ, ताकि कीबोर्ड इस्तेमाल करने वाले लोग टूलटिप खोल सकें।
- अगर आप टच टाइमआउट घटाते हैं, तो पक्का करें कि टेक्स्ट बचे हुए समय में भी पढ़ा जा सके। 0 का टाइमआउट टूलटिप को सिर्फ़ तब तक दिखाता है जब तक उँगली टिकी है।
- जो कुछ भी व्यक्ति को चाहिए, उसे टूलटिप के बाहर रखें। टच और स्क्रीन रीडर इस्तेमाल करने वाले लोग शायद उसे कभी न देखें।
- React Native पर `TanreiProvider` को अपने ऐप के रूट में रखें, विंडो के `insets` के साथ: उसकी ओवरले लेयर टूलटिप को सेफ़ एरिया के भीतर बनाती है। SwiftUI पर `.tanreiTheme(_:)` को ऐंकर के ऊपर लगाएँ, और `.tanreiTooltipLayer()` को अपनी शीट और पॉपओवर के कॉन्टेंट पर। Flutter पर टूलटिप को अपने ऊपर एक `Overlay` चाहिए, जो `Navigator` वाले हर `WidgetsApp` में होता है।
