@instructure/ui-popover 11.6.0 → 11.6.1-snapshot-129

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.
Files changed (56) hide show
  1. package/CHANGELOG.md +38 -288
  2. package/es/Popover/{index.js → v1/index.js} +3 -3
  3. package/es/Popover/v2/index.js +499 -0
  4. package/es/Popover/v2/props.js +26 -0
  5. package/es/Popover/v2/styles.js +39 -0
  6. package/es/{index.js → exports/a.js} +1 -1
  7. package/{src/index.ts → es/exports/b.js} +1 -2
  8. package/lib/Popover/{index.js → v1/index.js} +5 -6
  9. package/lib/Popover/v2/index.js +514 -0
  10. package/lib/Popover/v2/props.js +31 -0
  11. package/lib/Popover/v2/styles.js +45 -0
  12. package/lib/{index.js → exports/a.js} +2 -2
  13. package/lib/exports/b.js +12 -0
  14. package/package.json +46 -24
  15. package/src/Popover/{index.tsx → v1/index.tsx} +5 -5
  16. package/src/Popover/v2/README.md +455 -0
  17. package/src/Popover/v2/index.tsx +645 -0
  18. package/src/Popover/v2/props.ts +354 -0
  19. package/src/Popover/v2/styles.ts +45 -0
  20. package/src/exports/a.ts +25 -0
  21. package/src/exports/b.ts +25 -0
  22. package/tsconfig.build.tsbuildinfo +1 -1
  23. package/types/Popover/v1/index.d.ts +83 -0
  24. package/types/Popover/v1/index.d.ts.map +1 -0
  25. package/types/Popover/v1/props.d.ts.map +1 -0
  26. package/types/Popover/v1/styles.d.ts.map +1 -0
  27. package/types/Popover/v1/theme.d.ts.map +1 -0
  28. package/types/Popover/v2/index.d.ts.map +1 -0
  29. package/types/Popover/v2/props.d.ts +225 -0
  30. package/types/Popover/v2/props.d.ts.map +1 -0
  31. package/types/Popover/v2/styles.d.ts +13 -0
  32. package/types/Popover/v2/styles.d.ts.map +1 -0
  33. package/types/exports/a.d.ts +3 -0
  34. package/types/exports/a.d.ts.map +1 -0
  35. package/types/exports/b.d.ts +3 -0
  36. package/types/exports/b.d.ts.map +1 -0
  37. package/types/Popover/index.d.ts.map +0 -1
  38. package/types/Popover/props.d.ts.map +0 -1
  39. package/types/Popover/styles.d.ts.map +0 -1
  40. package/types/Popover/theme.d.ts.map +0 -1
  41. package/types/index.d.ts +0 -3
  42. package/types/index.d.ts.map +0 -1
  43. /package/es/Popover/{props.js → v1/props.js} +0 -0
  44. /package/es/Popover/{styles.js → v1/styles.js} +0 -0
  45. /package/es/Popover/{theme.js → v1/theme.js} +0 -0
  46. /package/lib/Popover/{props.js → v1/props.js} +0 -0
  47. /package/lib/Popover/{styles.js → v1/styles.js} +0 -0
  48. /package/lib/Popover/{theme.js → v1/theme.js} +0 -0
  49. /package/src/Popover/{README.md → v1/README.md} +0 -0
  50. /package/src/Popover/{props.ts → v1/props.ts} +0 -0
  51. /package/src/Popover/{styles.ts → v1/styles.ts} +0 -0
  52. /package/src/Popover/{theme.ts → v1/theme.ts} +0 -0
  53. /package/types/Popover/{props.d.ts → v1/props.d.ts} +0 -0
  54. /package/types/Popover/{styles.d.ts → v1/styles.d.ts} +0 -0
  55. /package/types/Popover/{theme.d.ts → v1/theme.d.ts} +0 -0
  56. /package/types/Popover/{index.d.ts → v2/index.d.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/ui-popover",
3
- "version": "11.6.0",
3
+ "version": "11.6.1-snapshot-129",
4
4
  "description": "A component for hiding or showing content based on user interaction.",
5
5
  "author": "Instructure, Inc. Engineering and Product Design",
6
6
  "module": "./es/index.js",
@@ -16,28 +16,28 @@
16
16
  "dependencies": {
17
17
  "@babel/runtime": "^7.27.6",
18
18
  "keycode": "^2.2.1",
19
- "@instructure/console": "11.6.0",
20
- "@instructure/emotion": "11.6.0",
21
- "@instructure/ui-a11y-utils": "11.6.0",
22
- "@instructure/ui-dialog": "11.6.0",
23
- "@instructure/shared-types": "11.6.0",
24
- "@instructure/ui-dom-utils": "11.6.0",
25
- "@instructure/ui-i18n": "11.6.0",
26
- "@instructure/ui-position": "11.6.0",
27
- "@instructure/ui-utils": "11.6.0",
28
- "@instructure/ui-view": "11.6.0",
29
- "@instructure/uid": "11.6.0",
30
- "@instructure/ui-react-utils": "11.6.0"
19
+ "@instructure/console": "11.6.1-snapshot-129",
20
+ "@instructure/emotion": "11.6.1-snapshot-129",
21
+ "@instructure/ui-a11y-utils": "11.6.1-snapshot-129",
22
+ "@instructure/ui-dialog": "11.6.1-snapshot-129",
23
+ "@instructure/shared-types": "11.6.1-snapshot-129",
24
+ "@instructure/ui-dom-utils": "11.6.1-snapshot-129",
25
+ "@instructure/ui-i18n": "11.6.1-snapshot-129",
26
+ "@instructure/ui-position": "11.6.1-snapshot-129",
27
+ "@instructure/ui-react-utils": "11.6.1-snapshot-129",
28
+ "@instructure/ui-utils": "11.6.1-snapshot-129",
29
+ "@instructure/ui-view": "11.6.1-snapshot-129",
30
+ "@instructure/uid": "11.6.1-snapshot-129"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@testing-library/jest-dom": "^6.6.3",
34
34
  "@testing-library/react": "15.0.7",
35
35
  "@testing-library/user-event": "^14.6.1",
36
36
  "vitest": "^3.2.2",
37
- "@instructure/ui-axe-check": "11.6.0",
38
- "@instructure/ui-babel-preset": "11.6.0",
39
- "@instructure/ui-color-utils": "11.6.0",
40
- "@instructure/ui-themes": "11.6.0"
37
+ "@instructure/ui-axe-check": "11.6.1-snapshot-129",
38
+ "@instructure/ui-babel-preset": "11.6.1-snapshot-129",
39
+ "@instructure/ui-color-utils": "11.6.1-snapshot-129",
40
+ "@instructure/ui-themes": "11.6.1-snapshot-129"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "react": ">=18 <=19"
@@ -47,17 +47,39 @@
47
47
  },
48
48
  "sideEffects": false,
49
49
  "exports": {
50
- ".": {
51
- "types": "./types/index.d.ts",
52
- "import": "./es/index.js",
53
- "require": "./lib/index.js",
54
- "default": "./es/index.js"
55
- },
56
50
  "./lib/*": "./lib/*",
57
51
  "./es/*": "./es/*",
58
52
  "./types/*": "./types/*",
59
53
  "./package.json": "./package.json",
60
- "./src/*": "./src/*"
54
+ "./src/*": "./src/*",
55
+ ".": {
56
+ "src": "./src/exports/a.ts",
57
+ "types": "./types/exports/a.d.ts",
58
+ "import": "./es/exports/a.js",
59
+ "require": "./lib/exports/a.js",
60
+ "default": "./es/exports/a.js"
61
+ },
62
+ "./v11_6": {
63
+ "src": "./src/exports/a.ts",
64
+ "types": "./types/exports/a.d.ts",
65
+ "import": "./es/exports/a.js",
66
+ "require": "./lib/exports/a.js",
67
+ "default": "./es/exports/a.js"
68
+ },
69
+ "./v11_7": {
70
+ "src": "./src/exports/b.ts",
71
+ "types": "./types/exports/b.d.ts",
72
+ "import": "./es/exports/b.js",
73
+ "require": "./lib/exports/b.js",
74
+ "default": "./es/exports/b.js"
75
+ },
76
+ "./latest": {
77
+ "src": "./src/exports/b.ts",
78
+ "types": "./types/exports/b.d.ts",
79
+ "import": "./es/exports/b.js",
80
+ "require": "./lib/exports/b.js",
81
+ "default": "./es/exports/b.js"
82
+ }
61
83
  },
62
84
  "scripts": {
63
85
  "lint": "ui-scripts lint",
@@ -30,7 +30,7 @@ import {
30
30
  parsePlacement,
31
31
  mirrorHorizontalPlacement
32
32
  } from '@instructure/ui-position'
33
- import { ContextView, View } from '@instructure/ui-view'
33
+ import { ContextView, View } from '@instructure/ui-view/v11_6'
34
34
  import { Dialog } from '@instructure/ui-dialog'
35
35
  import { textDirectionContextConsumer } from '@instructure/ui-i18n'
36
36
  import {
@@ -55,17 +55,17 @@ import { logError as error } from '@instructure/console'
55
55
  import { FocusRegion } from '@instructure/ui-a11y-utils'
56
56
 
57
57
  import type { RequestAnimationFrameType } from '@instructure/ui-dom-utils'
58
- import type { ViewProps, ContextViewProps } from '@instructure/ui-view'
58
+ import type { ViewProps, ContextViewProps } from '@instructure/ui-view/v11_6'
59
59
  import type { PositionProps } from '@instructure/ui-position'
60
60
  import type { DialogProps } from '@instructure/ui-dialog'
61
61
 
62
- import { withStyle } from '@instructure/emotion'
62
+ import { withStyleLegacy as withStyle } from '@instructure/emotion'
63
63
 
64
64
  import generateStyle from './styles'
65
65
  import generateComponentTheme from './theme'
66
66
 
67
- import type { PopoverProps, PopoverState } from './props'
68
- import { allowedProps } from './props'
67
+ import type { PopoverProps, PopoverState } from '../v1/props'
68
+ import { allowedProps } from '../v1/props'
69
69
  import type { Renderable } from '@instructure/shared-types'
70
70
  /**
71
71
  ---
@@ -0,0 +1,455 @@
1
+ ---
2
+ describes: Popover
3
+ ---
4
+
5
+ Popovers hide or show content as a result of user interaction, such as clicking, hovering, or focusing. When opened, the content remains connected to the element that triggered it. If you only need to display a small amount of text-only content, you might consider using a [Tooltip](Tooltip). If you need to display a larger amount of content, a [Tray](Tray) could be a better choice.
6
+
7
+ #### Uncontrolled Popover
8
+
9
+ ```js
10
+ ---
11
+ type: example
12
+ ---
13
+ const Example = () => {
14
+ const [withArrow, setWithArrow] = useState(true)
15
+ const [shouldAlignArrow, setShouldAlignArrow] = useState(true)
16
+ const [color, setColor] = useState('primary')
17
+
18
+ const toggleWithArrow = () => {
19
+ setWithArrow((withArrow) => !withArrow)
20
+ }
21
+
22
+ const toggleAlignArrow = () => {
23
+ setShouldAlignArrow((shouldAlignArrow) => !shouldAlignArrow)
24
+ }
25
+
26
+ const changeColor = (event, color) => {
27
+ setColor(color)
28
+ }
29
+
30
+ return (
31
+ <>
32
+ <FormFieldGroup description="Uncontrolled Popover Example">
33
+ <Checkbox
34
+ checked={withArrow}
35
+ label="With Arrow"
36
+ onChange={toggleWithArrow}
37
+ />
38
+ <Checkbox
39
+ checked={shouldAlignArrow}
40
+ label="Align Arrow"
41
+ onChange={toggleAlignArrow}
42
+ />
43
+ </FormFieldGroup>
44
+ <View display="block" margin="small none">
45
+ <RadioInputGroup
46
+ name="color"
47
+ defaultValue="primary"
48
+ description="Color:"
49
+ variant="toggle"
50
+ size="small"
51
+ onChange={changeColor}
52
+ >
53
+ <RadioInput label="Primary" value="primary" />
54
+ <RadioInput label="Primary inverse" value="primary-inverse" />
55
+ </RadioInputGroup>
56
+ </View>
57
+ <View display="block" as="div" margin="small">
58
+ <Popover
59
+ renderTrigger={
60
+ <Link aria-describedby="tip">Hover or focus me</Link>
61
+ }
62
+ shouldRenderOffscreen
63
+ shouldReturnFocus={false}
64
+ withArrow={withArrow}
65
+ shouldAlignArrow={shouldAlignArrow}
66
+ color={color}
67
+ placement="top end"
68
+ onPositioned={() => console.log('positioned')}
69
+ onShowContent={() => console.log('showing')}
70
+ onHideContent={() => console.log('hidden')}
71
+ >
72
+ <View padding="x-small" display="block" as="div" id="tip">
73
+ Hello World
74
+ </View>
75
+ </Popover>
76
+ </View>
77
+ </>
78
+ )
79
+ }
80
+ render(<Example />)
81
+ ```
82
+
83
+ #### Controlled Popover
84
+
85
+ ```js
86
+ ---
87
+ type: example
88
+ ---
89
+ const Example = () => {
90
+ const [isShowingContent, setIsShowingContent] = useState(false)
91
+
92
+ const usernameRef = useRef(null)
93
+
94
+ const renderCloseButton = () => (
95
+ <CloseButton
96
+ placement="end"
97
+ offset="small"
98
+ onClick={() => setIsShowingContent(false)}
99
+ screenReaderLabel="Close"
100
+ />
101
+ )
102
+
103
+ return (
104
+ <View>
105
+ <Popover
106
+ renderTrigger={<Button>Sign In</Button>}
107
+ isShowingContent={isShowingContent}
108
+ onShowContent={() => {
109
+ setIsShowingContent(true)
110
+ }}
111
+ onHideContent={() => {
112
+ setIsShowingContent(false)
113
+ }}
114
+ on="click"
115
+ screenReaderLabel="Popover Dialog Example"
116
+ shouldContainFocus
117
+ shouldReturnFocus
118
+ shouldCloseOnDocumentClick
119
+ offsetY="16px"
120
+ >
121
+ <View padding="medium" display="block" as="form">
122
+ {renderCloseButton()}
123
+ <FormFieldGroup description="Log In">
124
+ <TextInput renderLabel="Username" ref={usernameRef} />
125
+ <TextInput renderLabel="Password" type="password" />
126
+ </FormFieldGroup>
127
+ </View>
128
+ </Popover>
129
+ </View>
130
+ )
131
+ }
132
+
133
+ render(<Example />)
134
+ ```
135
+
136
+ > Note: Popover can act as a dialog with a close button. With the `shouldContainFocus` property set, it will trap focus inside the Popover.
137
+
138
+ The `shouldAlignArrow` prop will offset the popover content to adjust for the offset of the arrow. This will override offsetX for start/end placements, and will override offsetY for top/bottom placements.
139
+
140
+ ```js
141
+ ---
142
+ type: example
143
+ ---
144
+ const Example = () => {
145
+ const [shouldAlignArrow, setShouldAlignArrow] = useState(true)
146
+
147
+ const toggleAlignArrow = () => {
148
+ setShouldAlignArrow((shouldAlignArrow) => !shouldAlignArrow)
149
+ }
150
+
151
+ return (
152
+ <>
153
+ <FormFieldGroup description="Align Arrow Example">
154
+ <Checkbox
155
+ checked={shouldAlignArrow}
156
+ label="Align Arrow"
157
+ onChange={toggleAlignArrow}
158
+ />
159
+ </FormFieldGroup>
160
+ <div
161
+ style={{
162
+ paddingBottom: 25,
163
+ display: 'flex',
164
+ justifyContent: 'center'
165
+ }}
166
+ >
167
+ <Popover
168
+ renderTrigger={
169
+ <div
170
+ style={{
171
+ display: 'inline-block',
172
+ height: '3px',
173
+ width: '3px',
174
+ background: 'blue'
175
+ }}
176
+ />
177
+ }
178
+ isShowingContent={true}
179
+ placement="end top"
180
+ shouldAlignArrow={shouldAlignArrow}
181
+ >
182
+ <Heading>
183
+ Small
184
+ <br />
185
+ Target
186
+ </Heading>
187
+ </Popover>
188
+ </div>
189
+ </>
190
+ )
191
+ }
192
+
193
+ render(<Example />)
194
+ ```
195
+
196
+ If the `Popover` contains focusable content and should be rendered in the focus order immediately after the trigger, it can be configured using the `shouldFocusContentOnTriggerBlur` prop. Note that the content must be rendered in the correct order in the document (using the `mountNode` prop).
197
+
198
+ ```js
199
+ ---
200
+ type: example
201
+ ---
202
+ const Example = () => {
203
+ const [isShowingContent, setIsShowingContent] = useState(false)
204
+
205
+ return (
206
+ <div
207
+ style={{ paddingBottom: 50, display: 'flex', justifyContent: 'center' }}
208
+ >
209
+ <Popover
210
+ renderTrigger={<Button margin="small">Focus Me</Button>}
211
+ isShowingContent={isShowingContent}
212
+ onShowContent={() => {
213
+ setIsShowingContent(true)
214
+ }}
215
+ onHideContent={() => {
216
+ setIsShowingContent(false)
217
+ }}
218
+ on={['hover', 'focus']}
219
+ shouldContainFocus={false}
220
+ shouldFocusContentOnTriggerBlur={false}
221
+ >
222
+ <Button margin="small">Focus Me When Trigger Blurs</Button>
223
+ </Popover>
224
+ <div id="container" />
225
+ <Button id="next" margin="small">
226
+ Focus Me Next
227
+ </Button>
228
+ </div>
229
+ )
230
+ }
231
+
232
+ render(<Example />)
233
+ ```
234
+
235
+ #### Custom elements as renderTrigger
236
+
237
+ Popover and Tooltip attach mouse and focus event listeners to their `renderTrigger` components via props. These need to be propagated to the component for the listeners to work:
238
+
239
+ ```js
240
+ ---
241
+ type: example
242
+ ---
243
+ const MyComponent = React.forwardRef((props, ref) => {
244
+ return (
245
+ <div {...props} ref={ref} style={{ width: '10rem' }}>
246
+ My custom component
247
+ </div>
248
+ )
249
+ })
250
+
251
+ render(<MyComponent />)
252
+ ;<Popover renderTrigger={<MyComponent />}>
253
+ This text is wrapped by a Popover
254
+ </Popover>
255
+ ```
256
+
257
+ #### Popover playground
258
+
259
+ ```js
260
+ ---
261
+ type: example
262
+ ---
263
+ const placementsValues = [
264
+ 'top',
265
+ 'end',
266
+ 'bottom',
267
+ 'start',
268
+ 'top start',
269
+ 'start top',
270
+ 'start center',
271
+ 'start bottom',
272
+ 'bottom start',
273
+ 'bottom center',
274
+ 'bottom end',
275
+ 'end bottom',
276
+ 'end center',
277
+ 'end top',
278
+ 'top end',
279
+ 'top center',
280
+ 'center end',
281
+ 'center start'
282
+ ]
283
+
284
+ const shadowValues = ['none', 'resting', 'above', 'topmost']
285
+
286
+ const Example = () => {
287
+ const [shouldAlignArrow, setShouldAlignArrow] = useState(true)
288
+ const [isShowingContent, setIsShowingContent] = useState(true)
289
+ const [withArrow, setWithArrow] = useState(true)
290
+ const [placement, setPlacement] = useState('top')
291
+ const [shadow, setShadow] = useState('topmost')
292
+ const [color, setColor] = useState('primary')
293
+
294
+ const changePlacement = (e, { value }) => {
295
+ setPlacement(value)
296
+ }
297
+
298
+ const changeShadow = (e, { value }) => {
299
+ setShadow(value)
300
+ }
301
+
302
+ const toggleWithArrow = () => {
303
+ setWithArrow((withArrow) => !withArrow)
304
+ }
305
+
306
+ const toggleAlignArrow = () => {
307
+ setShouldAlignArrow((shouldAlignArrow) => !shouldAlignArrow)
308
+ }
309
+
310
+ const toggleShowContent = () =>
311
+ setIsShowingContent((isShowingContent) => !isShowingContent)
312
+
313
+ const changeColor = (event, value) => {
314
+ setColor(value)
315
+ }
316
+
317
+ return (
318
+ <View as="div" background="primary" padding="small">
319
+ <Flex margin="small small large" justifyItems="space-around">
320
+ <Flex.Item align="start">
321
+ <FormFieldGroup description="Popover Example">
322
+ <Checkbox
323
+ checked={isShowingContent}
324
+ label="Show Content"
325
+ onChange={toggleShowContent}
326
+ />
327
+ <Checkbox
328
+ checked={withArrow}
329
+ label="With Arrow"
330
+ onChange={toggleWithArrow}
331
+ />
332
+ <Checkbox
333
+ checked={shouldAlignArrow}
334
+ label="Align Arrow"
335
+ onChange={toggleAlignArrow}
336
+ />
337
+ </FormFieldGroup>
338
+ </Flex.Item>
339
+ <Flex.Item>
340
+ <View as="div" margin="none" maxWidth="15rem">
341
+ <SimpleSelect
342
+ renderLabel="Placement"
343
+ value={placement}
344
+ onChange={changePlacement}
345
+ >
346
+ {placementsValues.map((placement, index) => (
347
+ <SimpleSelect.Option
348
+ key={index}
349
+ id={`${index}`}
350
+ value={placement}
351
+ >
352
+ {placement}
353
+ </SimpleSelect.Option>
354
+ ))}
355
+ </SimpleSelect>
356
+ </View>
357
+ <View as="div" margin="medium none" maxWidth="15rem">
358
+ <SimpleSelect
359
+ value={shadow}
360
+ onChange={changeShadow}
361
+ renderLabel="Shadow"
362
+ >
363
+ {shadowValues.map((shadow, index) => (
364
+ <SimpleSelect.Option
365
+ key={index}
366
+ id={`${index}`}
367
+ value={shadow}
368
+ >
369
+ {shadow}
370
+ </SimpleSelect.Option>
371
+ ))}
372
+ </SimpleSelect>
373
+ </View>
374
+ </Flex.Item>
375
+ <Flex.Item align="start">
376
+ <View as="div" margin="none">
377
+ <RadioInputGroup
378
+ name="changeColor"
379
+ defaultValue="primary"
380
+ description="Color:"
381
+ variant="toggle"
382
+ size="small"
383
+ onChange={changeColor}
384
+ >
385
+ <RadioInput label="Primary" value="primary" />
386
+ <RadioInput label="Primary inverse" value="primary-inverse" />
387
+ </RadioInputGroup>
388
+ </View>
389
+ </Flex.Item>
390
+ </Flex>
391
+ <View as="div" display="block" padding="large" textAlign="center">
392
+ <Popover
393
+ renderTrigger={
394
+ <div
395
+ style={{
396
+ display: 'inline-block',
397
+ height: '3px',
398
+ width: '3px',
399
+ background: 'blue'
400
+ }}
401
+ />
402
+ }
403
+ isShowingContent={isShowingContent}
404
+ placement={placement}
405
+ withArrow={withArrow}
406
+ shouldAlignArrow={shouldAlignArrow}
407
+ shadow={shadow}
408
+ color={color}
409
+ >
410
+ <Heading>
411
+ Small
412
+ <br />
413
+ Target
414
+ </Heading>
415
+ </Popover>
416
+ </View>
417
+ </View>
418
+ )
419
+ }
420
+
421
+ render(<Example />)
422
+ ```
423
+
424
+ ### Guidelines
425
+
426
+ ```js
427
+ ---
428
+ type: embed
429
+ ---
430
+ <Guidelines>
431
+ <Figure recommendation="yes" title="Do">
432
+ <Figure.Item>Consider using a <Link href="/#Tray">Tray</Link> if the content is beyond a mobile screen size</Figure.Item>
433
+ </Figure>
434
+ <Figure recommendation="no" title="Don't">
435
+ <Figure.Item>Put content on the same row as the close "x"</Figure.Item>
436
+ <Figure.Item>Use with an <Link href="#Overlay">Overlay</Link></Figure.Item>
437
+ <Figure.Item>Have multiple Popovers open at the same time</Figure.Item>
438
+ <Figure.Item>Use in place of a <Link href="/#Tooltip">Tooltip</Link> or <Link href="/#Menu">Menu</Link></Figure.Item>
439
+ </Figure>
440
+ </Guidelines>
441
+ ```
442
+
443
+ ```js
444
+ ---
445
+ type: embed
446
+ ---
447
+ <Guidelines>
448
+ <Figure recommendation="a11y" title="Accessibility">
449
+ <Figure.Item>Keyboard focus must be set in the popover when it appears; usually on the first interactive element</Figure.Item>
450
+ <Figure.Item>Popovers must contain keyboard focus until they’re closed. This is to ensure that keyboard or screen reader users won't mistakenly interact with background content that is meant to be hidden or inaccessible</Figure.Item>
451
+ <Figure.Item>When a user closes the Popover, focus must return to a logical place within the page. This is usually the element that triggered opening the popover</Figure.Item>
452
+ <Figure.Item>Popovers should be able to be closed by clicking away, esc key and/or a close button</Figure.Item>
453
+ </Figure>
454
+ </Guidelines>
455
+ ```