@atlaskit/top-layer 0.12.2 → 0.14.0

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 (245) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +61 -34
  3. package/dist/cjs/animations/presets.js +4 -4
  4. package/dist/cjs/entry-points/focus.js +6 -4
  5. package/dist/cjs/entry-points/get-aria-for-trigger.js +12 -0
  6. package/dist/cjs/entry-points/popover-surface.js +12 -0
  7. package/dist/cjs/entry-points/use-anchor-position-at-point.js +12 -0
  8. package/dist/cjs/entry-points/use-popover-id.js +21 -0
  9. package/dist/cjs/focus/get-first-focusable.js +19 -0
  10. package/dist/cjs/focus/get-focusables.js +30 -0
  11. package/dist/cjs/focus/get-last-focusable.js +19 -0
  12. package/dist/cjs/focus/get-next-focusable.js +43 -0
  13. package/dist/cjs/focus/is-in-same-layer.js +23 -0
  14. package/dist/cjs/focus/is-nested-layer-focused.js +32 -0
  15. package/dist/cjs/focus/selectors.js +19 -0
  16. package/dist/cjs/focus/types.js +1 -0
  17. package/dist/cjs/internal/get-aria-for-trigger.js +88 -0
  18. package/dist/cjs/internal/role-to-aria-has-popup.js +37 -0
  19. package/dist/cjs/internal/role-types.js +2 -35
  20. package/dist/cjs/internal/should-focus-into-popover.js +19 -0
  21. package/dist/cjs/internal/slot.js +1 -1
  22. package/dist/cjs/internal/use-anchor-position-at-point.js +127 -0
  23. package/dist/cjs/internal/use-anchor-position.js +36 -16
  24. package/dist/cjs/internal/use-focus-wrap.js +8 -5
  25. package/dist/cjs/internal/use-initial-focus.js +4 -4
  26. package/dist/cjs/placement-map/index.js +2 -2
  27. package/dist/cjs/placement-map/legacy-placements.js +2 -101
  28. package/dist/cjs/placement-map/placement-mapping.js +103 -0
  29. package/dist/cjs/popover/popover.js +79 -80
  30. package/dist/cjs/popover-surface/index.js +12 -0
  31. package/dist/cjs/{popup/popup-surface.js → popover-surface/popover-surface.js} +9 -12
  32. package/dist/cjs/testing/polyfill.js +9 -6
  33. package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +7 -5
  34. package/dist/es2019/animations/presets.js +4 -4
  35. package/dist/es2019/entry-points/focus.js +3 -1
  36. package/dist/es2019/entry-points/get-aria-for-trigger.js +1 -0
  37. package/dist/es2019/entry-points/popover-surface.js +1 -0
  38. package/dist/es2019/entry-points/use-anchor-position-at-point.js +1 -0
  39. package/dist/es2019/entry-points/use-popover-id.js +15 -0
  40. package/dist/es2019/focus/get-first-focusable.js +14 -0
  41. package/dist/es2019/focus/get-focusables.js +19 -0
  42. package/dist/es2019/focus/get-last-focusable.js +14 -0
  43. package/dist/es2019/focus/get-next-focusable.js +38 -0
  44. package/dist/es2019/focus/is-in-same-layer.js +18 -0
  45. package/dist/es2019/focus/is-nested-layer-focused.js +28 -0
  46. package/dist/es2019/focus/selectors.js +11 -0
  47. package/dist/es2019/focus/types.js +0 -0
  48. package/dist/es2019/internal/get-aria-for-trigger.js +84 -0
  49. package/dist/es2019/internal/role-to-aria-has-popup.js +32 -0
  50. package/dist/es2019/internal/role-types.js +0 -33
  51. package/dist/es2019/internal/should-focus-into-popover.js +14 -0
  52. package/dist/es2019/internal/slot.js +1 -1
  53. package/dist/es2019/internal/use-anchor-position-at-point.js +122 -0
  54. package/dist/es2019/internal/use-anchor-position.js +21 -14
  55. package/dist/es2019/internal/use-focus-wrap.js +4 -1
  56. package/dist/es2019/internal/use-initial-focus.js +1 -1
  57. package/dist/es2019/placement-map/index.js +1 -1
  58. package/dist/es2019/placement-map/legacy-placements.js +1 -100
  59. package/dist/es2019/placement-map/placement-mapping.js +97 -0
  60. package/dist/es2019/popover/popover.js +79 -80
  61. package/dist/es2019/popover-surface/index.js +1 -0
  62. package/dist/es2019/popover-surface/popover-surface.js +27 -0
  63. package/dist/es2019/testing/polyfill.js +9 -6
  64. package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +3 -1
  65. package/dist/esm/animations/presets.js +4 -4
  66. package/dist/esm/entry-points/focus.js +3 -1
  67. package/dist/esm/entry-points/get-aria-for-trigger.js +1 -0
  68. package/dist/esm/entry-points/popover-surface.js +1 -0
  69. package/dist/esm/entry-points/use-anchor-position-at-point.js +1 -0
  70. package/dist/esm/entry-points/use-popover-id.js +15 -0
  71. package/dist/esm/focus/get-first-focusable.js +13 -0
  72. package/dist/esm/focus/get-focusables.js +24 -0
  73. package/dist/esm/focus/get-last-focusable.js +13 -0
  74. package/dist/esm/focus/get-next-focusable.js +37 -0
  75. package/dist/esm/focus/is-in-same-layer.js +17 -0
  76. package/dist/esm/focus/is-nested-layer-focused.js +27 -0
  77. package/dist/esm/focus/selectors.js +13 -0
  78. package/dist/esm/focus/types.js +0 -0
  79. package/dist/esm/internal/get-aria-for-trigger.js +83 -0
  80. package/dist/esm/internal/role-to-aria-has-popup.js +31 -0
  81. package/dist/esm/internal/role-types.js +2 -34
  82. package/dist/esm/internal/should-focus-into-popover.js +13 -0
  83. package/dist/esm/internal/slot.js +1 -1
  84. package/dist/esm/internal/use-anchor-position-at-point.js +122 -0
  85. package/dist/esm/internal/use-anchor-position.js +36 -16
  86. package/dist/esm/internal/use-focus-wrap.js +4 -1
  87. package/dist/esm/internal/use-initial-focus.js +1 -1
  88. package/dist/esm/placement-map/index.js +1 -1
  89. package/dist/esm/placement-map/legacy-placements.js +1 -100
  90. package/dist/esm/placement-map/placement-mapping.js +97 -0
  91. package/dist/esm/popover/popover.js +79 -80
  92. package/dist/esm/popover-surface/index.js +1 -0
  93. package/dist/esm/popover-surface/popover-surface.js +26 -0
  94. package/dist/esm/testing/polyfill.js +9 -6
  95. package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +3 -1
  96. package/dist/types/animations/presets.d.ts +4 -4
  97. package/dist/types/animations/types.d.ts +1 -1
  98. package/dist/types/dialog/types.d.ts +0 -8
  99. package/dist/types/entry-points/focus.d.ts +4 -2
  100. package/dist/types/entry-points/get-aria-for-trigger.d.ts +1 -0
  101. package/dist/types/entry-points/popover-surface.d.ts +2 -0
  102. package/dist/types/entry-points/popover.d.ts +1 -1
  103. package/dist/types/entry-points/use-anchor-position-at-point.d.ts +1 -0
  104. package/dist/types/entry-points/use-popover-id.d.ts +11 -0
  105. package/dist/types/focus/get-first-focusable.d.ts +8 -0
  106. package/dist/types/focus/get-focusables.d.ts +13 -0
  107. package/dist/types/focus/get-last-focusable.d.ts +8 -0
  108. package/dist/types/focus/get-next-focusable.d.ts +13 -0
  109. package/dist/types/focus/is-in-same-layer.d.ts +8 -0
  110. package/dist/types/focus/is-nested-layer-focused.d.ts +8 -0
  111. package/dist/types/focus/selectors.d.ts +4 -0
  112. package/dist/types/focus/types.d.ts +5 -0
  113. package/dist/types/internal/get-aria-for-trigger.d.ts +86 -0
  114. package/dist/types/internal/role-to-aria-has-popup.d.ts +13 -0
  115. package/dist/types/internal/role-types.d.ts +0 -12
  116. package/dist/types/internal/should-focus-into-popover.d.ts +8 -0
  117. package/dist/types/internal/slot.d.ts +2 -2
  118. package/dist/types/internal/use-anchor-position-at-point.d.ts +62 -0
  119. package/dist/types/internal/use-anchor-position.d.ts +6 -1
  120. package/dist/types/placement-map/index.d.ts +1 -1
  121. package/dist/types/placement-map/legacy-placements.d.ts +0 -12
  122. package/dist/types/placement-map/placement-mapping.d.ts +13 -0
  123. package/dist/types/popover/index.d.ts +1 -1
  124. package/dist/types/popover/popover.d.ts +6 -13
  125. package/dist/types/popover/types.d.ts +6 -5
  126. package/dist/types/popover-surface/index.d.ts +2 -0
  127. package/dist/types/popover-surface/popover-surface.d.ts +21 -0
  128. package/dist/types/use-arrow-navigation/use-arrow-navigation.d.ts +1 -1
  129. package/dist/types-ts4.5/animations/presets.d.ts +4 -4
  130. package/dist/types-ts4.5/animations/types.d.ts +1 -1
  131. package/dist/types-ts4.5/dialog/types.d.ts +0 -8
  132. package/dist/types-ts4.5/entry-points/focus.d.ts +4 -2
  133. package/dist/types-ts4.5/entry-points/get-aria-for-trigger.d.ts +1 -0
  134. package/dist/types-ts4.5/entry-points/popover-surface.d.ts +2 -0
  135. package/dist/types-ts4.5/entry-points/popover.d.ts +1 -1
  136. package/dist/types-ts4.5/entry-points/use-anchor-position-at-point.d.ts +1 -0
  137. package/dist/types-ts4.5/entry-points/use-popover-id.d.ts +11 -0
  138. package/dist/types-ts4.5/focus/get-first-focusable.d.ts +8 -0
  139. package/dist/types-ts4.5/focus/get-focusables.d.ts +13 -0
  140. package/dist/types-ts4.5/focus/get-last-focusable.d.ts +8 -0
  141. package/dist/types-ts4.5/focus/get-next-focusable.d.ts +13 -0
  142. package/dist/types-ts4.5/focus/is-in-same-layer.d.ts +8 -0
  143. package/dist/types-ts4.5/focus/is-nested-layer-focused.d.ts +8 -0
  144. package/dist/types-ts4.5/focus/selectors.d.ts +4 -0
  145. package/dist/types-ts4.5/focus/types.d.ts +5 -0
  146. package/dist/types-ts4.5/internal/get-aria-for-trigger.d.ts +86 -0
  147. package/dist/types-ts4.5/internal/role-to-aria-has-popup.d.ts +13 -0
  148. package/dist/types-ts4.5/internal/role-types.d.ts +0 -12
  149. package/dist/types-ts4.5/internal/should-focus-into-popover.d.ts +8 -0
  150. package/dist/types-ts4.5/internal/slot.d.ts +2 -2
  151. package/dist/types-ts4.5/internal/use-anchor-position-at-point.d.ts +62 -0
  152. package/dist/types-ts4.5/internal/use-anchor-position.d.ts +6 -1
  153. package/dist/types-ts4.5/placement-map/index.d.ts +1 -1
  154. package/dist/types-ts4.5/placement-map/legacy-placements.d.ts +0 -12
  155. package/dist/types-ts4.5/placement-map/placement-mapping.d.ts +13 -0
  156. package/dist/types-ts4.5/popover/index.d.ts +1 -1
  157. package/dist/types-ts4.5/popover/popover.d.ts +6 -13
  158. package/dist/types-ts4.5/popover/types.d.ts +6 -5
  159. package/dist/types-ts4.5/popover-surface/index.d.ts +2 -0
  160. package/dist/types-ts4.5/popover-surface/popover-surface.d.ts +21 -0
  161. package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +1 -1
  162. package/get-aria-for-trigger/package.json +17 -0
  163. package/package.json +3 -3
  164. package/popover-surface/package.json +17 -0
  165. package/use-anchor-position-at-point/package.json +17 -0
  166. package/use-popover-id/package.json +17 -0
  167. package/dist/cjs/entry-points/popup-surface.js +0 -12
  168. package/dist/cjs/entry-points/popup.js +0 -12
  169. package/dist/cjs/focus/focus.js +0 -169
  170. package/dist/cjs/focus/index.js +0 -24
  171. package/dist/cjs/popup/index.js +0 -37
  172. package/dist/cjs/popup/popup-content.js +0 -214
  173. package/dist/cjs/popup/popup-context.js +0 -25
  174. package/dist/cjs/popup/popup-provider.js +0 -15
  175. package/dist/cjs/popup/popup-trigger-function.js +0 -80
  176. package/dist/cjs/popup/popup-trigger.js +0 -66
  177. package/dist/cjs/popup/popup.js +0 -81
  178. package/dist/cjs/popup/types.js +0 -5
  179. package/dist/cjs/popup/use-maybe-popup-context.js +0 -17
  180. package/dist/cjs/popup/use-popup-context.js +0 -20
  181. package/dist/es2019/entry-points/popup-surface.js +0 -1
  182. package/dist/es2019/entry-points/popup.js +0 -1
  183. package/dist/es2019/focus/focus.js +0 -158
  184. package/dist/es2019/focus/index.js +0 -1
  185. package/dist/es2019/popup/index.js +0 -33
  186. package/dist/es2019/popup/popup-content.js +0 -206
  187. package/dist/es2019/popup/popup-context.js +0 -20
  188. package/dist/es2019/popup/popup-provider.js +0 -10
  189. package/dist/es2019/popup/popup-surface.js +0 -30
  190. package/dist/es2019/popup/popup-trigger-function.js +0 -75
  191. package/dist/es2019/popup/popup-trigger.js +0 -61
  192. package/dist/es2019/popup/popup.js +0 -67
  193. package/dist/es2019/popup/types.js +0 -1
  194. package/dist/es2019/popup/use-maybe-popup-context.js +0 -12
  195. package/dist/es2019/popup/use-popup-context.js +0 -15
  196. package/dist/esm/entry-points/popup-surface.js +0 -1
  197. package/dist/esm/entry-points/popup.js +0 -1
  198. package/dist/esm/focus/focus.js +0 -160
  199. package/dist/esm/focus/index.js +0 -1
  200. package/dist/esm/popup/index.js +0 -33
  201. package/dist/esm/popup/popup-content.js +0 -206
  202. package/dist/esm/popup/popup-context.js +0 -20
  203. package/dist/esm/popup/popup-provider.js +0 -10
  204. package/dist/esm/popup/popup-surface.js +0 -29
  205. package/dist/esm/popup/popup-trigger-function.js +0 -75
  206. package/dist/esm/popup/popup-trigger.js +0 -59
  207. package/dist/esm/popup/popup.js +0 -72
  208. package/dist/esm/popup/types.js +0 -1
  209. package/dist/esm/popup/use-maybe-popup-context.js +0 -12
  210. package/dist/esm/popup/use-popup-context.js +0 -15
  211. package/dist/types/entry-points/popup-surface.d.ts +0 -2
  212. package/dist/types/entry-points/popup.d.ts +0 -2
  213. package/dist/types/focus/focus.d.ts +0 -50
  214. package/dist/types/focus/index.d.ts +0 -2
  215. package/dist/types/popup/index.d.ts +0 -34
  216. package/dist/types/popup/popup-content.d.ts +0 -14
  217. package/dist/types/popup/popup-context.d.ts +0 -96
  218. package/dist/types/popup/popup-provider.d.ts +0 -10
  219. package/dist/types/popup/popup-surface.d.ts +0 -22
  220. package/dist/types/popup/popup-trigger-function.d.ts +0 -112
  221. package/dist/types/popup/popup-trigger.d.ts +0 -14
  222. package/dist/types/popup/popup.d.ts +0 -14
  223. package/dist/types/popup/types.d.ts +0 -321
  224. package/dist/types/popup/use-maybe-popup-context.d.ts +0 -8
  225. package/dist/types/popup/use-popup-context.d.ts +0 -7
  226. package/dist/types-ts4.5/entry-points/popup-surface.d.ts +0 -2
  227. package/dist/types-ts4.5/entry-points/popup.d.ts +0 -2
  228. package/dist/types-ts4.5/focus/focus.d.ts +0 -50
  229. package/dist/types-ts4.5/focus/index.d.ts +0 -2
  230. package/dist/types-ts4.5/popup/index.d.ts +0 -34
  231. package/dist/types-ts4.5/popup/popup-content.d.ts +0 -14
  232. package/dist/types-ts4.5/popup/popup-context.d.ts +0 -96
  233. package/dist/types-ts4.5/popup/popup-provider.d.ts +0 -10
  234. package/dist/types-ts4.5/popup/popup-surface.d.ts +0 -22
  235. package/dist/types-ts4.5/popup/popup-trigger-function.d.ts +0 -112
  236. package/dist/types-ts4.5/popup/popup-trigger.d.ts +0 -14
  237. package/dist/types-ts4.5/popup/popup.d.ts +0 -14
  238. package/dist/types-ts4.5/popup/types.d.ts +0 -321
  239. package/dist/types-ts4.5/popup/use-maybe-popup-context.d.ts +0 -8
  240. package/dist/types-ts4.5/popup/use-popup-context.d.ts +0 -7
  241. package/popup/package.json +0 -17
  242. package/popup-surface/package.json +0 -17
  243. /package/dist/cjs/{popup/popup-surface.compiled.css → popover-surface/popover-surface.compiled.css} +0 -0
  244. /package/dist/es2019/{popup/popup-surface.compiled.css → popover-surface/popover-surface.compiled.css} +0 -0
  245. /package/dist/esm/{popup/popup-surface.compiled.css → popover-surface/popover-surface.compiled.css} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # @atlaskit/top-layer
2
2
 
3
+ ## 0.14.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`021a645c6f39a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/021a645c6f39a) -
8
+ Remove the `Popup` compound and `PopupSurface`; use `Popover`, `PopoverSurface`,
9
+ `useAnchorPosition`, `useWidthFromAnchor`, `usePopoverId`, and `getAriaForTrigger` instead.
10
+
11
+ Nested-popover focus restoration is now automatic: `Popover` snapshots `document.activeElement` in
12
+ `beforetoggle` (newState='open') and restores it on close for focus-capturing roles (`dialog`,
13
+ `alertdialog`, `menu`, `listbox`, `tree`, `grid`) when the close reason is Escape or programmatic.
14
+ Click-outside (light dismiss) intentionally does not restore focus, matching the HTML Popover
15
+ spec's `focusPreviousElement=false` rule. This fixes a Firefox bug where nested popovers left
16
+ focus on `<body>` after dismiss.
17
+
18
+ ## 0.13.0
19
+
20
+ ### Minor Changes
21
+
22
+ - [`cf4af9aa9a2fe`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/cf4af9aa9a2fe) -
23
+ Fix tooltip with `position="mouse-x"` / `position="mouse-y"` not respecting the `mousePosition`
24
+ prop when the `platform-dst-top-layer` feature flag is enabled.
25
+
26
+ The cursor-anchored tooltip is now positioned via a new `useAnchorPositionAtPoint` hook in
27
+ `@atlaskit/top-layer`, which delegates to `useAnchorPosition` against a hidden anchor element
28
+ placed once at the cursor location at show time. The popover stays anchored at that location and
29
+ does not follow subsequent pointer movement.
30
+
31
+ `useAnchorPosition` now also accepts an optional `isEnabled` prop (defaults to `true`); when
32
+ `false`, the hook is a no-op.
33
+
3
34
  ## 0.12.2
4
35
 
5
36
  ### Patch Changes
package/README.md CHANGED
@@ -4,36 +4,63 @@ Low-level top-layer primitives using the native
4
4
  [Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API) (`popover="auto"`) and
5
5
  [`<dialog>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog) element.
6
6
 
7
- ## Popup
7
+ ## Popover
8
8
 
9
- Compound component for rendering content in the browser's top layer with CSS Anchor Positioning.
10
- Placement is owned by this compound: root provides it via context, Content applies it (CSS Anchor
11
- Positioning or JS fallback).
9
+ The primary primitive: a `<div>` with the `popover` attribute, plus a small lifecycle (animations,
10
+ role-based focus management, light-dismiss, nested-focus restoration). It does **not** know about
11
+ placement — compose it with the `useAnchorPosition` hook when you need anchor-positioned content.
12
12
 
13
13
  ```tsx
14
- <Popup onClose={handleClose}>
15
- <Popup.Trigger>
16
- <button>Open</button>
17
- </Popup.Trigger>
18
- <Popup.Content role="dialog" label="My popup">
19
- Content here
20
- </Popup.Content>
21
- </Popup>
14
+ import { useRef } from 'react';
15
+ import { slideAndFade } from '@atlaskit/top-layer/animations';
16
+ import { getAriaForTrigger } from '@atlaskit/top-layer/get-aria-for-trigger';
17
+ import { Popover } from '@atlaskit/top-layer/popover';
18
+ import { PopoverSurface } from '@atlaskit/top-layer/popover-surface';
19
+ import { usePopoverId } from '@atlaskit/top-layer/use-popover-id';
20
+ import { useAnchorPosition } from '@atlaskit/top-layer/use-anchor-position';
21
+
22
+ function MyPopup({ isOpen, onClose }: { isOpen: boolean; onClose: () => void }) {
23
+ const triggerRef = useRef<HTMLButtonElement>(null);
24
+ const popoverRef = useRef<HTMLDivElement>(null);
25
+ const popoverId = usePopoverId();
26
+
27
+ useAnchorPosition({
28
+ anchorRef: triggerRef,
29
+ popoverRef,
30
+ placement: { axis: 'block', edge: 'end', align: 'start' },
31
+ });
32
+
33
+ return (
34
+ <>
35
+ <button
36
+ ref={triggerRef}
37
+ onClick={() => popoverRef.current?.togglePopover()}
38
+ {...getAriaForTrigger({ role: 'dialog', isOpen, popoverId })}
39
+ >
40
+ Open
41
+ </button>
42
+ <Popover
43
+ ref={popoverRef}
44
+ id={popoverId}
45
+ role="dialog"
46
+ label="Settings"
47
+ isOpen={isOpen}
48
+ animate={slideAndFade()}
49
+ onClose={onClose}
50
+ >
51
+ <PopoverSurface>Content here</PopoverSurface>
52
+ </Popover>
53
+ </>
54
+ );
55
+ }
22
56
  ```
23
57
 
24
- `placement` defaults to `{}` - "below trigger, centered, with `space.100` gap". Pass an explicit
25
- object to override (e.g. `placement={{ axis: 'inline', edge: 'end' }}` for a popover anchored to the
26
- trigger's right edge).
27
-
28
- For default overlay styling (background, shadow, border-radius), see `PopupSurface` in the package
29
- examples (not currently a public API; we may expose it in a future release).
30
-
31
- ## Popover
32
-
33
- Low-level primitive: a `<div>` with the `popover` attribute and show/hide lifecycle only. No
34
- placement, no trigger wiring — use it when you need top-layer rendering with **fixed or custom
35
- positioning** (e.g. Flag uses `Popover mode="manual"`). For anchor-positioned content next to a
36
- trigger, use **Popup** instead.
58
+ - Focus restoration is automatic. The browser handles it for outermost popovers; `Popover`
59
+ snapshots `document.activeElement` on open and restores it on close for nested cases.
60
+ - For default overlay styling (background, shadow, border-radius), wrap content in `PopoverSurface`
61
+ from `@atlaskit/top-layer/popover-surface`.
62
+ - For trigger-less or custom-positioned UI (flag, tooltip, react-select menu portal), use `Popover`
63
+ on its own without `useAnchorPosition`.
37
64
 
38
65
  ## Dialog
39
66
 
@@ -60,8 +87,8 @@ Compound component for modal dialogs using the native `<dialog>` element with `.
60
87
 
61
88
  ## Animations
62
89
 
63
- Both Popup (and the low-level Popover) and Dialog support CSS-based entry/exit animations via the
64
- `animate` prop. Animations use
90
+ Both `Popover` and `Dialog` support CSS-based entry/exit animations via the `animate` prop.
91
+ Animations use
65
92
  [`@starting-style`](https://developer.mozilla.org/en-US/docs/Web/CSS/@starting-style) for entry and
66
93
  [`allow-discrete`](https://developer.mozilla.org/en-US/docs/Web/CSS/transition-behavior) on
67
94
  `display`/`overlay` for exit — no JavaScript animation coordination required.
@@ -80,23 +107,23 @@ import {
80
107
  } from '@atlaskit/top-layer/animations';
81
108
  ```
82
109
 
83
- ### Popup animation
110
+ ### Popover animation
84
111
 
85
- Pass a preset to `Popup.Content` (or to `Popover` when using the low-level primitive without
86
- placement):
112
+ Pass a preset to `Popover`:
87
113
 
88
114
  ```tsx
89
115
  import { slideAndFade } from '@atlaskit/top-layer/animations';
116
+ import { Popover } from '@atlaskit/top-layer/popover';
90
117
 
91
118
  const animation = slideAndFade();
92
119
 
93
- <Popup.Content animate={animation} role="dialog" label="My popup">
120
+ <Popover animate={animation} role="dialog" label="My popover">
94
121
  Content
95
- </Popup.Content>;
122
+ </Popover>;
96
123
  ```
97
124
 
98
- For overlay styling (background, shadow, border-radius), see the `PopupSurface` usage in the package
99
- examples.
125
+ For overlay styling (background, shadow, border-radius), wrap children in `PopoverSurface` from
126
+ `@atlaskit/top-layer/popover-surface`.
100
127
 
101
128
  Available popover presets:
102
129
 
@@ -67,10 +67,10 @@ var SLIDE_AND_FADE_CSS = "\n[data-ds-popover-slide-and-fade] {\n opacity: 0;\n
67
67
  * import { slideAndFade } from '@atlaskit/top-layer/animations';
68
68
  *
69
69
  * // Default 4px slide (tooltip)
70
- * <Popup.Content animate={slideAndFade()} />
70
+ * <Popover animate={slideAndFade()} />
71
71
  *
72
72
  * // Custom 8px slide (popup / dropdown)
73
- * <Popup.Content animate={slideAndFade({ distance: 8 })} />
73
+ * <Popover animate={slideAndFade({ distance: 8 })} />
74
74
  * ```
75
75
  */
76
76
  function slideAndFade(options) {
@@ -104,7 +104,7 @@ var FADE_CSS = "\n[data-ds-popover-fade] {\n opacity: 0;\n transition:\n op
104
104
  * ```tsx
105
105
  * import { fade } from '@atlaskit/top-layer/animations';
106
106
  *
107
- * <Popup.Content animate={fade()} />
107
+ * <Popover animate={fade()} />
108
108
  * ```
109
109
  */
110
110
  // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
@@ -130,7 +130,7 @@ var SCALE_AND_FADE_CSS = "\n[data-ds-popover-scale-and-fade] {\n opacity: 0;\n
130
130
  * ```tsx
131
131
  * import { scaleAndFade } from '@atlaskit/top-layer/animations';
132
132
  *
133
- * <Popup.Content animate={scaleAndFade()} />
133
+ * <Popover animate={scaleAndFade()} />
134
134
  * ```
135
135
  */
136
136
  // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
@@ -6,19 +6,21 @@ Object.defineProperty(exports, "__esModule", {
6
6
  Object.defineProperty(exports, "getFirstFocusable", {
7
7
  enumerable: true,
8
8
  get: function get() {
9
- return _focus.getFirstFocusable;
9
+ return _getFirstFocusable.getFirstFocusable;
10
10
  }
11
11
  });
12
12
  Object.defineProperty(exports, "getLastFocusable", {
13
13
  enumerable: true,
14
14
  get: function get() {
15
- return _focus.getLastFocusable;
15
+ return _getLastFocusable.getLastFocusable;
16
16
  }
17
17
  });
18
18
  Object.defineProperty(exports, "getNextFocusable", {
19
19
  enumerable: true,
20
20
  get: function get() {
21
- return _focus.getNextFocusable;
21
+ return _getNextFocusable.getNextFocusable;
22
22
  }
23
23
  });
24
- var _focus = require("../focus");
24
+ var _getFirstFocusable = require("../focus/get-first-focusable");
25
+ var _getLastFocusable = require("../focus/get-last-focusable");
26
+ var _getNextFocusable = require("../focus/get-next-focusable");
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "getAriaForTrigger", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _getAriaForTrigger.getAriaForTrigger;
10
+ }
11
+ });
12
+ var _getAriaForTrigger = require("../internal/get-aria-for-trigger");
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "PopoverSurface", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _popoverSurface.PopoverSurface;
10
+ }
11
+ });
12
+ var _popoverSurface = require("../popover-surface");
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "useAnchorPositionAtPoint", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _useAnchorPositionAtPoint.useAnchorPositionAtPoint;
10
+ }
11
+ });
12
+ var _useAnchorPositionAtPoint = require("../internal/use-anchor-position-at-point");
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.usePopoverId = usePopoverId;
7
+ var _useId = require("@atlaskit/ds-lib/use-id");
8
+ /**
9
+ * Returns a stable HTML `id` used to wire a trigger element to its popover
10
+ * via ARIA (`aria-controls`) and the Popover API (`popovertarget`).
11
+ *
12
+ * The returned value is intended for the `id` attribute on the popover and
13
+ * for the matching `aria-controls` / `popovertarget` references on the
14
+ * trigger. It is NOT a CSS `anchor-name` value: CSS anchor positioning is
15
+ * handled internally by `useAnchorPosition`, which mints and applies its
16
+ * own `anchor-name` on the trigger element.
17
+ */
18
+ function usePopoverId() {
19
+ // prefixing for debug clarity in the DOM
20
+ return "popover-".concat((0, _useId.useId)());
21
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getFirstFocusable = getFirstFocusable;
7
+ var _getFocusables = require("./get-focusables");
8
+ /**
9
+ * Returns the first focusable element within the container.
10
+ */
11
+ function getFirstFocusable(_ref) {
12
+ var container = _ref.container,
13
+ filter = _ref.filter;
14
+ var items = (0, _getFocusables.getFocusables)({
15
+ container: container,
16
+ filter: filter
17
+ });
18
+ return items.length > 0 ? items[0] : null;
19
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getFocusables = getFocusables;
7
+ var _isInSameLayer = require("./is-in-same-layer");
8
+ var _selectors = require("./selectors");
9
+ /**
10
+ * Returns all focusable HTMLElements within the container, optionally filtered.
11
+ *
12
+ * Focusables that belong to a nested top-layer scope (a `[popover]` or
13
+ * `<dialog>` descendant of the container) are excluded - those elements
14
+ * are owned by the inner layer's focus management. The container itself
15
+ * is allowed to be a popover/dialog; only nested ones are filtered.
16
+ */
17
+ function getFocusables(_ref) {
18
+ var container = _ref.container,
19
+ filter = _ref.filter;
20
+ return Array.from(container.querySelectorAll(_selectors.selectors.focusable)).filter(function (element) {
21
+ return element instanceof HTMLElement;
22
+ }).filter(function (element) {
23
+ return (0, _isInSameLayer.isInSameLayer)({
24
+ element: element,
25
+ container: container
26
+ });
27
+ }).filter(function (element) {
28
+ return !filter || filter(element, container);
29
+ });
30
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getLastFocusable = getLastFocusable;
7
+ var _getFocusables = require("./get-focusables");
8
+ /**
9
+ * Returns the last focusable element within the container.
10
+ */
11
+ function getLastFocusable(_ref) {
12
+ var container = _ref.container,
13
+ filter = _ref.filter;
14
+ var items = (0, _getFocusables.getFocusables)({
15
+ container: container,
16
+ filter: filter
17
+ });
18
+ return items.length > 0 ? items[items.length - 1] : null;
19
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getNextFocusable = getNextFocusable;
7
+ var _getFocusables = require("./get-focusables");
8
+ var _selectors = require("./selectors");
9
+ /**
10
+ * Returns the next focusable element in the given direction relative to the
11
+ * currently focused element within the container. Wraps around at both ends.
12
+ *
13
+ * Returns `null` if there is no focused element within the container or if
14
+ * the focused element is not in the list of focusable elements.
15
+ */
16
+
17
+ function getNextFocusable(_ref) {
18
+ var _all$nextIndex;
19
+ var container = _ref.container,
20
+ direction = _ref.direction,
21
+ filter = _ref.filter;
22
+ var all = (0, _getFocusables.getFocusables)({
23
+ container: container,
24
+ filter: filter
25
+ });
26
+ var current = container.querySelector(_selectors.selectors.focused);
27
+ if (!(current instanceof HTMLElement)) {
28
+ return null;
29
+ }
30
+ var index = all.indexOf(current);
31
+ if (index === -1) {
32
+ return null;
33
+ }
34
+ var nextIndex = function () {
35
+ if (direction === 'forwards') {
36
+ return (index + 1) % all.length;
37
+ }
38
+ var proposed = index - 1;
39
+ // if going into negative numbers, loop back to the last item
40
+ return proposed < 0 ? all.length - 1 : proposed;
41
+ }();
42
+ return (_all$nextIndex = all[nextIndex]) !== null && _all$nextIndex !== void 0 ? _all$nextIndex : null;
43
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isInSameLayer = isInSameLayer;
7
+ var topLayerSelector = '[popover], dialog, [role="dialog"], [role="alertdialog"]';
8
+
9
+ /**
10
+ * Returns true when `element` and `container` resolve to the same nearest
11
+ * top-layer host (or both resolve to `null`, meaning the document layer).
12
+ */
13
+ function isInSameLayer(_ref) {
14
+ var element = _ref.element,
15
+ container = _ref.container;
16
+ var elementLayer = element.closest(topLayerSelector);
17
+ var containerLayer = container.closest(topLayerSelector);
18
+ // Both elements are in the "document" layer
19
+ if (!elementLayer && !containerLayer) {
20
+ return true;
21
+ }
22
+ return elementLayer === containerLayer;
23
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isNestedLayerFocused = isNestedLayerFocused;
7
+ var _browserApis = require("@atlaskit/browser-apis");
8
+ var _isInSameLayer = require("./is-in-same-layer");
9
+ /**
10
+ * Returns `true` when `document.activeElement` is inside a nested top-layer
11
+ * descendant of `container` (a `[popover]`, `<dialog>`, `[role="dialog"]` or
12
+ * `[role="alertdialog"]` that is itself a descendant of `container`).
13
+ */
14
+ function isNestedLayerFocused(_ref) {
15
+ var _getDocument;
16
+ var container = _ref.container;
17
+ var focused = (_getDocument = (0, _browserApis.getDocument)()) === null || _getDocument === void 0 ? void 0 : _getDocument.activeElement;
18
+ if (!(focused instanceof HTMLElement)) {
19
+ return false;
20
+ }
21
+
22
+ // Cannot be in a nested layer if it is not in the container
23
+ if (!container.contains(focused)) {
24
+ return false;
25
+ }
26
+
27
+ // If not in the same layer, must be in a nested layer
28
+ return !(0, _isInSameLayer.isInSameLayer)({
29
+ element: focused,
30
+ container: container
31
+ });
32
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.selectors = void 0;
7
+ var selectors = exports.selectors = function () {
8
+ // Common exclusion filter applied to every selector.
9
+ var not = ':not([tabindex="-1"]):not([aria-disabled="true"]):not([aria-hidden="true"])';
10
+ var notDisabled = ":not([disabled])".concat(not);
11
+ var focusable = ["a[href]".concat(not), "area[href]".concat(not), "input".concat(notDisabled, ":not([type=\"hidden\"])"), "select".concat(notDisabled), "textarea".concat(notDisabled), "button".concat(notDisabled), "iframe".concat(not), "audio[controls]".concat(not), "video[controls]".concat(not), "[contenteditable]:not([contenteditable=\"false\"])".concat(not), "[tabindex]".concat(notDisabled).concat(not)];
12
+ return {
13
+ focusable: focusable.join(','),
14
+ // Build the `:focus` selector
15
+ focused: focusable.map(function (selector) {
16
+ return "".concat(selector, ":focus");
17
+ }).join(',')
18
+ };
19
+ }();
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getAriaForTrigger = getAriaForTrigger;
7
+ var _roleToAriaHasPopup = require("./role-to-aria-has-popup");
8
+ /**
9
+ * Roles accepted by `getAriaForTrigger`.
10
+ *
11
+ * Excludes tooltip-family roles (`tooltip`, `note`, `status`, `alert`, `log`)
12
+ * because the correct trigger wiring for those is `aria-describedby`, not
13
+ * `aria-haspopup` / `aria-expanded` / `aria-controls`. Use `aria-describedby`
14
+ * manually for tooltip triggers.
15
+ */
16
+
17
+ /**
18
+ * Non-undefined subset of `TAriaHasPopupValue`. Every role accepted by
19
+ * `getAriaForTrigger` maps to a concrete `aria-haspopup` string, so the
20
+ * trigger always receives a defined attribute value.
21
+ */
22
+
23
+ /**
24
+ * Returns the ARIA attributes to spread onto a click-activated popover trigger.
25
+ *
26
+ * Centralises three attributes that are easy to forget or get wrong individually:
27
+ *
28
+ * - `aria-haspopup` - derived from the popover's role (e.g. `dialog → "dialog"`,
29
+ * `menu → "menu"`, `tooltip → undefined`). React omits the attribute when
30
+ * the value is `undefined`.
31
+ * - `aria-expanded` - reflects the current open state.
32
+ * - `aria-controls` - references the popover element by its id, even
33
+ * while the popover is closed. The relationship is stable; `aria-expanded`
34
+ * carries the current visibility state.
35
+ *
36
+ * **This function is for click/keyboard-activated popovers only.** For
37
+ * hover-driven tooltips, the trigger should use `aria-describedby` instead.
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * import { getAriaForTrigger } from '@atlaskit/top-layer/get-aria-for-trigger';
42
+ * import { usePopoverId } from '@atlaskit/top-layer/use-popover-id';
43
+ *
44
+ * const popoverId = usePopoverId();
45
+ * const [isOpen, setIsOpen] = useState(false);
46
+ *
47
+ * return (
48
+ * <>
49
+ * <button
50
+ * ref={triggerRef}
51
+ * onClick={() => setIsOpen((previous) => !previous)}
52
+ * {...getAriaForTrigger({ role: 'dialog', isOpen, popoverId })}
53
+ * >
54
+ * Open
55
+ * </button>
56
+ * <Popover
57
+ * id={popoverId}
58
+ * role="dialog"
59
+ * label="My dialog"
60
+ * isOpen={isOpen}
61
+ * triggerRef={triggerRef}
62
+ * onClose={() => setIsOpen(false)}
63
+ * >
64
+ * …
65
+ * </Popover>
66
+ * </>
67
+ * );
68
+ * ```
69
+ */
70
+ function getAriaForTrigger(_ref) {
71
+ var role = _ref.role,
72
+ isOpen = _ref.isOpen,
73
+ popoverId = _ref.popoverId;
74
+ // `roleToAriaHasPopup` accepts a wider role union (including tooltip-family
75
+ // roles that map to `undefined`). `TAriaForTriggerRole` excludes those, so
76
+ // the returned value is guaranteed to be a defined string. The cast narrows
77
+ // the wider helper signature to match.
78
+ var ariaHasPopup = (0, _roleToAriaHasPopup.roleToAriaHasPopup)({
79
+ role: role
80
+ });
81
+ return {
82
+ 'aria-haspopup': ariaHasPopup,
83
+ 'aria-expanded': isOpen,
84
+ // Keep the trigger-to-popover relationship stable. `aria-expanded`
85
+ // tells assistive technology whether the controlled popover is visible.
86
+ 'aria-controls': popoverId
87
+ };
88
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.roleToAriaHasPopup = roleToAriaHasPopup;
7
+ /**
8
+ * Maps a popover content role to the correct `aria-haspopup` value
9
+ * for its trigger element.
10
+ *
11
+ * Returns `undefined` for roles that are not popups in the ARIA sense
12
+ * (`tooltip`, `note`, `status`, `alert`, `log`). Triggers for those roles
13
+ * should not announce a popup at all - emitting `aria-haspopup="dialog"`
14
+ * on a tooltip trigger would mislead assistive technology.
15
+ */
16
+ function roleToAriaHasPopup(_ref) {
17
+ var role = _ref.role;
18
+ if (role === 'menu') {
19
+ return 'menu';
20
+ }
21
+ if (role === 'listbox') {
22
+ return 'listbox';
23
+ }
24
+ if (role === 'tree') {
25
+ return 'tree';
26
+ }
27
+ if (role === 'grid') {
28
+ return 'grid';
29
+ }
30
+ if (role === 'dialog' || role === 'alertdialog') {
31
+ return 'dialog';
32
+ }
33
+ // Non-popup roles (tooltip, note, status, alert, log) and the
34
+ // no-role case: omit `aria-haspopup` entirely. React drops the
35
+ // attribute when the value is `undefined`.
36
+ return undefined;
37
+ }
@@ -3,7 +3,6 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.roleToAriaHasPopup = roleToAriaHasPopup;
7
6
  exports.shouldFocusIntoPopover = shouldFocusIntoPopover;
8
7
  /**
9
8
  * Valid values for the `aria-haspopup` attribute.
@@ -49,38 +48,6 @@ exports.shouldFocusIntoPopover = shouldFocusIntoPopover;
49
48
  * the role for cases where it is set externally or not needed.
50
49
  */
51
50
 
52
- /**
53
- * Maps a popover content role to the correct `aria-haspopup` value
54
- * for its trigger element.
55
- *
56
- * Returns `undefined` for roles that are not popups in the ARIA sense
57
- * (`tooltip`, `note`, `status`, `alert`, `log`). Triggers for those roles
58
- * should not announce a popup at all - emitting `aria-haspopup="dialog"`
59
- * on a tooltip trigger would mislead assistive technology.
60
- */
61
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
62
- function roleToAriaHasPopup(_ref) {
63
- var role = _ref.role;
64
- if (role === 'menu') {
65
- return 'menu';
66
- }
67
- if (role === 'listbox') {
68
- return 'listbox';
69
- }
70
- if (role === 'tree') {
71
- return 'tree';
72
- }
73
- if (role === 'grid') {
74
- return 'grid';
75
- }
76
- if (role === 'dialog' || role === 'alertdialog') {
77
- return 'dialog';
78
- }
79
- // Non-popup roles (tooltip, note, status, alert, log) and the
80
- // no-role case: omit `aria-haspopup` entirely. React drops the
81
- // attribute when the value is `undefined`.
82
- return undefined;
83
- }
84
51
  var rolesThatMoveFocus = new Set(['dialog', 'alertdialog', 'menu', 'listbox', 'tree', 'grid']);
85
52
 
86
53
  /**
@@ -88,8 +55,8 @@ var rolesThatMoveFocus = new Set(['dialog', 'alertdialog', 'menu', 'listbox', 't
88
55
  * on open, and `false` otherwise (including when `role` is `undefined`).
89
56
  */
90
57
  // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
91
- function shouldFocusIntoPopover(_ref2) {
92
- var role = _ref2.role;
58
+ function shouldFocusIntoPopover(_ref) {
59
+ var role = _ref.role;
93
60
  if (!role) {
94
61
  return false;
95
62
  }