@fluentui/react-popover 9.3.1 → 9.3.3
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.json +105 -1
- package/CHANGELOG.md +31 -2
- package/lib/components/Popover/usePopover.js +3 -10
- package/lib/components/Popover/usePopover.js.map +1 -1
- package/lib-amd/Popover.js +6 -0
- package/lib-amd/Popover.js.map +1 -0
- package/lib-amd/PopoverSurface.js +6 -0
- package/lib-amd/PopoverSurface.js.map +1 -0
- package/lib-amd/PopoverTrigger.js +6 -0
- package/lib-amd/PopoverTrigger.js.map +1 -0
- package/lib-amd/components/Popover/Popover.js +15 -0
- package/lib-amd/components/Popover/Popover.js.map +1 -0
- package/lib-amd/components/Popover/Popover.types.js +5 -0
- package/lib-amd/components/Popover/Popover.types.js.map +1 -0
- package/lib-amd/components/Popover/constants.js +15 -0
- package/lib-amd/components/Popover/constants.js.map +1 -0
- package/lib-amd/components/Popover/index.js +9 -0
- package/lib-amd/components/Popover/index.js.map +1 -0
- package/lib-amd/components/Popover/renderPopover.js +32 -0
- package/lib-amd/components/Popover/renderPopover.js.map +1 -0
- package/lib-amd/components/Popover/usePopover.js +144 -0
- package/lib-amd/components/Popover/usePopover.js.map +1 -0
- package/lib-amd/components/PopoverSurface/PopoverSurface.js +15 -0
- package/lib-amd/components/PopoverSurface/PopoverSurface.js.map +1 -0
- package/lib-amd/components/PopoverSurface/PopoverSurface.types.js +5 -0
- package/lib-amd/components/PopoverSurface/PopoverSurface.types.js.map +1 -0
- package/lib-amd/components/PopoverSurface/index.js +10 -0
- package/lib-amd/components/PopoverSurface/index.js.map +1 -0
- package/lib-amd/components/PopoverSurface/renderPopoverSurface.js +20 -0
- package/lib-amd/components/PopoverSurface/renderPopoverSurface.js.map +1 -0
- package/lib-amd/components/PopoverSurface/usePopoverSurface.js +65 -0
- package/lib-amd/components/PopoverSurface/usePopoverSurface.js.map +1 -0
- package/lib-amd/components/PopoverSurface/usePopoverSurfaceStyles.js +44 -0
- package/lib-amd/components/PopoverSurface/usePopoverSurfaceStyles.js.map +1 -0
- package/lib-amd/components/PopoverTrigger/PopoverTrigger.js +17 -0
- package/lib-amd/components/PopoverTrigger/PopoverTrigger.js.map +1 -0
- package/lib-amd/components/PopoverTrigger/PopoverTrigger.types.js +5 -0
- package/lib-amd/components/PopoverTrigger/PopoverTrigger.types.js.map +1 -0
- package/lib-amd/components/PopoverTrigger/index.js +9 -0
- package/lib-amd/components/PopoverTrigger/index.js.map +1 -0
- package/lib-amd/components/PopoverTrigger/renderPopoverTrigger.js +13 -0
- package/lib-amd/components/PopoverTrigger/renderPopoverTrigger.js.map +1 -0
- package/lib-amd/components/PopoverTrigger/usePopoverTrigger.js +61 -0
- package/lib-amd/components/PopoverTrigger/usePopoverTrigger.js.map +1 -0
- package/lib-amd/index.js +20 -0
- package/lib-amd/index.js.map +1 -0
- package/lib-amd/popoverContext.js +28 -0
- package/lib-amd/popoverContext.js.map +1 -0
- package/lib-commonjs/components/Popover/usePopover.js +3 -10
- package/lib-commonjs/components/Popover/usePopover.js.map +1 -1
- package/package.json +9 -9
- package/Spec.md +0 -516
package/Spec.md
DELETED
@@ -1,516 +0,0 @@
|
|
1
|
-
# @fluentui/react-popover Spec
|
2
|
-
|
3
|
-
## Background
|
4
|
-
|
5
|
-
`Popovers` contain content that is opened after interacting with visible content. The content does not belong to the flow of visible information and is rendered out of DOM order. The content can display complementary information to existing content, or serve as a lightweight Dialog with interactable content.
|
6
|
-
|
7
|
-
## Prior Art
|
8
|
-
|
9
|
-
- [Open UI research](https://github.com/openui/open-ui/pull/205)
|
10
|
-
- [Github epic issue #17920](https://github.com/microsoft/fluentui/issues/17920)
|
11
|
-
|
12
|
-
### v0/v8 components
|
13
|
-
|
14
|
-
- [v8 Callout](https://developer.microsoft.com/en-us/fluentui#/controls/web/callout)
|
15
|
-
- [v0 Popup](https://fluentsite.z22.web.core.windows.net/0.54.0/components/popup/definition)
|
16
|
-
|
17
|
-
### Callout in v8
|
18
|
-
|
19
|
-
The v8 `Callout` component only covers the positioned content functionality. The default usage involves conditional rendering of the `Callout`. The `onDismiss` prop requests the `Callout` to close on events such as clicking outside or pressing the escape key.
|
20
|
-
|
21
|
-
```tsx
|
22
|
-
{isCalloutVisible && (
|
23
|
-
<Callout
|
24
|
-
target={`#${targetId}`}
|
25
|
-
onDismiss={toggleIsCalloutVisible}
|
26
|
-
>
|
27
|
-
{children}
|
28
|
-
</Callout>
|
29
|
-
}
|
30
|
-
```
|
31
|
-
|
32
|
-
Focus traps are supported for this scenario using a different component.
|
33
|
-
|
34
|
-
```tsx
|
35
|
-
{isCalloutVisible && (
|
36
|
-
<FocusTrapCallout
|
37
|
-
setInitialFocus
|
38
|
-
target={`#${targetId}`}
|
39
|
-
onDismiss={toggleIsCalloutVisible}
|
40
|
-
>
|
41
|
-
{children}
|
42
|
-
</FocusTrapCallout>
|
43
|
-
}
|
44
|
-
```
|
45
|
-
|
46
|
-
### Popup in v0
|
47
|
-
|
48
|
-
The v0 `Popup` comes in both the controlled an uncontrolled variant that includes a `trigger` element which will open the `Popup`. Four interactions to open the `Popup` are supported:
|
49
|
-
|
50
|
-
- Click
|
51
|
-
- Hover
|
52
|
-
- Context (i.e. right click)
|
53
|
-
- Focus
|
54
|
-
|
55
|
-
In the controlled variant, an `onOpenChange` callback requests open/close of the popup to the user. This callback handles all the interactions for the trigger (above) and events such as clicking outside and the escape key.
|
56
|
-
|
57
|
-
```tsx
|
58
|
-
// Uncontrolled
|
59
|
-
<Popup
|
60
|
-
trigger={<Button icon={<MoreIcon />} title="Show popup" />}
|
61
|
-
content={popupContent}
|
62
|
-
on=['click', 'hover', 'context', 'focus']
|
63
|
-
/>
|
64
|
-
|
65
|
-
// Controlled
|
66
|
-
<Popup
|
67
|
-
open={open}
|
68
|
-
onOpenChange={(e, { open }) => setOpen(open)}
|
69
|
-
trigger={<Button icon={<MoreIcon />} title="Show popup" />}
|
70
|
-
content={popupContent}
|
71
|
-
on=['click', 'hover', 'context', 'focus']
|
72
|
-
/>
|
73
|
-
```
|
74
|
-
|
75
|
-
Focus trap is enabled using the `trapFocus` prop.
|
76
|
-
|
77
|
-
A `target` prop also exists so that the `Popup` does not have to be anchored to the `trigger` element.
|
78
|
-
|
79
|
-
### Position/Alignment hints
|
80
|
-
|
81
|
-
Both libraries provide an API that achieves the same end result for positioning and alignment. Below is a table that maps the v8 `DirectionalHint` with the v0 props of `position` and `alignment`
|
82
|
-
|
83
|
-
| DirectionalHint (v7) | position (v0) | align (v0) |
|
84
|
-
| -------------------- | ------------- | ---------- |
|
85
|
-
| topLeftEdge | above | start |
|
86
|
-
| topCenter | above | center |
|
87
|
-
| topRightEdge | above | bottom |
|
88
|
-
| topAutoEdge | above | |
|
89
|
-
| bottomLeftEdge | below | start |
|
90
|
-
| bottomCenter | below | center |
|
91
|
-
| bottomRightEdge | below | bottom |
|
92
|
-
| bottomAutoEdge | below | |
|
93
|
-
| leftTopEdge | before | top |
|
94
|
-
| leftCenter | before | center |
|
95
|
-
| leftBottomEdge | before | bottom |
|
96
|
-
| rightTopEdge | after | before |
|
97
|
-
| rightCenter | after | center |
|
98
|
-
| rightBottomEdge | after | bottom |
|
99
|
-
|
100
|
-
v8 uses `left` and `right`. v0 uses `before` and `after`. v0 vocabulary tries to be consistent regardless of RTL state. It's also possible to supply an explicit RTL hint to v8 which is a flip by default. v0 will flip by default but requires the consumer to detect RTL scenarios and modify props in these situations.
|
101
|
-
|
102
|
-
In general the separation of both the position and alignment in v0 results in an API that is easier to use if a consumer only needs to modify one of the two props. However both try to achieve the same result in the end.
|
103
|
-
|
104
|
-
It's important to note that if an incorrect pair of `position` and `align` are provided in v0, then `position` takes priority and `align` is set to `center`
|
105
|
-
|
106
|
-
### Offset
|
107
|
-
|
108
|
-
```tsx
|
109
|
-
<Callout
|
110
|
-
// single number value
|
111
|
-
gap={100}
|
112
|
-
/>
|
113
|
-
|
114
|
-
<Popup
|
115
|
-
offset={[-100, 100]}
|
116
|
-
/>
|
117
|
-
|
118
|
-
// offset can also be a function of raw Popper properties
|
119
|
-
const offsetFunction = ({
|
120
|
-
popper: PopperJs.Rect;
|
121
|
-
reference: PopperJs.Rect;
|
122
|
-
placement: PopperJs.Placement;
|
123
|
-
}) => ([popper.width, -popper.height])
|
124
|
-
```
|
125
|
-
|
126
|
-
v8 positioning can only apply a numerical value to the first part position attribute of DirectionalHint. v0 supports a function to defer calculation at runtime. v0 also supports offset of the Popup in both axes while supporting RTL flips for offset values.
|
127
|
-
|
128
|
-
### Bounds and overflow
|
129
|
-
|
130
|
-
```tsx
|
131
|
-
<Popup
|
132
|
-
...
|
133
|
-
flipBoundary={htmlElement}
|
134
|
-
overflowBoundary={htmlElement}
|
135
|
-
mountNode={htmlElement}
|
136
|
-
/>
|
137
|
-
```
|
138
|
-
|
139
|
-
v0 `Popup` provides 3 different properties to handle bounds and overflow:
|
140
|
-
|
141
|
-
- flipBoundary - the bounds to calculate when to flip positioning of the popup
|
142
|
-
- overflowBoundary - the bounds to shift the popup without overflowing
|
143
|
-
- mountNode - where the popup is actually rendered in the DOM, by default this is a portal to a div in body
|
144
|
-
|
145
|
-
```tsx
|
146
|
-
<Callout
|
147
|
-
// pixel values for bounding rectangle
|
148
|
-
// defaults to target window as default bounding rectangle
|
149
|
-
bounds={{height: 0, width: 0, top: 0, left:0 , right: 0, bottom: 0}}
|
150
|
-
// callback for bounds
|
151
|
-
bounds{(target, targetWindow) => ({/*Same object as above*/})}
|
152
|
-
target={htmlElement}
|
153
|
-
|
154
|
-
// renders to a portal node on body
|
155
|
-
layerProps={/*ILayerProps*/}
|
156
|
-
|
157
|
-
// every single one of the above can all be declared here too
|
158
|
-
calloutProps={{bounds, target}}
|
159
|
-
/>
|
160
|
-
```
|
161
|
-
|
162
|
-
v8 `Callout` has no notion of separate boundaries for flip or overflow, and auto behaviour is used for flip and overflow 'pushing'.
|
163
|
-
|
164
|
-
### Events
|
165
|
-
|
166
|
-
v8 provides the following positioning event callbacks
|
167
|
-
|
168
|
-
- onLayerMounted -> proposed to be removed in converged Portal spec [#17824](https://github.com/microsoft/fluentui/pull/17824)
|
169
|
-
- onPositioned -> `Callout` calls this when it finishes positioning the element
|
170
|
-
- onScroll -> `Callout` calls this when the contents are scrolled
|
171
|
-
|
172
|
-
### Hidden mount
|
173
|
-
|
174
|
-
v8 `Callout` provides two props which will allow mounting a hidden popup and disabling renders when the component is hidden. According to the PRs that introduced the features, it should be a performance optimization.
|
175
|
-
|
176
|
-
- `hidden` [#4419](https://github.com/microsoft/fluentui/pull/4419)
|
177
|
-
- `shouldUpdateWhenHidden` [#10465](https://github.com/microsoft/fluentui/pull/10465)
|
178
|
-
|
179
|
-
## Sample Code
|
180
|
-
|
181
|
-
```tsx
|
182
|
-
<Popover>
|
183
|
-
<PopoverTrigger>
|
184
|
-
<button>Opens popover</button>
|
185
|
-
</PopoverTrigger>
|
186
|
-
|
187
|
-
<PopoverSurface>
|
188
|
-
<h1>Popover</h2>
|
189
|
-
<div>Some section</div>
|
190
|
-
<div>Some section</div>
|
191
|
-
</PopoverSurface>
|
192
|
-
</Popover>
|
193
|
-
```
|
194
|
-
|
195
|
-
## Variants
|
196
|
-
|
197
|
-
- Anchor content to a different target than the trigger
|
198
|
-
- Inline popover rendered in DOM order
|
199
|
-
- Open on:
|
200
|
-
- Click
|
201
|
-
- Hover
|
202
|
-
- Context menu (right click)
|
203
|
-
- Focus
|
204
|
-
|
205
|
-
## API
|
206
|
-
|
207
|
-
The `Popover` component will use React context to manage both a trigger and content component.
|
208
|
-
|
209
|
-
### Popover
|
210
|
-
|
211
|
-
Outer component that sets up context and does not render DOM.
|
212
|
-
|
213
|
-
> TODO Discuss: dismiss on scroll ?
|
214
|
-
|
215
|
-
> TODO Discuss: v8 `hidden` `shouldUpdateHidden` prop [#4419](https://github.com/microsoft/fluentui/pull/4419) [#10465](https://github.com/microsoft/fluentui/pull/10465)
|
216
|
-
|
217
|
-
> TODO Discuss: v8 `onPositioned`
|
218
|
-
|
219
|
-
> TODO Discuss: A11y -> Should only one popup be open at a time or is aria-hidden enough ?
|
220
|
-
|
221
|
-
> TODO Discuss: merge position and align props -> no real reason they were separated in v0 in the first place
|
222
|
-
|
223
|
-
> TODO Discuss: v0 `unstable`props supported out of the box ? (pinned, disableTether)
|
224
|
-
|
225
|
-
> TODO Discuss v0 `shouldDismissOnWindowFocus` ?
|
226
|
-
|
227
|
-
The `@fluentui/react-positioning` library that exports the `usePopper` hook which will power the `Popover` contains more than the declared props here. These extra positioning props should be exposed as required.
|
228
|
-
|
229
|
-
```typescript
|
230
|
-
export type PopoverProps = {
|
231
|
-
/**
|
232
|
-
* Controls the popover open state
|
233
|
-
*/
|
234
|
-
open?: boolean;
|
235
|
-
|
236
|
-
/**
|
237
|
-
* Call back when the component requests to change value
|
238
|
-
*/
|
239
|
-
onOpenChange?: (e: OpenPopoverEvents, data: OpenEventData) => void;
|
240
|
-
|
241
|
-
/**
|
242
|
-
* Flag to open the Popover by hovering the trigger
|
243
|
-
*/
|
244
|
-
openOnHover?: boolean;
|
245
|
-
|
246
|
-
/**
|
247
|
-
* Anchor the popover to an element other than the trigger
|
248
|
-
*/
|
249
|
-
target?: HTMLElement;
|
250
|
-
|
251
|
-
/**
|
252
|
-
* Popover position relative to target
|
253
|
-
*/
|
254
|
-
position?: 'above' | 'below' | 'before' | 'after';
|
255
|
-
|
256
|
-
/**
|
257
|
-
* Popover alignment relative to target
|
258
|
-
*/
|
259
|
-
align?: 'top' | 'bottom' | 'start' | 'end' | 'center';
|
260
|
-
|
261
|
-
/**
|
262
|
-
* Popover offset value or callback with positioning props
|
263
|
-
*/
|
264
|
-
offset?: OffsetFunction | [number, number];
|
265
|
-
|
266
|
-
/**
|
267
|
-
* Renders `PopoverSurface` to a portal out of DOM order
|
268
|
-
*
|
269
|
-
* @default document.body
|
270
|
-
*/
|
271
|
-
mountNode?: string;
|
272
|
-
|
273
|
-
/**
|
274
|
-
* Explicitly render the popover in DOM order
|
275
|
-
*/
|
276
|
-
inline?: boolean;
|
277
|
-
|
278
|
-
/**
|
279
|
-
* Traps focus inside the popup and applies modal dialog behaviour
|
280
|
-
*/
|
281
|
-
trapFocus?: boolean;
|
282
|
-
|
283
|
-
/**
|
284
|
-
* Covers the target that the popover is anchored to. This is the `PopoverTrigger` unless `target` prop is used
|
285
|
-
*/
|
286
|
-
coverTarget?: boolean;
|
287
|
-
|
288
|
-
/**
|
289
|
-
* Do not render an arrow pointing to the target element. This is the `PopoverTrigger` unless `target` prop is used
|
290
|
-
*/
|
291
|
-
noArrow?: boolean;
|
292
|
-
|
293
|
-
/**
|
294
|
-
* Sets the delay for closing popover on mouse leave
|
295
|
-
*/
|
296
|
-
mouseLeaveDelay?: number;
|
297
|
-
|
298
|
-
/**
|
299
|
-
* Close when scrolling outside of it
|
300
|
-
*/
|
301
|
-
closeOnScroll?: boolean;
|
302
|
-
};
|
303
|
-
```
|
304
|
-
|
305
|
-
### PopoverTrigger
|
306
|
-
|
307
|
-
This component does not render DOM. Utility component that clones a single child and applies HTML event callbacks to control the open/dismiss of the popover.
|
308
|
-
|
309
|
-
```typescript
|
310
|
-
export type PopoverTriggerProps = {
|
311
|
-
/**
|
312
|
-
* Should only be a single child
|
313
|
-
*/
|
314
|
-
children?: React.ReactElement;
|
315
|
-
};
|
316
|
-
```
|
317
|
-
|
318
|
-
### PopoverSurface
|
319
|
-
|
320
|
-
This component renders the positioned HTML element and renders user provided children. Renders as `<div>` by default.
|
321
|
-
|
322
|
-
```typescript
|
323
|
-
export type PopoverSurfaceProps = {
|
324
|
-
children?: React.ReactNode;
|
325
|
-
};
|
326
|
-
```
|
327
|
-
|
328
|
-
## Structure
|
329
|
-
|
330
|
-
Default popover
|
331
|
-
|
332
|
-
```tsx
|
333
|
-
<div id="container">
|
334
|
-
<Popover>
|
335
|
-
<PopoverTrigger>
|
336
|
-
<button>Trigger</button>
|
337
|
-
</PopoverTrigger>
|
338
|
-
|
339
|
-
<PopoverSurface>
|
340
|
-
{children}
|
341
|
-
</PopoverSurface>
|
342
|
-
</Popover>
|
343
|
-
<div>
|
344
|
-
|
345
|
-
// Expected Markup
|
346
|
-
<div id="container">
|
347
|
-
<button aria-expanded="false">Trigger</button>
|
348
|
-
</div>
|
349
|
-
|
350
|
-
// on document.body
|
351
|
-
<div role="group">
|
352
|
-
{/** content */}
|
353
|
-
</div>
|
354
|
-
```
|
355
|
-
|
356
|
-
Popover that traps focus
|
357
|
-
|
358
|
-
```tsx
|
359
|
-
<div id="container">
|
360
|
-
<Popover trapFocus>
|
361
|
-
<PopoverTrigger>
|
362
|
-
<button>Trigger</button>
|
363
|
-
</PopoverTrigger>
|
364
|
-
|
365
|
-
<PopoverSurface>
|
366
|
-
{children}
|
367
|
-
</PopoverSurface>
|
368
|
-
</Popover>
|
369
|
-
<div>
|
370
|
-
|
371
|
-
// Expected Markup
|
372
|
-
<div id="container">
|
373
|
-
<button aria-expanded="false">Trigger</button>
|
374
|
-
</div>
|
375
|
-
|
376
|
-
// on document.body
|
377
|
-
<div role="dialog" aria-modal="true">
|
378
|
-
{/** content */}
|
379
|
-
</div>
|
380
|
-
```
|
381
|
-
|
382
|
-
Inline popover
|
383
|
-
|
384
|
-
```tsx
|
385
|
-
<div id="container">
|
386
|
-
<Popover inline>
|
387
|
-
<PopoverTrigger>
|
388
|
-
<button>Trigger</button>
|
389
|
-
</PopoverTrigger>
|
390
|
-
|
391
|
-
<PopoverSurface>
|
392
|
-
{children}
|
393
|
-
</PopoverSurface>
|
394
|
-
</Popover>
|
395
|
-
<div>
|
396
|
-
|
397
|
-
// Expected Markup
|
398
|
-
<div id="container">
|
399
|
-
<button aria-expanded="false">Trigger</button>
|
400
|
-
<div>
|
401
|
-
{/** content */}
|
402
|
-
</div>
|
403
|
-
</div>
|
404
|
-
|
405
|
-
|
406
|
-
```
|
407
|
-
|
408
|
-
## Migration
|
409
|
-
|
410
|
-
### v8
|
411
|
-
|
412
|
-
- `onDismiss` should listen to `onOpenChange`.
|
413
|
-
- `preventDismissOnEvent` no longer exists, `onOpenChange` will return the associated event, so this functionality is still possible.
|
414
|
-
- Removed `onRestoreFocus`. `Popover` will focus the trigger when closed by default. Any other behaviour can be done through an effect by users.
|
415
|
-
- Removed `onPositioned`.
|
416
|
-
- Removed `doNotLayer` with `inline`.
|
417
|
-
- Removed all styling props supported by `Callout`. `makeStyles` should be used instead.
|
418
|
-
- Removed `coverTarget`, use `offset` callback instead.
|
419
|
-
- Removed `setInitialFocus`. If `trapFocus` is used, first focusable element is used. Users must handle other specific cases.
|
420
|
-
|
421
|
-
### v0
|
422
|
-
|
423
|
-
- No more `autoFocus` for scenarios without `trapFocus`. Users should handle this scenario manually.
|
424
|
-
- No more `tabbableTrigger`. Users can do this with their own trigger element.
|
425
|
-
- No `PopoverSurface` props, v0 duplicated props from `Popover` to `PopoverSurface`, all props should be declared on converged `Popover`.
|
426
|
-
|
427
|
-
## Behaviors
|
428
|
-
|
429
|
-
### Trigger interactions
|
430
|
-
|
431
|
-
A popover should support click, hover, context menu and focus interactions for the `PopoverTrigger`. These interactions should also be composable.
|
432
|
-
|
433
|
-
#### Click
|
434
|
-
|
435
|
-
Clicking the trigger when the popover is closed opens the popover.
|
436
|
-
|
437
|
-
Clicking the trigger when the popover is open closes the popover.
|
438
|
-
|
439
|
-
Click also includes `Spacebar` and `Enter` keys.
|
440
|
-
|
441
|
-
#### Hover
|
442
|
-
|
443
|
-
When the mouse hovers over the trigger the popover opens.
|
444
|
-
|
445
|
-
When the mouse leaves the trigger and popover content, the popover closes.
|
446
|
-
|
447
|
-
#### Context menu
|
448
|
-
|
449
|
-
Right click on the trigger opens the popover. The popover anchors to the mouse position.
|
450
|
-
|
451
|
-
Shift + F10 on the trigger opens the popover
|
452
|
-
|
453
|
-
### Additional interactions
|
454
|
-
|
455
|
-
#### Escape key
|
456
|
-
|
457
|
-
The popover closes with the escape key when the trigger or popover content has focus.
|
458
|
-
|
459
|
-
#### Click outside
|
460
|
-
|
461
|
-
The popover closes when a click happens outside the popover trigger or content.
|
462
|
-
|
463
|
-
#### Scroll outside
|
464
|
-
|
465
|
-
The context menu popover closes when scroll happens outside the popover trigger or content.
|
466
|
-
When popover is configured with `closeOnScroll`, popover closes when scroll happens outside the popover trigger or content.
|
467
|
-
|
468
|
-
### Focus trap
|
469
|
-
|
470
|
-
When the popover is configured to be a focus trap, focus the first focusable element inside the popover on open.
|
471
|
-
|
472
|
-
### Nesting
|
473
|
-
|
474
|
-
Popovers should allow nesting
|
475
|
-
|
476
|
-
## Accessibility
|
477
|
-
|
478
|
-
### Existing patterns
|
479
|
-
|
480
|
-
The [WAI Dialog pattern](https://www.w3.org/TR/wai-aria-practices-1.2/#dialog_modal) and its variants are the inspirations for `Popover` accessibility.
|
481
|
-
|
482
|
-
- [Datepicker](https://www.w3.org/TR/wai-aria-practices-1.2/examples/dialog-modal/datepicker-dialog.html)
|
483
|
-
- [Modal Dialog](https://www.w3.org/TR/wai-aria-practices-1.2/examples/dialog-modal/dialog.html)
|
484
|
-
|
485
|
-
### DOM element usage
|
486
|
-
|
487
|
-
Only the `PopoverSurface` component will render DOM markup. By default the components renders an HTML `div` element.
|
488
|
-
|
489
|
-
### aria-hidden
|
490
|
-
|
491
|
-
Using a Popover with a focus trap is no different from a modal dialog in terms of a11y. Therefore, aria-hidden must be applied to all non-interactive elements of the page when the Popover is open.
|
492
|
-
|
493
|
-
This also means that a Popover should be closed when another Popover is opened if they are not nested. In a nested case, the parent Popovers need to be hidden.
|
494
|
-
|
495
|
-
### Accessible markup
|
496
|
-
|
497
|
-
Accessible markup is divided into two scenarios:
|
498
|
-
|
499
|
-
```tsx
|
500
|
-
// Popover that does not trap focus
|
501
|
-
<button aria-expanded="false">Trigger</button>
|
502
|
-
<div role="group">
|
503
|
-
No focus trap
|
504
|
-
</div>
|
505
|
-
|
506
|
-
// Popover that does trap focus
|
507
|
-
<div aria-hidden="true" /> // other content
|
508
|
-
<div aria-hidden="true" /> // other content
|
509
|
-
<div aria-hidden="true" className='fui-provider'>
|
510
|
-
<button aria-expanded="false">Trigger</button>
|
511
|
-
</div>
|
512
|
-
|
513
|
-
<div role="dialog" aria-modal="true">
|
514
|
-
Focus trapped
|
515
|
-
</div>
|
516
|
-
```
|