@fluentui/react-tooltip 0.0.0-nightly6a6e258c4020220125.1 → 0.0.0-nightly6faffd280a20220221.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +198 -42
- package/CHANGELOG.md +53 -14
- package/MIGRATION.md +51 -43
- package/Spec.md +201 -337
- package/dist/react-tooltip.d.ts +31 -37
- package/lib/Tooltip.js.map +1 -1
- package/lib/components/Tooltip/Tooltip.d.ts +3 -2
- package/lib/components/Tooltip/Tooltip.js +4 -4
- package/lib/components/Tooltip/Tooltip.js.map +1 -1
- package/lib/components/Tooltip/Tooltip.types.d.ts +29 -33
- package/lib/components/Tooltip/Tooltip.types.js.map +1 -1
- package/lib/components/Tooltip/index.js.map +1 -1
- package/lib/components/Tooltip/private/constants.js.map +1 -1
- package/lib/components/Tooltip/renderTooltip.js +2 -2
- package/lib/components/Tooltip/renderTooltip.js.map +1 -1
- package/lib/components/Tooltip/useTooltip.d.ts +1 -3
- package/lib/components/Tooltip/useTooltip.js +40 -55
- package/lib/components/Tooltip/useTooltip.js.map +1 -1
- package/lib/components/Tooltip/useTooltipStyles.js +2 -2
- package/lib/components/Tooltip/useTooltipStyles.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib-commonjs/Tooltip.js.map +1 -1
- package/lib-commonjs/components/Tooltip/Tooltip.d.ts +3 -2
- package/lib-commonjs/components/Tooltip/Tooltip.js +6 -5
- package/lib-commonjs/components/Tooltip/Tooltip.js.map +1 -1
- package/lib-commonjs/components/Tooltip/Tooltip.types.d.ts +29 -33
- package/lib-commonjs/components/Tooltip/Tooltip.types.js.map +1 -1
- package/lib-commonjs/components/Tooltip/index.js.map +1 -1
- package/lib-commonjs/components/Tooltip/private/constants.js.map +1 -1
- package/lib-commonjs/components/Tooltip/renderTooltip.js +2 -2
- package/lib-commonjs/components/Tooltip/renderTooltip.js.map +1 -1
- package/lib-commonjs/components/Tooltip/useTooltip.d.ts +1 -3
- package/lib-commonjs/components/Tooltip/useTooltip.js +39 -54
- package/lib-commonjs/components/Tooltip/useTooltip.js.map +1 -1
- package/lib-commonjs/components/Tooltip/useTooltipStyles.js +3 -3
- package/lib-commonjs/components/Tooltip/useTooltipStyles.js.map +1 -1
- package/lib-commonjs/index.js.map +1 -1
- package/package.json +8 -10
package/Spec.md
CHANGED
@@ -44,31 +44,42 @@ v0 tooltips use a `trigger` property to render the tooltip's target component. H
|
|
44
44
|
|
45
45
|
# Sample Code
|
46
46
|
|
47
|
-
|
47
|
+
Label tooltip for an icon-only button:
|
48
48
|
|
49
|
-
|
49
|
+
```tsx
|
50
|
+
<Tooltip content="Copy" relationship="label">
|
51
|
+
<Button icon={<CopyRegular />} />
|
52
|
+
</Tooltip>
|
53
|
+
```
|
50
54
|
|
51
|
-
|
52
|
-
- A render function that takes the extra props to be added to the trigger element.
|
55
|
+
Description tooltip for a link:
|
53
56
|
|
54
57
|
```tsx
|
55
|
-
<
|
56
|
-
<a href="http://example.com">
|
57
|
-
|
58
|
-
|
59
|
-
</TooltipTrigger>
|
60
|
-
|
61
|
-
<TooltipTrigger tooltip="Label for an icon button" type="label">
|
62
|
-
<button href="http://example.com">
|
63
|
-
<SomeIcon />
|
64
|
-
</button>
|
65
|
-
</TooltipTrigger>
|
58
|
+
<Tooltip content="This is an example" relationship="description">
|
59
|
+
<a href="http://example.com">A link</a>
|
60
|
+
</Tooltip>
|
61
|
+
```
|
66
62
|
|
67
|
-
|
68
|
-
<ThirdPartyComponent />
|
69
|
-
</TooltipTrigger>
|
63
|
+
Tooltip with custom JSX content:
|
70
64
|
|
71
|
-
|
65
|
+
```tsx
|
66
|
+
<Tooltip content={<b>The content can be JSX</b>} relationship="label">
|
67
|
+
<Button />
|
68
|
+
</Tooltip>
|
69
|
+
```
|
70
|
+
|
71
|
+
Custom component as a trigger:
|
72
|
+
|
73
|
+
```tsx
|
74
|
+
<Tooltip content="Supports any component that accepts HTML attributes" relationship="label">
|
75
|
+
<FancyButton />
|
76
|
+
</Tooltip>
|
77
|
+
```
|
78
|
+
|
79
|
+
Render function for the trigger:
|
80
|
+
|
81
|
+
```tsx
|
82
|
+
<Tooltip content="The child can be a render function" relationship="description">
|
72
83
|
{triggerProps => (
|
73
84
|
<>
|
74
85
|
<div>
|
@@ -76,34 +87,37 @@ TooltipTrigger only supports a single child element, which can be either:
|
|
76
87
|
</div>
|
77
88
|
</>
|
78
89
|
)}
|
79
|
-
</
|
90
|
+
</Tooltip>
|
91
|
+
```
|
80
92
|
|
81
|
-
|
93
|
+
```tsx
|
94
|
+
<Tooltip
|
95
|
+
content="It can target an element other than its trigger"
|
96
|
+
relationship="description"
|
97
|
+
positioning={{ target: targetElement }}
|
98
|
+
>
|
82
99
|
<button>
|
83
|
-
Custom target:{
|
84
|
-
<div ref={targetRef} style={{ display: 'inline-block', width: '8px', height: '8px', background: 'red' }} />
|
100
|
+
Custom target: <div ref={setTargetElement} />
|
85
101
|
</button>
|
86
|
-
</
|
102
|
+
</Tooltip>
|
87
103
|
```
|
88
104
|
|
89
105
|
# Variants
|
90
106
|
|
91
|
-
- The tooltip
|
92
|
-
- The tooltip
|
107
|
+
- The tooltip supports higher contrast colors with `appearance="inverted"`.
|
108
|
+
- The tooltip supports rendering an arrow pointing to the target element, using `withArrow`.
|
93
109
|
|
94
110
|
# API
|
95
111
|
|
96
|
-
|
112
|
+
To attach a tooltip to an element, wrap it with a `Tooltip`. There is a `content` slot for the text of the tooltip itself.
|
113
|
+
|
114
|
+
Unlike most components, Tooltip doesn't have a root slot and doesn't allow native DOM props on the Tooltip itself. This is because it doesn't render any nodes inline around its trigger (it does _not_ wrap the element with a `<div>` for example). Instead, it attaches listeners to the child by cloning the JSX object and adding `onPointerEnter`, etc. listeners.
|
97
115
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
- [`TooltipTrigger`](#tooltiptrigger)
|
104
|
-
- [**@fluentui/react-tooltip**](#fluentuireact-tooltip)
|
105
|
-
- [`Tooltip`](#tooltip)
|
106
|
-
- [`TooltipProvider`](#tooltipprovider)
|
116
|
+
Tooltip only supports a single child element, which can be either:
|
117
|
+
|
118
|
+
- A native element or component that supports DOM attributes (the child can't be a string, for example).
|
119
|
+
- A render function that takes the extra props to be added to the trigger element.
|
120
|
+
- It is allowed to have a tooltip without a child (trigger) element, in which case it _must_ have a target set via the `positioning` prop, and its visibility must be controlled with the `visible` prop.
|
107
121
|
|
108
122
|
_A note about the terminology used for the elements that the tooltip is attached to:_
|
109
123
|
|
@@ -111,400 +125,250 @@ _A note about the terminology used for the elements that the tooltip is attached
|
|
111
125
|
- _The **target** is the element that the tooltip is anchored to (and the arrow points to)._
|
112
126
|
- _Almost always, these will both be the same element, but it is possible to specify them separately, so the tooltip can show up adjacent to a different element than the one that triggered it._
|
113
127
|
|
114
|
-
##
|
115
|
-
|
116
|
-
`react-tooltip-trigger` is a lightweight package that allows any component to add a tooltip without taking a dependency on the full `react-tooltip` package. It provides the basic functionality to render the tooltip; but it will only work if the `TooltipProvider` context is present.
|
128
|
+
## Types
|
117
129
|
|
118
|
-
###
|
130
|
+
### `Tooltip`
|
119
131
|
|
120
|
-
|
132
|
+
From [Tooltip.types.tsx](https://github.com/microsoft/fluentui/blob/master/packages/react-tooltip/src/components/Tooltip/Tooltip.types.tsx) in `@fluentui/react-tooltip`:
|
121
133
|
|
122
134
|
```ts
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
* but the tooltip may be flipped to the other side if there is not enough room.
|
128
|
-
*
|
129
|
-
* @defaultvalue above
|
130
|
-
*/
|
131
|
-
position?: 'above' | 'below' | 'before' | 'after';
|
132
|
-
|
133
|
-
/**
|
134
|
-
* How to align the tooltip along the edge of the target element.
|
135
|
-
*
|
136
|
-
* @defaultvalue center
|
137
|
-
*/
|
138
|
-
align?: 'top' | 'bottom' | 'start' | 'end' | 'center';
|
139
|
-
|
140
|
-
/**
|
141
|
-
* Color variant with a subtle look
|
142
|
-
*/
|
143
|
-
subtle?: boolean;
|
144
|
-
|
145
|
-
/**
|
146
|
-
* Do not render an arrow pointing to the target element
|
147
|
-
*/
|
148
|
-
noArrow?: boolean;
|
149
|
-
|
150
|
-
/**
|
151
|
-
* Distance between the tooltip and the target element, in pixels
|
152
|
-
*
|
153
|
-
* @defaultvalue 4
|
154
|
-
*/
|
155
|
-
offset?: number;
|
156
|
-
|
157
|
-
/**
|
158
|
-
* The arrow that points to the target element. This will be rendered by default unless `noArrow` is specified.
|
159
|
-
*/
|
160
|
-
arrow?: ShorthandProps<React.HTMLAttributes<HTMLElement> & React.RefAttributes<HTMLElement>>;
|
161
|
-
|
162
|
-
/**
|
163
|
-
* Imperative handle to show and hide the tooltip
|
164
|
-
*/
|
165
|
-
componentRef?: React.Ref<TooltipImperativeHandle>;
|
166
|
-
};
|
167
|
-
```
|
168
|
-
|
169
|
-
### TooltipImperativeHandle
|
170
|
-
|
171
|
-
The `TooltipImperativeHandle` is the imperative API used by `TooltipManager` to show and hide the tooltip.
|
172
|
-
|
173
|
-
```ts
|
174
|
-
export interface TooltipImperativeHandle {
|
135
|
+
/**
|
136
|
+
* Slot properties for Tooltip
|
137
|
+
*/
|
138
|
+
export type TooltipSlots = {
|
175
139
|
/**
|
176
|
-
*
|
140
|
+
* The text or JSX content of the tooltip.
|
177
141
|
*/
|
178
|
-
|
142
|
+
content: NonNullable<Slot<'div'>>;
|
143
|
+
};
|
179
144
|
|
145
|
+
/**
|
146
|
+
* Properties for Tooltip
|
147
|
+
*/
|
148
|
+
export type TooltipProps = ComponentProps<TooltipSlots> & {
|
180
149
|
/**
|
181
|
-
*
|
150
|
+
* (Required) Specifies whether this tooltip is acting as the description or label of its trigger element.
|
151
|
+
*
|
152
|
+
* * `label` - The tooltip sets the trigger's aria-label or aria-labelledby attribute. This is useful for buttons
|
153
|
+
* displaying only an icon, for example.
|
154
|
+
* * `description` - The tooltip sets the trigger's aria-description or aria-describedby attribute.
|
155
|
+
* * `inaccessible` - No aria attributes are set on the trigger. This makes the tooltip's content inaccessible to
|
156
|
+
* screen readers, and should only be used if the tooltip's text is available by some other means.
|
182
157
|
*/
|
183
|
-
|
158
|
+
relationship: 'label' | 'description' | 'inaccessible';
|
184
159
|
|
185
160
|
/**
|
186
|
-
*
|
161
|
+
* The tooltip can have a single JSX child, or a render function that accepts TooltipTriggerProps.
|
162
|
+
*
|
163
|
+
* If no child is provided, the tooltip's target must be set with the `positioning` prop, and its
|
164
|
+
* visibility must be controlled with the `visible` prop.
|
187
165
|
*/
|
188
|
-
|
189
|
-
}
|
190
|
-
|
191
|
-
|
192
|
-
### TooltipManager
|
193
|
-
|
194
|
-
The `TooltipManager` is responsible for managing the visibiltiy of the tooltips, including ensuring that only one tooltip is visible at once, and handling the delay to show or hide a tooltip.
|
195
|
-
|
196
|
-
This imperative interface is implemented by `TooltipProvider`, and used by `TooltipTrigger` to show and hide its tooltip based on events on the trigger element.
|
197
|
-
|
198
|
-
```ts
|
199
|
-
/**
|
200
|
-
* The tooltip manager is responsible for managing the visibiltiy of the tooltips,
|
201
|
-
* including ensuring that only one tooltip is visible at once, and handling the
|
202
|
-
* delay to show or hide a tooltip.
|
203
|
-
*
|
204
|
-
* This imperative interface is used by TooltipTrigger to show and hide its tooltip
|
205
|
-
* based on events on the trigger element.
|
206
|
-
*/
|
207
|
-
export interface TooltipManager {
|
208
|
-
showTooltip: (args: ShowTooltipArgs, reason: TooltipTriggerReason) => void;
|
209
|
-
hideTooltip: (trigger: HTMLElement, reason: TooltipTriggerReason) => void;
|
210
|
-
|
211
|
-
hideAll: () => void;
|
212
|
-
|
213
|
-
onPointerEnterTooltip: (tooltipRoot: HTMLElement) => void;
|
214
|
-
onPointerLeaveTooltip: (tooltipRoot: HTMLElement) => void;
|
215
|
-
}
|
216
|
-
|
217
|
-
/**
|
218
|
-
* The arguments to TooltipManager.showTooltip
|
219
|
-
*/
|
220
|
-
export type ShowTooltipArgs = {
|
221
|
-
tooltip: TooltipImperativeHandle;
|
222
|
-
trigger: HTMLElement;
|
223
|
-
target: HTMLElement;
|
224
|
-
showDelay: number;
|
225
|
-
hideDelay: number;
|
226
|
-
onlyIfTruncated?: boolean;
|
227
|
-
};
|
228
|
-
|
229
|
-
/**
|
230
|
-
* The source of the event that caused the tooltip to be shown or hidden
|
231
|
-
*/
|
232
|
-
export type TooltipTriggerReason = 'focus' | 'pointer';
|
233
|
-
```
|
234
|
-
|
235
|
-
### useTooltipContext
|
236
|
-
|
237
|
-
The tooltip hooks get the actual implementation of the TooltipManagerApi and Tooltip renderer via React context. By default this is `undefined`, and requires a `TooltipProvider` to provide the actual implementations.
|
238
|
-
|
239
|
-
```ts
|
240
|
-
export type TooltipContext = {
|
241
|
-
Tooltip: React.FC<TooltipProps & React.RefAttributes<HTMLElement>>;
|
242
|
-
manager: TooltipManager | undefined;
|
243
|
-
portalRoot: HTMLElement;
|
244
|
-
};
|
166
|
+
children?:
|
167
|
+
| (React.ReactElement & { ref?: React.Ref<unknown> })
|
168
|
+
| ((props: TooltipTriggerProps) => React.ReactElement | null)
|
169
|
+
| null;
|
245
170
|
|
246
|
-
export const internal__TooltipContext = React.createContext<TooltipContext>({
|
247
|
-
// These default values are replaced by TooltipProvider
|
248
|
-
Tooltip: () => null,
|
249
|
-
manager: undefined,
|
250
|
-
portalRoot: document.body,
|
251
|
-
});
|
252
|
-
|
253
|
-
export const useTooltipContext = () => React.useContext(internal__TooltipContext);
|
254
|
-
```
|
255
|
-
|
256
|
-
### TooltipTrigger
|
257
|
-
|
258
|
-
`TooltipTrigger` allows tooltips to be added to any focusable component that doesn't have its own `tooltip` prop. It supports a single JSX child, and works by cloning the JSX element in order to add the same `onPointerDown`, etc. listeners that are added by `useTooltipSlot`.
|
259
|
-
|
260
|
-
```ts
|
261
|
-
export type TooltipTriggerProps
|
262
|
-
= Pick<TooltipProps, 'position' | 'align' | 'subtle' | 'noArrow' | 'offset'> & {
|
263
171
|
/**
|
264
|
-
* The
|
265
|
-
*
|
266
|
-
*
|
267
|
-
*
|
172
|
+
* The tooltip's visual appearance.
|
173
|
+
* * `normal` - Uses the theme's background and text colors.
|
174
|
+
* * `inverted` - Higher contrast variant that uses the theme's inverted colors.
|
175
|
+
*
|
176
|
+
* @defaultvalue normal
|
268
177
|
*/
|
269
|
-
|
270
|
-
| React.ReactElement<React.HTMLAttributes<HTMLElement>>
|
271
|
-
| ((props: TooltipTriggerChildProps) => React.ReactNode);
|
178
|
+
appearance?: 'normal' | 'inverted';
|
272
179
|
|
273
180
|
/**
|
274
|
-
*
|
181
|
+
* Render an arrow pointing to the target element
|
182
|
+
*
|
183
|
+
* @defaultvalue false
|
275
184
|
*/
|
276
|
-
|
185
|
+
withArrow?: boolean;
|
277
186
|
|
278
187
|
/**
|
279
|
-
*
|
280
|
-
* This determines whether to set aria-describedby or aria-labelledby on the trigger element.
|
188
|
+
* Configure the positioning of the tooltip
|
281
189
|
*
|
282
|
-
* @defaultvalue
|
190
|
+
* @defaultvalue above
|
283
191
|
*/
|
284
|
-
|
192
|
+
positioning?: PositioningShorthand;
|
285
193
|
|
286
194
|
/**
|
287
|
-
*
|
195
|
+
* Control the tooltip's visibility programatically.
|
288
196
|
*
|
289
|
-
*
|
197
|
+
* This can be used in conjunction with onVisibleChange to modify the tooltip's show and hide behavior.
|
198
|
+
*
|
199
|
+
* If not provided, the visibility will be controlled by the tooltip itself, based on hover and focus events on the
|
200
|
+
* trigger (child) element.
|
290
201
|
*/
|
291
|
-
|
202
|
+
visible?: boolean;
|
292
203
|
|
293
204
|
/**
|
294
|
-
*
|
295
|
-
*
|
296
|
-
* @defaultvalue 250
|
205
|
+
* Notification when the visibility of the tooltip is changing
|
297
206
|
*/
|
298
|
-
|
207
|
+
onVisibleChange?: (
|
208
|
+
event: React.PointerEvent<HTMLElement> | React.FocusEvent<HTMLElement> | undefined,
|
209
|
+
data: OnVisibleChangeData,
|
210
|
+
) => void;
|
299
211
|
|
300
212
|
/**
|
301
|
-
*
|
213
|
+
* Delay before the tooltip is shown, in milliseconds.
|
214
|
+
*
|
215
|
+
* @defaultvalue 250
|
302
216
|
*/
|
303
|
-
|
217
|
+
showDelay?: number;
|
304
218
|
|
305
219
|
/**
|
306
|
-
*
|
220
|
+
* Delay before the tooltip is hidden, in milliseconds.
|
307
221
|
*
|
308
|
-
*
|
222
|
+
* @defaultvalue 250
|
309
223
|
*/
|
310
|
-
|
311
|
-
}
|
224
|
+
hideDelay?: number;
|
225
|
+
};
|
312
226
|
|
313
227
|
/**
|
314
|
-
* The
|
228
|
+
* The properties that are added to the trigger of the Tooltip
|
315
229
|
*/
|
316
|
-
export type
|
230
|
+
export type TooltipTriggerProps = {
|
231
|
+
ref?: React.Ref<never>;
|
232
|
+
} & Pick<
|
317
233
|
React.HTMLAttributes<HTMLElement>,
|
318
|
-
'onPointerEnter' | 'onPointerLeave' | 'onFocus' | 'onBlur' | 'aria-describedby' | 'aria-labelledby'
|
234
|
+
'onPointerEnter' | 'onPointerLeave' | 'onFocus' | 'onBlur' | 'aria-describedby' | 'aria-labelledby' | 'aria-label'
|
319
235
|
>;
|
320
236
|
|
321
237
|
/**
|
322
|
-
*
|
323
|
-
*/
|
324
|
-
export type TooltipTriggerShorthandProps = typeof tooltipTriggerShorthandProps[number];
|
325
|
-
|
326
|
-
/**
|
327
|
-
* Names of TooltipTriggerProps that have a default value in useTooltipTrigger
|
238
|
+
* Data for the Tooltip's onVisibleChange event.
|
328
239
|
*/
|
329
|
-
export type
|
330
|
-
|
331
|
-
|
332
|
-
ResolvedShorthandProps<
|
333
|
-
TooltipTriggerProps & {
|
334
|
-
manager: TooltipManager | undefined;
|
335
|
-
portalRoot: HTMLElement;
|
336
|
-
tooltipRef: React.MutableRefObject<TooltipImperativeHandle | null>;
|
337
|
-
},
|
338
|
-
TooltipTriggerShorthandProps
|
339
|
-
>,
|
340
|
-
TooltipTriggerDefaultedProps
|
240
|
+
export type OnVisibleChangeData = {
|
241
|
+
visible: boolean;
|
242
|
+
};
|
341
243
|
```
|
342
244
|
|
343
|
-
|
344
|
-
|
345
|
-
The `react-tooltip` package contains the bulk of the implementation of tooltips, including rendering, styling, positioning, lifetime management, etc.
|
245
|
+
### `TooltipContext`
|
346
246
|
|
347
|
-
|
247
|
+
The context is included at the app root on `FluentProvider` and is used by `Tooltip` to ensure that only one is visible at once.
|
348
248
|
|
349
|
-
|
350
|
-
|
351
|
-
The `TooltipProps` interface is defined in the `react-tooltip-trigger` package.
|
249
|
+
From [TooltipContext.ts](https://github.com/microsoft/fluentui/blob/master/packages/react-shared-contexts/src/TooltipContext/TooltipContext.ts) in `@fluentui/react-shared-contexts`:
|
352
250
|
|
353
251
|
```ts
|
354
|
-
import { TooltipProps } from '@fluentui/react-tooltip-trigger';
|
355
|
-
|
356
|
-
export { TooltipProps };
|
357
|
-
|
358
252
|
/**
|
359
|
-
*
|
253
|
+
* The context provided by TooltipProvider
|
360
254
|
*/
|
361
|
-
export type
|
255
|
+
export type TooltipContextType = {
|
256
|
+
/**
|
257
|
+
* When a tooltip is shown, it sets itself as the visibleTooltip.
|
258
|
+
* The next tooltip to become visible can use it to hide the previous tooltip immediately.
|
259
|
+
*/
|
260
|
+
visibleTooltip?: {
|
261
|
+
hide: () => void;
|
262
|
+
};
|
263
|
+
};
|
362
264
|
|
363
265
|
/**
|
364
|
-
*
|
266
|
+
* Context shared by all of the tooltips in the app
|
365
267
|
*/
|
366
|
-
export
|
367
|
-
|
368
|
-
export type TooltipState = ComponentState<
|
369
|
-
React.Ref<HTMLElement>,
|
370
|
-
TooltipProps & {
|
371
|
-
visible: boolean;
|
372
|
-
},
|
373
|
-
TooltipShorthandProps,
|
374
|
-
TooltipDefaultedProps
|
375
|
-
>;
|
376
|
-
```
|
377
|
-
|
378
|
-
### TooltipProvider
|
379
|
-
|
380
|
-
`TooltipProvider` is responsible for providing the actual implementation of `TooltipManager` and `Tooltip`. It uses a React context to that contains those when it is included in the tree. This context will also be included into `FluentContext`.
|
381
|
-
|
382
|
-
```ts
|
383
|
-
export type TooltipProviderProps = ComponentProps &
|
384
|
-
React.HTMLAttributes<HTMLElement> & {
|
385
|
-
// TooltipProvider has no additional props
|
386
|
-
};
|
387
|
-
|
388
|
-
export type TooltipProviderState = ComponentState<
|
389
|
-
React.RefObject<HTMLElement>,
|
390
|
-
TooltipProviderProps & {
|
391
|
-
manager: TooltipManager;
|
392
|
-
portalRoot: HTMLElement;
|
393
|
-
}
|
394
|
-
>;
|
268
|
+
export const TooltipContext = React.createContext<TooltipContextType>({});
|
395
269
|
```
|
396
270
|
|
397
271
|
# Structure
|
398
272
|
|
399
|
-
##
|
273
|
+
## Tooltip as a label
|
274
|
+
|
275
|
+
### JSX tree
|
400
276
|
|
401
277
|
```tsx
|
402
|
-
<
|
403
|
-
<
|
404
|
-
<
|
405
|
-
</
|
406
|
-
|
407
|
-
<button>...</button>
|
408
|
-
</TooltipTrigger>
|
409
|
-
</TooltipProvider>
|
278
|
+
<Tooltip content="Example" relationship="label">
|
279
|
+
<button>
|
280
|
+
<svg>...</svg>
|
281
|
+
</button>
|
282
|
+
</Tooltip>
|
410
283
|
```
|
411
284
|
|
412
|
-
|
285
|
+
### DOM
|
413
286
|
|
414
|
-
|
287
|
+
Tooltip with `relationship="label"` is not rendered when it is not visible. Its content is used as the `aria-label` of the control. The Tooltip will be rendered once it is visible; see the next example for what the DOM structure looks like in that case.
|
415
288
|
|
416
|
-
```
|
289
|
+
```html
|
417
290
|
<body>
|
418
|
-
|
419
|
-
|
420
|
-
<button aria-
|
421
|
-
|
422
|
-
|
423
|
-
<div role="tooltip" id="tooltip-1" {/* Tooltip */}>
|
424
|
-
<div {/* Arrow */} />
|
425
|
-
Example tooltip
|
426
|
-
</div>
|
427
|
-
<div role="tooltip" id="tooltip-2" class="... (display: none) ..." {/* Tooltip */}>
|
428
|
-
<div {/* Arrow */} />
|
429
|
-
Button with a tooltip for a label
|
430
|
-
</div>
|
431
|
-
</div>
|
291
|
+
<!-- App root -->
|
292
|
+
<div>
|
293
|
+
<button aria-label="Example" onPointerEnter="{...}" onPointerLeave="{...}" onFocus="{...}" onBlur="{...}">
|
294
|
+
<svg>...</svg>
|
295
|
+
</button>
|
432
296
|
</div>
|
433
297
|
</body>
|
434
298
|
```
|
435
299
|
|
436
|
-
##
|
300
|
+
## Tooltip as a description
|
437
301
|
|
438
|
-
|
302
|
+
### JSX tree
|
439
303
|
|
440
304
|
```tsx
|
441
|
-
<
|
442
|
-
|
443
|
-
|
444
|
-
portalRoot: state.portalRoot,
|
445
|
-
Tooltip,
|
446
|
-
}}
|
447
|
-
>
|
448
|
-
{children}
|
449
|
-
<slots.root {...rootProps} />
|
450
|
-
</internal__TooltipContext.Provider>
|
305
|
+
<Tooltip content="Example description of the button" relationship="description" withArrow>
|
306
|
+
<button>The Button</button>
|
307
|
+
</Tooltip>
|
451
308
|
```
|
452
309
|
|
453
|
-
|
454
|
-
|
455
|
-
```tsx
|
456
|
-
<slots.root {...slotProps.root}>
|
457
|
-
<slots.arrow {...slotProps.arrow} />
|
458
|
-
{state.children}
|
459
|
-
</slots.root>
|
460
|
-
```
|
310
|
+
### DOM
|
461
311
|
|
462
|
-
`
|
312
|
+
Tooltip with `relationship="description"` is always rendered because it's used as the `aria-describedby` of the control, which always has to point to a valid DOM element even if it's not visible.
|
463
313
|
|
464
|
-
|
314
|
+
```html
|
315
|
+
<body>
|
316
|
+
<!-- App root -->
|
317
|
+
<div>
|
318
|
+
<button aria-describedby="tooltip-2" onPointerEnter="{...}" onPointerLeave="{...}" onFocus="{...}" onBlur="{...}">
|
319
|
+
The Button
|
320
|
+
</button>
|
321
|
+
</div>
|
465
322
|
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
323
|
+
<!-- Portal for Tooltip -->
|
324
|
+
<div>
|
325
|
+
<div role="tooltip" id="tooltip-2" class="{tooltip}">
|
326
|
+
<div class="{arrow}"></div>
|
327
|
+
Example description of the button
|
328
|
+
</div>
|
329
|
+
</div>
|
330
|
+
</body>
|
471
331
|
```
|
472
332
|
|
473
333
|
# Migration
|
474
334
|
|
475
|
-
See MIGRATION.md.
|
335
|
+
See [MIGRATION.md](./MIGRATION.md).
|
476
336
|
|
477
337
|
# Behaviors
|
478
338
|
|
479
|
-
|
480
|
-
|
481
|
-
- There is only ever one tooltip visible at once.
|
482
|
-
- The tooltip shows 250ms (by default) after the trigger element receives either mouse/pointer hover or keyboard focus, with the following exceptions:
|
483
|
-
- If another tooltip is currently visible, the new tooltip will immediately replace the old one without any delay.
|
484
|
-
- If `onlyIfTruncated` is true, then the tooltip will only show if the target element's content is overflowing.
|
485
|
-
- The tooltip hides 250ms (by default) after the trigger element loses focus, with the following exceptions:
|
486
|
-
- The tooltip will not hide if the pointer is hovering on the tooltip itself
|
487
|
-
- If the tooltip was triggered by getting focus, then moving the mouse out of the element won't hide it (it'll hide when the element loses focus, or another tooltip is triggered).
|
488
|
-
- The tooltip hides immediately when the user presses Esc.
|
339
|
+
## Visibility
|
489
340
|
|
490
|
-
-
|
341
|
+
- The tooltip shows:
|
342
|
+
- After `showDelay` (250ms default) from when the mouse/pointer enters the trigger.
|
343
|
+
- After `showDelay` (250ms default) from when the trigger gets keyboard focus.
|
344
|
+
- _Immediately_ (ignoring `showDelay`) if it is triggered while another tooltip is currently visible.
|
345
|
+
- The tooltip hides:
|
346
|
+
- After `hideDelay` (250ms default) from when the mouse/pointer leaves BOTH the trigger AND the tooltip itself.
|
347
|
+
- _Immediately_ when the trigger loses keyboard focus.
|
348
|
+
- _Immediately_ when the ESC key is pressed.
|
349
|
+
- _Immediately_ when another tooltip is shown.
|
491
350
|
|
492
|
-
|
493
|
-
- The placement is handled by the react-positioning package, which uses PopperJS.
|
351
|
+
There is only ever one tooltip visible at once (coordinated using `TooltipContext`). If another tooltip is triggered while there's one currently visible, the previous one hides and the new one shows immediately, without delay.
|
494
352
|
|
495
|
-
|
353
|
+
### Placement
|
496
354
|
|
497
|
-
|
355
|
+
The tooltip is placed relative to its target element based on the `positioning` prop. The placement is handled by the `@fluentui/react-positioning` package, which uses PopperJS.
|
498
356
|
|
499
|
-
|
357
|
+
### Focus
|
500
358
|
|
501
|
-
|
359
|
+
Content within the tooltip is not focusable, and can't be interacted with directly by keyboard or mouse.
|
502
360
|
|
503
361
|
# Accessibility
|
504
362
|
|
505
|
-
- ARIA design pattern:
|
506
|
-
- The Tooltip
|
507
|
-
-
|
508
|
-
- The
|
363
|
+
- ARIA design pattern: https://www.w3.org/TR/wai-aria-practices-1.2/#tooltip.
|
364
|
+
- The Tooltip content element has `role="tooltip"`.
|
365
|
+
- If Tooltip has `relationship="label"` with simple string content:
|
366
|
+
- The content is set as the trigger's `aria-label`.
|
367
|
+
- The tooltip is only rendered while it is visible.
|
368
|
+
- If Tooltip has `relationship="label"` with JSX content, OR `relationship="description"` (string or JSX):
|
369
|
+
- The tooltip's ID is set as the trigger's `aria-labelledby` or `aria-describedby` (an ID is generated if not provided).
|
370
|
+
- The tooltip is always rendered, even while hidden.
|
371
|
+
- While hidden, the tooltip itself is styled with `display: none`.
|
509
372
|
- The Tooltip itself can never receive focus.
|
510
373
|
- The Tooltip should never contain focusable elements.
|
374
|
+
- The trigger for the Tooltip should be focusable.
|