@fluentui/react-tooltip 0.0.0-nightly-20220302-0405.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 +3319 -0
- package/CHANGELOG.md +1147 -0
- package/LICENSE +15 -0
- package/MIGRATION.md +68 -0
- package/README.md +5 -0
- package/Spec.md +374 -0
- package/dist/react-tooltip.d.ts +154 -0
- package/lib/Tooltip.d.ts +1 -0
- package/lib/Tooltip.js +2 -0
- package/lib/Tooltip.js.map +1 -0
- package/lib/components/Tooltip/Tooltip.d.ts +7 -0
- package/lib/components/Tooltip/Tooltip.js +15 -0
- package/lib/components/Tooltip/Tooltip.js.map +1 -0
- package/lib/components/Tooltip/Tooltip.types.d.ts +117 -0
- package/lib/components/Tooltip/Tooltip.types.js +2 -0
- package/lib/components/Tooltip/Tooltip.types.js.map +1 -0
- package/lib/components/Tooltip/index.d.ts +5 -0
- package/lib/components/Tooltip/index.js +6 -0
- package/lib/components/Tooltip/index.js.map +1 -0
- package/lib/components/Tooltip/private/constants.d.ts +12 -0
- package/lib/components/Tooltip/private/constants.js +14 -0
- package/lib/components/Tooltip/private/constants.js.map +1 -0
- package/lib/components/Tooltip/renderTooltip.d.ts +5 -0
- package/lib/components/Tooltip/renderTooltip.js +19 -0
- package/lib/components/Tooltip/renderTooltip.js.map +1 -0
- package/lib/components/Tooltip/useTooltip.d.ts +10 -0
- package/lib/components/Tooltip/useTooltip.js +193 -0
- package/lib/components/Tooltip/useTooltip.js.map +1 -0
- package/lib/components/Tooltip/useTooltipStyles.d.ts +6 -0
- package/lib/components/Tooltip/useTooltipStyles.js +95 -0
- package/lib/components/Tooltip/useTooltipStyles.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib/tsdoc-metadata.json +11 -0
- package/lib-commonjs/Tooltip.d.ts +1 -0
- package/lib-commonjs/Tooltip.js +10 -0
- package/lib-commonjs/Tooltip.js.map +1 -0
- package/lib-commonjs/components/Tooltip/Tooltip.d.ts +7 -0
- package/lib-commonjs/components/Tooltip/Tooltip.js +27 -0
- package/lib-commonjs/components/Tooltip/Tooltip.js.map +1 -0
- package/lib-commonjs/components/Tooltip/Tooltip.types.d.ts +117 -0
- package/lib-commonjs/components/Tooltip/Tooltip.types.js +6 -0
- package/lib-commonjs/components/Tooltip/Tooltip.types.js.map +1 -0
- package/lib-commonjs/components/Tooltip/index.d.ts +5 -0
- package/lib-commonjs/components/Tooltip/index.js +18 -0
- package/lib-commonjs/components/Tooltip/index.js.map +1 -0
- package/lib-commonjs/components/Tooltip/private/constants.d.ts +12 -0
- package/lib-commonjs/components/Tooltip/private/constants.js +21 -0
- package/lib-commonjs/components/Tooltip/private/constants.js.map +1 -0
- package/lib-commonjs/components/Tooltip/renderTooltip.d.ts +5 -0
- package/lib-commonjs/components/Tooltip/renderTooltip.js +31 -0
- package/lib-commonjs/components/Tooltip/renderTooltip.js.map +1 -0
- package/lib-commonjs/components/Tooltip/useTooltip.d.ts +10 -0
- package/lib-commonjs/components/Tooltip/useTooltip.js +207 -0
- package/lib-commonjs/components/Tooltip/useTooltip.js.map +1 -0
- package/lib-commonjs/components/Tooltip/useTooltipStyles.d.ts +6 -0
- package/lib-commonjs/components/Tooltip/useTooltipStyles.js +108 -0
- package/lib-commonjs/components/Tooltip/useTooltipStyles.js.map +1 -0
- package/lib-commonjs/index.d.ts +1 -0
- package/lib-commonjs/index.js +10 -0
- package/lib-commonjs/index.js.map +1 -0
- package/package.json +66 -0
package/LICENSE
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
@fluentui/react-tooltip
|
2
|
+
|
3
|
+
Copyright (c) Microsoft Corporation
|
4
|
+
|
5
|
+
All rights reserved.
|
6
|
+
|
7
|
+
MIT License
|
8
|
+
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
14
|
+
|
15
|
+
Note: Usage of the fonts and icons referenced in Fluent UI React is subject to the terms listed at https://aka.ms/fluentui-assets-license
|
package/MIGRATION.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Tooltip Migration
|
2
|
+
|
3
|
+
## STATUS: WIP 🚧
|
4
|
+
|
5
|
+
This Migration guide is a work in progress and is not yet ready for use.
|
6
|
+
|
7
|
+
## Migration from v8
|
8
|
+
|
9
|
+
TooltipHost is replaced by Tooltip itself, as the wrapper around the element that should receive a tooltip.
|
10
|
+
|
11
|
+
- `Tooltip`
|
12
|
+
- `calloutProps`
|
13
|
+
- `isBeakVisible` => `withArrow`
|
14
|
+
- `beakWidth` => Not supported.
|
15
|
+
- `gapSpace` => Not supported.
|
16
|
+
- `doNotLayer` => Not supported. Tooltips are always layered by rendering in a Portal.
|
17
|
+
- `setInitialFocus` => Not supported. Tooltips can't be focused, by design.
|
18
|
+
- `componentRef` => Not supported. Tooltips can be controlled declaratively with props like `visible`, instead of using an imperative API like `componentRef`.
|
19
|
+
- `delay` => `showDelay`
|
20
|
+
- `directionalHint` => `positioning`
|
21
|
+
- `topLeftEdge` => `positioning="above-start"`
|
22
|
+
- `topCenter` => `positioning="above"`
|
23
|
+
- `topRightEdge` => `positioning="above-end"`
|
24
|
+
- `topAutoEdge` => Not supported
|
25
|
+
- `bottomLeftEdge` => `positioning="below-start"`
|
26
|
+
- `bottomCenter` => `positioning="below"`
|
27
|
+
- `bottomRightEdge` => `positioning="below-end"`
|
28
|
+
- `bottomAutoEdge` => Not supported
|
29
|
+
- `leftTopEdge` => `positioning="before-top"`
|
30
|
+
- `leftCenter` => `positioning="before"`
|
31
|
+
- `leftBottomEdge` => `positioning="before-bottom"`
|
32
|
+
- `rightTopEdge` => `positioning="after-top"`
|
33
|
+
- `rightCenter` => `positioning="after"`
|
34
|
+
- `rightBottomEdge` => `positioning="after-bottom"`
|
35
|
+
- `directionalHintForRTL` => Automatic based on whether the element is in an RTL context according to `FluentProvider`.
|
36
|
+
- `maxWidth` => Supported only through CSS styling of the `content` slot.
|
37
|
+
- `onRenderContent` => Set the `content` slot to a custom render function.
|
38
|
+
- `TooltipHost` => The tooltip itself is the "host".
|
39
|
+
- `closeDelay` => `hideDelay`
|
40
|
+
- `hostClassName` => Not needed because there is no element rendered inline by Tooltip
|
41
|
+
- `onTooltipToggle` => `onVisibleChange`
|
42
|
+
- `overflowMode` => Not supported. If this behavior is needed, the tooltip's visibility can be controlled using the `visible` prop and `onVisibleChange` event.
|
43
|
+
|
44
|
+
## Migration from v0
|
45
|
+
|
46
|
+
The v9 Tooltip swaps the meaning of children between content and trigger. In v0, Tooltip's children is the tooltip content, and its trigger is a prop. In v9, that is swapped: Tooltip's children is the trigger, and its content is a prop.
|
47
|
+
|
48
|
+
- `Tooltip`
|
49
|
+
- children => `content`
|
50
|
+
- `trigger` => children
|
51
|
+
- `defaultOpen` => Not supported. The tooltip's visibility can be controlled using the `visible` prop and `onVisibleChange` event.
|
52
|
+
- `mountNode` => Not supported
|
53
|
+
- `open` => `visible`
|
54
|
+
- `onOpenChange` => `onVisibleChange`
|
55
|
+
- `pointing` => `withArrow`
|
56
|
+
- `mouseEnterDelay` => `showDelay`
|
57
|
+
- `mouseLeaveDelay` => `hideDelay`
|
58
|
+
- `subtle={true}` = `appearance="normal"` (default)
|
59
|
+
- `subtle={false}` => `appearance="inverted"`
|
60
|
+
- Positioning props are now attributes of the `positioning` prop:
|
61
|
+
- `flipBoundary` => `positioning.flipBoundary`
|
62
|
+
- `offset` => `positioning.offset`
|
63
|
+
- `overflowBoundary` => `positioning.overflowBoundary`
|
64
|
+
- `popperRef` => `positioning.popperRef`
|
65
|
+
- `position` => `positioning.position`
|
66
|
+
- `align` => `positioning.align`
|
67
|
+
- `positionFixed` => `positioning.positionFixed`
|
68
|
+
- `target` => `positioning.target`
|
package/README.md
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
# @fluentui/react-tooltip
|
2
|
+
|
3
|
+
**React Tooltip components for [Fluent UI React](https://developer.microsoft.com/en-us/fluentui)**
|
4
|
+
|
5
|
+
These are not production-ready components and **should never be used in product**. This space is useful for testing new components whose APIs might change before final release.
|
package/Spec.md
ADDED
@@ -0,0 +1,374 @@
|
|
1
|
+
# Tooltip Spec
|
2
|
+
|
3
|
+
Tooltips provide additional information about an element when hovering or focusing on the element.
|
4
|
+
|
5
|
+
## Prior Art
|
6
|
+
|
7
|
+
- OpenUI Tooltip resarch: https://open-ui.org/components/tooltip.research
|
8
|
+
- GitHub Epic issue: [Tooltip Convergence #16735](https://github.com/microsoft/fluentui/issues/16735)
|
9
|
+
|
10
|
+
### Tooltips in v8/Fabric
|
11
|
+
|
12
|
+
v8 tooltips use a `TooltipHost` wrapped around the target element to provide tooltip functionality. This creates a `div` around the element that listens for mouse and focus events.
|
13
|
+
|
14
|
+
The `Tooltip` component renders as a `Callout`, and supports all `Callout` props.
|
15
|
+
|
16
|
+
```tsx
|
17
|
+
<TooltipHost
|
18
|
+
content="This is the tooltip content"
|
19
|
+
// This id is used on the tooltip itself, not the host
|
20
|
+
// (so an element with this id only exists when the tooltip is shown)
|
21
|
+
id={tooltipId}
|
22
|
+
calloutProps={calloutProps}
|
23
|
+
styles={hostStyles}
|
24
|
+
>
|
25
|
+
<DefaultButton aria-describedby={tooltipId}>Hover over me</DefaultButton>
|
26
|
+
</TooltipHost>
|
27
|
+
```
|
28
|
+
|
29
|
+
#### Drawbacks
|
30
|
+
|
31
|
+
There are a few drawbacks with this approach to adding tooltips, which are outlined in [☂ Tooltip: open issues to resolve in converged approach #15102](https://github.com/microsoft/fluentui/issues/15102), and summarized below:
|
32
|
+
|
33
|
+
- The wrapper `div` created by `TooltipHost` can cause layout issues for the component. It also doesn't always result in proper positioning for the tooltip.
|
34
|
+
- The API is overly complex.
|
35
|
+
- There's no coordination between tooltips on a page. For example, moving the mouse between two elements with tooltips should cause the second tooltip to appear immediately without fading in/out.
|
36
|
+
|
37
|
+
### Tooltips in v0/Northstar
|
38
|
+
|
39
|
+
v0 tooltips use a `trigger` property to render the tooltip's target component. However, unlike v8 it does not create a wrapper `div` around the target component, but instead adds listeners to the target component's props.
|
40
|
+
|
41
|
+
```tsx
|
42
|
+
<Tooltip content="Example tooltip" trigger={<Button content="A button" />} />
|
43
|
+
```
|
44
|
+
|
45
|
+
# Sample Code
|
46
|
+
|
47
|
+
Label tooltip for an icon-only button:
|
48
|
+
|
49
|
+
```tsx
|
50
|
+
<Tooltip content="Copy" relationship="label">
|
51
|
+
<Button icon={<CopyRegular />} />
|
52
|
+
</Tooltip>
|
53
|
+
```
|
54
|
+
|
55
|
+
Description tooltip for a link:
|
56
|
+
|
57
|
+
```tsx
|
58
|
+
<Tooltip content="This is an example" relationship="description">
|
59
|
+
<a href="http://example.com">A link</a>
|
60
|
+
</Tooltip>
|
61
|
+
```
|
62
|
+
|
63
|
+
Tooltip with custom JSX content:
|
64
|
+
|
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">
|
83
|
+
{triggerProps => (
|
84
|
+
<>
|
85
|
+
<div>
|
86
|
+
<button {...triggerProps}>The trigger element</button>
|
87
|
+
</div>
|
88
|
+
</>
|
89
|
+
)}
|
90
|
+
</Tooltip>
|
91
|
+
```
|
92
|
+
|
93
|
+
```tsx
|
94
|
+
<Tooltip
|
95
|
+
content="It can target an element other than its trigger"
|
96
|
+
relationship="description"
|
97
|
+
positioning={{ target: targetElement }}
|
98
|
+
>
|
99
|
+
<button>
|
100
|
+
Custom target: <div ref={setTargetElement} />
|
101
|
+
</button>
|
102
|
+
</Tooltip>
|
103
|
+
```
|
104
|
+
|
105
|
+
# Variants
|
106
|
+
|
107
|
+
- The tooltip supports higher contrast colors with `appearance="inverted"`.
|
108
|
+
- The tooltip supports rendering an arrow pointing to the target element, using `withArrow`.
|
109
|
+
|
110
|
+
# API
|
111
|
+
|
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.
|
115
|
+
|
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.
|
121
|
+
|
122
|
+
_A note about the terminology used for the elements that the tooltip is attached to:_
|
123
|
+
|
124
|
+
- _The **trigger** is the element that causes the tooltip to open._
|
125
|
+
- _The **target** is the element that the tooltip is anchored to (and the arrow points to)._
|
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._
|
127
|
+
|
128
|
+
## Types
|
129
|
+
|
130
|
+
### `Tooltip`
|
131
|
+
|
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`:
|
133
|
+
|
134
|
+
```ts
|
135
|
+
/**
|
136
|
+
* Slot properties for Tooltip
|
137
|
+
*/
|
138
|
+
export type TooltipSlots = {
|
139
|
+
/**
|
140
|
+
* The text or JSX content of the tooltip.
|
141
|
+
*/
|
142
|
+
content: NonNullable<Slot<'div'>>;
|
143
|
+
};
|
144
|
+
|
145
|
+
/**
|
146
|
+
* Properties for Tooltip
|
147
|
+
*/
|
148
|
+
export type TooltipProps = ComponentProps<TooltipSlots> & {
|
149
|
+
/**
|
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.
|
157
|
+
*/
|
158
|
+
relationship: 'label' | 'description' | 'inaccessible';
|
159
|
+
|
160
|
+
/**
|
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.
|
165
|
+
*/
|
166
|
+
children?:
|
167
|
+
| (React.ReactElement & { ref?: React.Ref<unknown> })
|
168
|
+
| ((props: TooltipTriggerProps) => React.ReactElement | null)
|
169
|
+
| null;
|
170
|
+
|
171
|
+
/**
|
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
|
177
|
+
*/
|
178
|
+
appearance?: 'normal' | 'inverted';
|
179
|
+
|
180
|
+
/**
|
181
|
+
* Render an arrow pointing to the target element
|
182
|
+
*
|
183
|
+
* @defaultvalue false
|
184
|
+
*/
|
185
|
+
withArrow?: boolean;
|
186
|
+
|
187
|
+
/**
|
188
|
+
* Configure the positioning of the tooltip
|
189
|
+
*
|
190
|
+
* @defaultvalue above
|
191
|
+
*/
|
192
|
+
positioning?: PositioningShorthand;
|
193
|
+
|
194
|
+
/**
|
195
|
+
* Control the tooltip's visibility programatically.
|
196
|
+
*
|
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.
|
201
|
+
*/
|
202
|
+
visible?: boolean;
|
203
|
+
|
204
|
+
/**
|
205
|
+
* Notification when the visibility of the tooltip is changing
|
206
|
+
*/
|
207
|
+
onVisibleChange?: (
|
208
|
+
event: React.PointerEvent<HTMLElement> | React.FocusEvent<HTMLElement> | undefined,
|
209
|
+
data: OnVisibleChangeData,
|
210
|
+
) => void;
|
211
|
+
|
212
|
+
/**
|
213
|
+
* Delay before the tooltip is shown, in milliseconds.
|
214
|
+
*
|
215
|
+
* @defaultvalue 250
|
216
|
+
*/
|
217
|
+
showDelay?: number;
|
218
|
+
|
219
|
+
/**
|
220
|
+
* Delay before the tooltip is hidden, in milliseconds.
|
221
|
+
*
|
222
|
+
* @defaultvalue 250
|
223
|
+
*/
|
224
|
+
hideDelay?: number;
|
225
|
+
};
|
226
|
+
|
227
|
+
/**
|
228
|
+
* The properties that are added to the trigger of the Tooltip
|
229
|
+
*/
|
230
|
+
export type TooltipTriggerProps = {
|
231
|
+
ref?: React.Ref<never>;
|
232
|
+
} & Pick<
|
233
|
+
React.HTMLAttributes<HTMLElement>,
|
234
|
+
'onPointerEnter' | 'onPointerLeave' | 'onFocus' | 'onBlur' | 'aria-describedby' | 'aria-labelledby' | 'aria-label'
|
235
|
+
>;
|
236
|
+
|
237
|
+
/**
|
238
|
+
* Data for the Tooltip's onVisibleChange event.
|
239
|
+
*/
|
240
|
+
export type OnVisibleChangeData = {
|
241
|
+
visible: boolean;
|
242
|
+
};
|
243
|
+
```
|
244
|
+
|
245
|
+
### `TooltipContext`
|
246
|
+
|
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.
|
248
|
+
|
249
|
+
From [TooltipContext.ts](https://github.com/microsoft/fluentui/blob/master/packages/react-shared-contexts/src/TooltipContext/TooltipContext.ts) in `@fluentui/react-shared-contexts`:
|
250
|
+
|
251
|
+
```ts
|
252
|
+
/**
|
253
|
+
* The context provided by TooltipProvider
|
254
|
+
*/
|
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
|
+
};
|
264
|
+
|
265
|
+
/**
|
266
|
+
* Context shared by all of the tooltips in the app
|
267
|
+
*/
|
268
|
+
export const TooltipContext = React.createContext<TooltipContextType>({});
|
269
|
+
```
|
270
|
+
|
271
|
+
# Structure
|
272
|
+
|
273
|
+
## Tooltip as a label
|
274
|
+
|
275
|
+
### JSX tree
|
276
|
+
|
277
|
+
```tsx
|
278
|
+
<Tooltip content="Example" relationship="label">
|
279
|
+
<button>
|
280
|
+
<svg>...</svg>
|
281
|
+
</button>
|
282
|
+
</Tooltip>
|
283
|
+
```
|
284
|
+
|
285
|
+
### DOM
|
286
|
+
|
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.
|
288
|
+
|
289
|
+
```html
|
290
|
+
<body>
|
291
|
+
<!-- App root -->
|
292
|
+
<div>
|
293
|
+
<button aria-label="Example" onPointerEnter="{...}" onPointerLeave="{...}" onFocus="{...}" onBlur="{...}">
|
294
|
+
<svg>...</svg>
|
295
|
+
</button>
|
296
|
+
</div>
|
297
|
+
</body>
|
298
|
+
```
|
299
|
+
|
300
|
+
## Tooltip as a description
|
301
|
+
|
302
|
+
### JSX tree
|
303
|
+
|
304
|
+
```tsx
|
305
|
+
<Tooltip content="Example description of the button" relationship="description" withArrow>
|
306
|
+
<button>The Button</button>
|
307
|
+
</Tooltip>
|
308
|
+
```
|
309
|
+
|
310
|
+
### DOM
|
311
|
+
|
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.
|
313
|
+
|
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>
|
322
|
+
|
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>
|
331
|
+
```
|
332
|
+
|
333
|
+
# Migration
|
334
|
+
|
335
|
+
See [MIGRATION.md](./MIGRATION.md).
|
336
|
+
|
337
|
+
# Behaviors
|
338
|
+
|
339
|
+
## Visibility
|
340
|
+
|
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.
|
350
|
+
|
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.
|
352
|
+
|
353
|
+
### Placement
|
354
|
+
|
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.
|
356
|
+
|
357
|
+
### Focus
|
358
|
+
|
359
|
+
Content within the tooltip is not focusable, and can't be interacted with directly by keyboard or mouse.
|
360
|
+
|
361
|
+
# Accessibility
|
362
|
+
|
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`.
|
372
|
+
- The Tooltip itself can never receive focus.
|
373
|
+
- The Tooltip should never contain focusable elements.
|
374
|
+
- The trigger for the Tooltip should be focusable.
|
@@ -0,0 +1,154 @@
|
|
1
|
+
import type { ComponentProps } from '@fluentui/react-utilities';
|
2
|
+
import type { ComponentState } from '@fluentui/react-utilities';
|
3
|
+
import type { FluentTriggerComponent } from '@fluentui/react-utilities';
|
4
|
+
import type { PositioningShorthand } from '@fluentui/react-positioning';
|
5
|
+
import * as React_2 from 'react';
|
6
|
+
import type { Slot } from '@fluentui/react-utilities';
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Data for the Tooltip's onVisibleChange event.
|
10
|
+
*/
|
11
|
+
export declare type OnVisibleChangeData = {
|
12
|
+
visible: boolean;
|
13
|
+
};
|
14
|
+
|
15
|
+
/**
|
16
|
+
* Render the final JSX of Tooltip
|
17
|
+
*/
|
18
|
+
export declare const renderTooltip_unstable: (state: TooltipState) => JSX.Element;
|
19
|
+
|
20
|
+
/**
|
21
|
+
* A tooltip provides light weight contextual information on top of its target element.
|
22
|
+
*/
|
23
|
+
export declare const Tooltip: React_2.FC<TooltipProps> & FluentTriggerComponent;
|
24
|
+
|
25
|
+
export declare const tooltipClassName = "fui-Tooltip";
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Properties and state for Tooltip
|
29
|
+
*/
|
30
|
+
declare type TooltipCommons = {
|
31
|
+
/**
|
32
|
+
* (Required) Specifies whether this tooltip is acting as the description or label of its trigger element.
|
33
|
+
*
|
34
|
+
* * `label` - The tooltip sets the trigger's aria-label or aria-labelledby attribute. This is useful for buttons
|
35
|
+
* displaying only an icon, for example.
|
36
|
+
* * `description` - The tooltip sets the trigger's aria-description or aria-describedby attribute.
|
37
|
+
* * `inaccessible` - No aria attributes are set on the trigger. This makes the tooltip's content inaccessible to
|
38
|
+
* screen readers, and should only be used if the tooltip's text is available by some other means.
|
39
|
+
*/
|
40
|
+
relationship: 'label' | 'description' | 'inaccessible';
|
41
|
+
/**
|
42
|
+
* The tooltip's visual appearance.
|
43
|
+
* * `normal` - Uses the theme's background and text colors.
|
44
|
+
* * `inverted` - Higher contrast variant that uses the theme's inverted colors.
|
45
|
+
*
|
46
|
+
* @defaultvalue normal
|
47
|
+
*/
|
48
|
+
appearance?: 'normal' | 'inverted';
|
49
|
+
/**
|
50
|
+
* Render an arrow pointing to the target element
|
51
|
+
*
|
52
|
+
* @defaultvalue false
|
53
|
+
*/
|
54
|
+
withArrow?: boolean;
|
55
|
+
/**
|
56
|
+
* Configure the positioning of the tooltip
|
57
|
+
*
|
58
|
+
* @defaultvalue above
|
59
|
+
*/
|
60
|
+
positioning?: PositioningShorthand;
|
61
|
+
/**
|
62
|
+
* Control the tooltip's visibility programatically.
|
63
|
+
*
|
64
|
+
* This can be used in conjunction with onVisibleChange to modify the tooltip's show and hide behavior.
|
65
|
+
*
|
66
|
+
* If not provided, the visibility will be controlled by the tooltip itself, based on hover and focus events on the
|
67
|
+
* trigger (child) element.
|
68
|
+
*/
|
69
|
+
visible?: boolean;
|
70
|
+
/**
|
71
|
+
* Notification when the visibility of the tooltip is changing
|
72
|
+
*/
|
73
|
+
onVisibleChange?: (event: React_2.PointerEvent<HTMLElement> | React_2.FocusEvent<HTMLElement> | undefined, data: OnVisibleChangeData) => void;
|
74
|
+
/**
|
75
|
+
* Delay before the tooltip is shown, in milliseconds.
|
76
|
+
*
|
77
|
+
* @defaultvalue 250
|
78
|
+
*/
|
79
|
+
showDelay: number;
|
80
|
+
/**
|
81
|
+
* Delay before the tooltip is hidden, in milliseconds.
|
82
|
+
*
|
83
|
+
* @defaultvalue 250
|
84
|
+
*/
|
85
|
+
hideDelay: number;
|
86
|
+
};
|
87
|
+
|
88
|
+
/**
|
89
|
+
* Properties for Tooltip
|
90
|
+
*/
|
91
|
+
export declare type TooltipProps = ComponentProps<TooltipSlots> & Partial<Omit<TooltipCommons, 'relationship'>> & Pick<TooltipCommons, 'relationship'> & {
|
92
|
+
/**
|
93
|
+
* The tooltip can have a single JSX child, or a render function that accepts TooltipTriggerProps.
|
94
|
+
*
|
95
|
+
* If no child is provided, the tooltip's target must be set with the `positioning` prop, and its
|
96
|
+
* visibility must be controlled with the `visible` prop.
|
97
|
+
*/
|
98
|
+
children?: (React_2.ReactElement & {
|
99
|
+
ref?: React_2.Ref<unknown>;
|
100
|
+
}) | ((props: TooltipTriggerProps) => React_2.ReactElement | null) | null;
|
101
|
+
};
|
102
|
+
|
103
|
+
/**
|
104
|
+
* Slot properties for Tooltip
|
105
|
+
*/
|
106
|
+
export declare type TooltipSlots = {
|
107
|
+
/**
|
108
|
+
* The text or JSX content of the tooltip.
|
109
|
+
*/
|
110
|
+
content: NonNullable<Slot<'div'>>;
|
111
|
+
};
|
112
|
+
|
113
|
+
/**
|
114
|
+
* State used in rendering Tooltip
|
115
|
+
*/
|
116
|
+
export declare type TooltipState = ComponentState<TooltipSlots> & TooltipCommons & {
|
117
|
+
children?: React_2.ReactElement | null;
|
118
|
+
/**
|
119
|
+
* Whether the tooltip should be rendered to the DOM.
|
120
|
+
*/
|
121
|
+
shouldRenderTooltip?: boolean;
|
122
|
+
/**
|
123
|
+
* Ref to the arrow element
|
124
|
+
*/
|
125
|
+
arrowRef?: React_2.Ref<HTMLDivElement>;
|
126
|
+
/**
|
127
|
+
* CSS class for the arrow element
|
128
|
+
*/
|
129
|
+
arrowClassName?: string;
|
130
|
+
};
|
131
|
+
|
132
|
+
/**
|
133
|
+
* The properties that are added to the trigger of the Tooltip
|
134
|
+
*/
|
135
|
+
export declare type TooltipTriggerProps = {
|
136
|
+
ref?: React_2.Ref<never>;
|
137
|
+
} & Pick<React_2.HTMLAttributes<HTMLElement>, 'onPointerEnter' | 'onPointerLeave' | 'onFocus' | 'onBlur' | 'aria-describedby' | 'aria-labelledby' | 'aria-label'>;
|
138
|
+
|
139
|
+
/**
|
140
|
+
* Create the state required to render Tooltip.
|
141
|
+
*
|
142
|
+
* The returned state can be modified with hooks such as useTooltipStyles_unstable,
|
143
|
+
* before being passed to renderTooltip_unstable.
|
144
|
+
*
|
145
|
+
* @param props - props from this instance of Tooltip
|
146
|
+
*/
|
147
|
+
export declare const useTooltip_unstable: (props: TooltipProps) => TooltipState;
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Apply styling to the Tooltip slots based on the state
|
151
|
+
*/
|
152
|
+
export declare const useTooltipStyles_unstable: (state: TooltipState) => TooltipState;
|
153
|
+
|
154
|
+
export { }
|
package/lib/Tooltip.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export * from './components/Tooltip/index';
|
package/lib/Tooltip.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"Tooltip.js","sourceRoot":"../src/","sources":["Tooltip.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC","sourcesContent":["export * from './components/Tooltip/index';\n"]}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import * as React from 'react';
|
2
|
+
import type { TooltipProps } from './Tooltip.types';
|
3
|
+
import type { FluentTriggerComponent } from '@fluentui/react-utilities';
|
4
|
+
/**
|
5
|
+
* A tooltip provides light weight contextual information on top of its target element.
|
6
|
+
*/
|
7
|
+
export declare const Tooltip: React.FC<TooltipProps> & FluentTriggerComponent;
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { useTooltip_unstable } from './useTooltip';
|
2
|
+
import { renderTooltip_unstable } from './renderTooltip';
|
3
|
+
import { useTooltipStyles_unstable } from './useTooltipStyles';
|
4
|
+
/**
|
5
|
+
* A tooltip provides light weight contextual information on top of its target element.
|
6
|
+
*/
|
7
|
+
|
8
|
+
export const Tooltip = props => {
|
9
|
+
const state = useTooltip_unstable(props);
|
10
|
+
useTooltipStyles_unstable(state);
|
11
|
+
return renderTooltip_unstable(state);
|
12
|
+
};
|
13
|
+
Tooltip.displayName = 'Tooltip';
|
14
|
+
Tooltip.isFluentTriggerComponent = true;
|
15
|
+
//# sourceMappingURL=Tooltip.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["components/Tooltip/Tooltip.tsx"],"names":[],"mappings":"AACA,SAAS,mBAAT,QAAoC,cAApC;AACA,SAAS,sBAAT,QAAuC,iBAAvC;AACA,SAAS,yBAAT,QAA0C,oBAA1C;AAIA;;AAEG;;AACH,OAAO,MAAM,OAAO,GAAoD,KAAK,IAAG;AAC9E,QAAM,KAAK,GAAG,mBAAmB,CAAC,KAAD,CAAjC;AAEA,EAAA,yBAAyB,CAAC,KAAD,CAAzB;AACA,SAAO,sBAAsB,CAAC,KAAD,CAA7B;AACD,CALM;AAOP,OAAO,CAAC,WAAR,GAAsB,SAAtB;AACA,OAAO,CAAC,wBAAR,GAAmC,IAAnC","sourcesContent":["import * as React from 'react';\nimport { useTooltip_unstable } from './useTooltip';\nimport { renderTooltip_unstable } from './renderTooltip';\nimport { useTooltipStyles_unstable } from './useTooltipStyles';\nimport type { TooltipProps } from './Tooltip.types';\nimport type { FluentTriggerComponent } from '@fluentui/react-utilities';\n\n/**\n * A tooltip provides light weight contextual information on top of its target element.\n */\nexport const Tooltip: React.FC<TooltipProps> & FluentTriggerComponent = props => {\n const state = useTooltip_unstable(props);\n\n useTooltipStyles_unstable(state);\n return renderTooltip_unstable(state);\n};\n\nTooltip.displayName = 'Tooltip';\nTooltip.isFluentTriggerComponent = true;\n"],"sourceRoot":"../src/"}
|