@primer/components 29.1.0 → 29.1.1-rc.cea79543

Sign up to get free protection for your applications and to get access to all the features.
Files changed (753) hide show
  1. package/.changeset/README.md +8 -0
  2. package/.changeset/config.json +10 -0
  3. package/.devcontainer/devcontainer.json +8 -0
  4. package/.eslintrc.json +106 -0
  5. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  6. package/.github/ISSUE_TEMPLATE/new_component_proposal_template.md +41 -0
  7. package/.github/dependabot.yml +18 -0
  8. package/.github/pull_request_template.md +18 -0
  9. package/.github/workflows/ci.yml +31 -0
  10. package/.github/workflows/deploy_preview.yml +47 -0
  11. package/.github/workflows/deploy_production.yml +70 -0
  12. package/.github/workflows/release.yml +35 -0
  13. package/.github/workflows/release_canary.yml +70 -0
  14. package/.github/workflows/release_candidate.yml +60 -0
  15. package/.github/workflows/size.yml +13 -0
  16. package/.github/workflows/stale.yml +26 -0
  17. package/.gitignore +10 -0
  18. package/.npmrc +4 -0
  19. package/.nvmrc +1 -0
  20. package/.storybook/main.js +11 -0
  21. package/.storybook/preview.js +69 -0
  22. package/.vscode/launch.json +21 -0
  23. package/.vscode/settings.json +13 -0
  24. package/@types/@styled-system/index.d.ts +0 -0
  25. package/@types/@styled-system/prop-types/index.d.ts +1 -0
  26. package/@types/@styled-system/props/index.d.ts +1 -0
  27. package/@types/jest-styled-components/index.d.ts +1 -0
  28. package/CHANGELOG.md +6 -0
  29. package/CODEOWNERS +2 -0
  30. package/babel-defines.js +13 -0
  31. package/babel.config.js +39 -0
  32. package/contributor-docs/CODE_OF_CONDUCT.md +76 -0
  33. package/contributor-docs/CONTRIBUTING.md +274 -0
  34. package/contributor-docs/adrs/adr-001-typescript.md +23 -0
  35. package/contributor-docs/adrs/adr-002-behavior-isolation.md +106 -0
  36. package/contributor-docs/behaviors.md +132 -0
  37. package/contributor-docs/component-contents-api-patterns.md +315 -0
  38. package/contributor-docs/principles.md +39 -0
  39. package/docs/.eslintrc +0 -0
  40. package/docs/.gitignore +91 -0
  41. package/docs/components/PropsList.js +5 -0
  42. package/docs/components/State.js +9 -0
  43. package/docs/components/constants.js +34 -0
  44. package/docs/components/index.js +2 -0
  45. package/docs/content/ActionList.mdx +72 -0
  46. package/docs/content/ActionMenu.mdx +80 -0
  47. package/docs/content/AnchoredOverlay.mdx +37 -0
  48. package/docs/content/Avatar.mdx +33 -0
  49. package/docs/content/AvatarStack.mdx +43 -0
  50. package/docs/content/BorderBox.md +46 -0
  51. package/docs/content/Box.md +74 -0
  52. package/docs/content/BranchName.md +18 -0
  53. package/docs/content/Breadcrumbs.md +52 -0
  54. package/docs/content/Buttons.md +54 -0
  55. package/docs/content/CircleBadge.md +45 -0
  56. package/docs/content/CircleOcticon.md +18 -0
  57. package/docs/content/CounterLabel.md +30 -0
  58. package/docs/content/Details.md +105 -0
  59. package/docs/content/Dialog.md +108 -0
  60. package/docs/content/Dialog2.mdx +179 -0
  61. package/docs/content/Dropdown.md +72 -0
  62. package/docs/content/DropdownMenu.mdx +49 -0
  63. package/docs/content/FilterList.md +44 -0
  64. package/docs/content/FilteredSearch.md +39 -0
  65. package/docs/content/Flash.md +42 -0
  66. package/docs/content/Flex.md +58 -0
  67. package/docs/content/FormGroup.md +44 -0
  68. package/docs/content/Grid.md +59 -0
  69. package/docs/content/Header.md +79 -0
  70. package/docs/content/Heading.md +22 -0
  71. package/docs/content/Label.md +40 -0
  72. package/docs/content/LabelGroup.md +31 -0
  73. package/docs/content/Link.md +37 -0
  74. package/docs/content/Overlay.mdx +94 -0
  75. package/docs/content/Pagehead.md +27 -0
  76. package/docs/content/Pagination.md +187 -0
  77. package/docs/content/PointerBox.md +81 -0
  78. package/docs/content/Popover.md +137 -0
  79. package/docs/content/Portal.mdx +73 -0
  80. package/docs/content/Position.md +97 -0
  81. package/docs/content/ProgressBar.mdx +29 -0
  82. package/docs/content/SelectMenu.md +433 -0
  83. package/docs/content/SelectPanel.mdx +67 -0
  84. package/docs/content/SideNav.md +179 -0
  85. package/docs/content/Spinner.mdx +32 -0
  86. package/docs/content/StateLabel.md +33 -0
  87. package/docs/content/StyledOcticon.md +34 -0
  88. package/docs/content/SubNav.md +102 -0
  89. package/docs/content/TabNav.md +50 -0
  90. package/docs/content/Text.md +29 -0
  91. package/docs/content/TextInput.md +32 -0
  92. package/docs/content/Timeline.md +138 -0
  93. package/docs/content/Tooltip.md +41 -0
  94. package/docs/content/Truncate.md +65 -0
  95. package/docs/content/UnderlineNav.md +53 -0
  96. package/docs/content/anchoredPosition.mdx +163 -0
  97. package/docs/content/core-concepts.md +70 -0
  98. package/docs/content/focusTrap.mdx +103 -0
  99. package/docs/content/focusZone.mdx +145 -0
  100. package/docs/content/getting-started.md +134 -0
  101. package/docs/content/index.md +33 -0
  102. package/docs/content/linting.md +35 -0
  103. package/docs/content/overriding-styles.mdx +79 -0
  104. package/docs/content/philosophy.md +23 -0
  105. package/docs/content/primer-theme.md +89 -0
  106. package/docs/content/ssr.mdx +43 -0
  107. package/docs/content/system-props.mdx +37 -0
  108. package/docs/content/theme-reference.md +16 -0
  109. package/docs/content/theming.md +249 -0
  110. package/docs/content/useOnEscapePress.mdx +56 -0
  111. package/docs/content/useOnOutsideClick.mdx +57 -0
  112. package/docs/content/useOpenAndCloseFocus.mdx +49 -0
  113. package/docs/content/useOverlay.mdx +62 -0
  114. package/docs/content/useSafeTimeout.mdx +32 -0
  115. package/docs/gatsby-config.js +30 -0
  116. package/docs/gatsby-node.js +101 -0
  117. package/docs/package-lock.json +20979 -0
  118. package/docs/package.json +35 -0
  119. package/docs/src/@primer/gatsby-theme-doctocat/components/hero.js +21 -0
  120. package/docs/src/@primer/gatsby-theme-doctocat/components/live-code.js +84 -0
  121. package/docs/src/@primer/gatsby-theme-doctocat/components/live-preview-wrapper.js +39 -0
  122. package/docs/src/@primer/gatsby-theme-doctocat/components/nav-dropdown.js +48 -0
  123. package/docs/src/@primer/gatsby-theme-doctocat/components/wrap-page-element.js +25 -0
  124. package/docs/src/@primer/gatsby-theme-doctocat/live-code-scope.js +54 -0
  125. package/docs/src/@primer/gatsby-theme-doctocat/nav.yml +127 -0
  126. package/docs/src/@primer/gatsby-theme-doctocat/primer-components-hero.svg +1411 -0
  127. package/docs/src/props.js +77 -0
  128. package/jest.config.js +13 -0
  129. package/lib/Button/Button.d.ts +0 -1
  130. package/lib/Button/ButtonClose.d.ts +1 -2
  131. package/lib/Button/ButtonDanger.d.ts +0 -1
  132. package/lib/Button/ButtonInvisible.d.ts +0 -1
  133. package/lib/Button/ButtonOutline.d.ts +0 -1
  134. package/lib/Button/ButtonPrimary.d.ts +0 -1
  135. package/lib/CircleOcticon.d.ts +0 -1
  136. package/lib/Dialog.d.ts +2 -3
  137. package/lib/Dropdown.d.ts +0 -4
  138. package/lib/DropdownMenu/DropdownButton.d.ts +1 -2
  139. package/lib/FilterList.d.ts +0 -1
  140. package/lib/Position.d.ts +4 -4
  141. package/lib/SelectMenu/SelectMenu.d.ts +4 -10
  142. package/lib/SelectMenu/SelectMenuItem.d.ts +1 -1
  143. package/lib/SelectMenu/SelectMenuModal.d.ts +1 -1
  144. package/lib/Timeline.d.ts +0 -1
  145. package/lib/__tests__/ActionList.d.ts +1 -0
  146. package/lib/__tests__/ActionList.js +67 -0
  147. package/lib/__tests__/ActionMenu.d.ts +1 -0
  148. package/lib/__tests__/ActionMenu.js +154 -0
  149. package/lib/__tests__/AnchoredOverlay.d.ts +1 -0
  150. package/lib/__tests__/AnchoredOverlay.js +161 -0
  151. package/lib/__tests__/Avatar.d.ts +1 -0
  152. package/lib/__tests__/Avatar.js +70 -0
  153. package/lib/__tests__/AvatarStack.d.ts +1 -0
  154. package/lib/__tests__/AvatarStack.js +71 -0
  155. package/lib/__tests__/BorderBox.d.ts +1 -0
  156. package/lib/__tests__/BorderBox.js +61 -0
  157. package/lib/__tests__/Box.d.ts +1 -0
  158. package/lib/__tests__/Box.js +81 -0
  159. package/lib/__tests__/BranchName.d.ts +1 -0
  160. package/lib/__tests__/BranchName.js +39 -0
  161. package/lib/__tests__/Breadcrumb.d.ts +1 -0
  162. package/lib/__tests__/Breadcrumb.js +42 -0
  163. package/lib/__tests__/BreadcrumbItem.d.ts +1 -0
  164. package/lib/__tests__/BreadcrumbItem.js +52 -0
  165. package/lib/__tests__/Button.d.ts +1 -0
  166. package/lib/__tests__/Button.js +152 -0
  167. package/lib/__tests__/Caret.d.ts +1 -0
  168. package/lib/__tests__/Caret.js +52 -0
  169. package/lib/__tests__/CircleBadge.d.ts +1 -0
  170. package/lib/__tests__/CircleBadge.js +87 -0
  171. package/lib/__tests__/CircleOcticon.d.ts +1 -0
  172. package/lib/__tests__/CircleOcticon.js +74 -0
  173. package/lib/__tests__/CounterLabel.d.ts +1 -0
  174. package/lib/__tests__/CounterLabel.js +61 -0
  175. package/lib/__tests__/Details.d.ts +1 -0
  176. package/lib/__tests__/Details.js +120 -0
  177. package/lib/__tests__/Dialog.d.ts +1 -0
  178. package/lib/__tests__/Dialog.js +188 -0
  179. package/lib/__tests__/Dropdown.d.ts +1 -0
  180. package/lib/__tests__/Dropdown.js +70 -0
  181. package/lib/__tests__/DropdownMenu.d.ts +1 -0
  182. package/lib/__tests__/DropdownMenu.js +153 -0
  183. package/lib/__tests__/FilterList.d.ts +1 -0
  184. package/lib/__tests__/FilterList.js +39 -0
  185. package/lib/__tests__/FilterListItem.d.ts +1 -0
  186. package/lib/__tests__/FilterListItem.js +49 -0
  187. package/lib/__tests__/FilteredSearch.d.ts +1 -0
  188. package/lib/__tests__/FilteredSearch.js +39 -0
  189. package/lib/__tests__/Flash.d.ts +1 -0
  190. package/lib/__tests__/Flash.js +65 -0
  191. package/lib/__tests__/Flex.d.ts +1 -0
  192. package/lib/__tests__/Flex.js +77 -0
  193. package/lib/__tests__/FormGroup.d.ts +1 -0
  194. package/lib/__tests__/FormGroup.js +58 -0
  195. package/lib/__tests__/Grid.d.ts +1 -0
  196. package/lib/__tests__/Grid.js +107 -0
  197. package/lib/__tests__/Header.d.ts +1 -0
  198. package/lib/__tests__/Header.js +63 -0
  199. package/lib/__tests__/Heading.d.ts +1 -0
  200. package/lib/__tests__/Heading.js +112 -0
  201. package/lib/__tests__/Label.d.ts +1 -0
  202. package/lib/__tests__/Label.js +49 -0
  203. package/lib/__tests__/LabelGroup.d.ts +1 -0
  204. package/lib/__tests__/LabelGroup.js +41 -0
  205. package/lib/__tests__/Link.d.ts +1 -0
  206. package/lib/__tests__/Link.js +73 -0
  207. package/lib/__tests__/Overlay.d.ts +1 -0
  208. package/lib/__tests__/Overlay.js +145 -0
  209. package/lib/__tests__/Pagehead.d.ts +1 -0
  210. package/lib/__tests__/Pagehead.js +40 -0
  211. package/lib/__tests__/Pagination/Pagination.d.ts +1 -0
  212. package/lib/__tests__/Pagination/Pagination.js +50 -0
  213. package/lib/__tests__/Pagination/PaginationModel.d.ts +1 -0
  214. package/lib/__tests__/Pagination/PaginationModel.js +186 -0
  215. package/lib/__tests__/PointerBox.d.ts +1 -0
  216. package/lib/__tests__/PointerBox.js +49 -0
  217. package/lib/__tests__/Popover.d.ts +1 -0
  218. package/lib/__tests__/Popover.js +70 -0
  219. package/lib/__tests__/Portal.d.ts +1 -0
  220. package/lib/__tests__/Portal.js +124 -0
  221. package/lib/__tests__/Position.d.ts +1 -0
  222. package/lib/__tests__/Position.js +149 -0
  223. package/lib/__tests__/ProgressBar.d.ts +1 -0
  224. package/lib/__tests__/ProgressBar.js +71 -0
  225. package/lib/__tests__/SelectMenu.d.ts +1 -0
  226. package/lib/__tests__/SelectMenu.js +155 -0
  227. package/lib/__tests__/SelectPanel.d.ts +1 -0
  228. package/lib/__tests__/SelectPanel.js +83 -0
  229. package/lib/__tests__/SideNav.d.ts +1 -0
  230. package/lib/__tests__/SideNav.js +75 -0
  231. package/lib/__tests__/Spinner.d.ts +1 -0
  232. package/lib/__tests__/Spinner.js +56 -0
  233. package/lib/__tests__/StateLabel.d.ts +1 -0
  234. package/lib/__tests__/StateLabel.js +74 -0
  235. package/lib/__tests__/StyledOcticon.d.ts +1 -0
  236. package/lib/__tests__/StyledOcticon.js +43 -0
  237. package/lib/__tests__/SubNav.d.ts +1 -0
  238. package/lib/__tests__/SubNav.js +65 -0
  239. package/lib/__tests__/SubNavLink.d.ts +1 -0
  240. package/lib/__tests__/SubNavLink.js +52 -0
  241. package/lib/__tests__/TabNav.d.ts +1 -0
  242. package/lib/__tests__/TabNav.js +53 -0
  243. package/lib/__tests__/Text.d.ts +1 -0
  244. package/lib/__tests__/Text.js +108 -0
  245. package/lib/__tests__/TextInput.d.ts +1 -0
  246. package/lib/__tests__/TextInput.js +81 -0
  247. package/lib/__tests__/ThemeProvider.d.ts +1 -0
  248. package/lib/__tests__/ThemeProvider.js +444 -0
  249. package/lib/__tests__/Timeline.d.ts +1 -0
  250. package/lib/__tests__/Timeline.js +80 -0
  251. package/lib/__tests__/Tooltip.d.ts +1 -0
  252. package/lib/__tests__/Tooltip.js +72 -0
  253. package/lib/__tests__/Truncate.d.ts +1 -0
  254. package/lib/__tests__/Truncate.js +66 -0
  255. package/lib/__tests__/UnderlineNav.d.ts +1 -0
  256. package/lib/__tests__/UnderlineNav.js +75 -0
  257. package/lib/__tests__/UnderlineNavLink.d.ts +1 -0
  258. package/lib/__tests__/UnderlineNavLink.js +54 -0
  259. package/lib/__tests__/behaviors/anchoredPosition.d.ts +1 -0
  260. package/lib/__tests__/behaviors/anchoredPosition.js +390 -0
  261. package/lib/__tests__/behaviors/focusTrap.d.ts +1 -0
  262. package/lib/__tests__/behaviors/focusTrap.js +234 -0
  263. package/lib/__tests__/behaviors/focusZone.d.ts +1 -0
  264. package/lib/__tests__/behaviors/focusZone.js +570 -0
  265. package/lib/__tests__/behaviors/iterateFocusableElements.d.ts +1 -0
  266. package/lib/__tests__/behaviors/iterateFocusableElements.js +55 -0
  267. package/lib/__tests__/filterObject.d.ts +1 -0
  268. package/lib/__tests__/filterObject.js +30 -0
  269. package/lib/__tests__/hooks/useAnchoredPosition.d.ts +1 -0
  270. package/lib/__tests__/hooks/useAnchoredPosition.js +54 -0
  271. package/lib/__tests__/hooks/useOnEscapePress.d.ts +1 -0
  272. package/lib/__tests__/hooks/useOnEscapePress.js +32 -0
  273. package/lib/__tests__/hooks/useOnOutsideClick.d.ts +1 -0
  274. package/lib/__tests__/hooks/useOnOutsideClick.js +87 -0
  275. package/lib/__tests__/hooks/useOpenAndCloseFocus.d.ts +1 -0
  276. package/lib/__tests__/hooks/useOpenAndCloseFocus.js +60 -0
  277. package/lib/__tests__/hooks/useProvidedStateOrCreate.d.ts +1 -0
  278. package/lib/__tests__/hooks/useProvidedStateOrCreate.js +45 -0
  279. package/lib/__tests__/theme.d.ts +1 -0
  280. package/lib/__tests__/theme.js +36 -0
  281. package/lib/__tests__/themeGet.d.ts +1 -0
  282. package/lib/__tests__/themeGet.js +25 -0
  283. package/lib/__tests__/useSafeTimeout.d.ts +1 -0
  284. package/lib/__tests__/useSafeTimeout.js +45 -0
  285. package/lib/stories/ActionList.stories.js +382 -0
  286. package/lib/stories/ActionMenu.stories.js +338 -0
  287. package/lib/stories/AnchoredOverlay.stories.js +127 -0
  288. package/lib/stories/AvatarStack.stories.js +49 -0
  289. package/lib/stories/Button.stories.js +114 -0
  290. package/lib/stories/ConfirmationDialog.stories.js +111 -0
  291. package/lib/stories/Dialog.stories.js +265 -0
  292. package/lib/stories/DropdownMenu.stories.js +122 -0
  293. package/lib/stories/Overlay.stories.js +185 -0
  294. package/lib/stories/Portal.stories.js +104 -0
  295. package/lib/stories/SelectPanel.stories.js +342 -0
  296. package/lib/stories/ThemeProvider.stories.js +102 -0
  297. package/lib/stories/useAnchoredPosition.stories.js +351 -0
  298. package/lib/stories/useFocusTrap.stories.js +356 -0
  299. package/lib/stories/useFocusZone.stories.js +599 -0
  300. package/lib-esm/Button/Button.d.ts +0 -1
  301. package/lib-esm/Button/ButtonClose.d.ts +1 -2
  302. package/lib-esm/Button/ButtonDanger.d.ts +0 -1
  303. package/lib-esm/Button/ButtonInvisible.d.ts +0 -1
  304. package/lib-esm/Button/ButtonOutline.d.ts +0 -1
  305. package/lib-esm/Button/ButtonPrimary.d.ts +0 -1
  306. package/lib-esm/CircleOcticon.d.ts +0 -1
  307. package/lib-esm/Dialog.d.ts +2 -3
  308. package/lib-esm/Dropdown.d.ts +0 -4
  309. package/lib-esm/DropdownMenu/DropdownButton.d.ts +1 -2
  310. package/lib-esm/FilterList.d.ts +0 -1
  311. package/lib-esm/Position.d.ts +4 -4
  312. package/lib-esm/SelectMenu/SelectMenu.d.ts +4 -10
  313. package/lib-esm/SelectMenu/SelectMenuItem.d.ts +1 -1
  314. package/lib-esm/SelectMenu/SelectMenuModal.d.ts +1 -1
  315. package/lib-esm/Timeline.d.ts +0 -1
  316. package/lib-esm/__tests__/ActionList.d.ts +1 -0
  317. package/lib-esm/__tests__/ActionList.js +54 -0
  318. package/lib-esm/__tests__/ActionMenu.d.ts +1 -0
  319. package/lib-esm/__tests__/ActionMenu.js +141 -0
  320. package/lib-esm/__tests__/AnchoredOverlay.d.ts +1 -0
  321. package/lib-esm/__tests__/AnchoredOverlay.js +135 -0
  322. package/lib-esm/__tests__/Avatar.d.ts +1 -0
  323. package/lib-esm/__tests__/Avatar.js +58 -0
  324. package/lib-esm/__tests__/AvatarStack.d.ts +1 -0
  325. package/lib-esm/__tests__/AvatarStack.js +57 -0
  326. package/lib-esm/__tests__/BorderBox.d.ts +1 -0
  327. package/lib-esm/__tests__/BorderBox.js +49 -0
  328. package/lib-esm/__tests__/Box.d.ts +1 -0
  329. package/lib-esm/__tests__/Box.js +69 -0
  330. package/lib-esm/__tests__/BranchName.d.ts +1 -0
  331. package/lib-esm/__tests__/BranchName.js +28 -0
  332. package/lib-esm/__tests__/Breadcrumb.d.ts +1 -0
  333. package/lib-esm/__tests__/Breadcrumb.js +31 -0
  334. package/lib-esm/__tests__/BreadcrumbItem.d.ts +1 -0
  335. package/lib-esm/__tests__/BreadcrumbItem.js +41 -0
  336. package/lib-esm/__tests__/Button.d.ts +1 -0
  337. package/lib-esm/__tests__/Button.js +141 -0
  338. package/lib-esm/__tests__/Caret.d.ts +1 -0
  339. package/lib-esm/__tests__/Caret.js +42 -0
  340. package/lib-esm/__tests__/CircleBadge.d.ts +1 -0
  341. package/lib-esm/__tests__/CircleBadge.js +73 -0
  342. package/lib-esm/__tests__/CircleOcticon.d.ts +1 -0
  343. package/lib-esm/__tests__/CircleOcticon.js +61 -0
  344. package/lib-esm/__tests__/CounterLabel.d.ts +1 -0
  345. package/lib-esm/__tests__/CounterLabel.js +49 -0
  346. package/lib-esm/__tests__/Details.d.ts +1 -0
  347. package/lib-esm/__tests__/Details.js +109 -0
  348. package/lib-esm/__tests__/Dialog.d.ts +1 -0
  349. package/lib-esm/__tests__/Dialog.js +174 -0
  350. package/lib-esm/__tests__/Dropdown.d.ts +1 -0
  351. package/lib-esm/__tests__/Dropdown.js +59 -0
  352. package/lib-esm/__tests__/DropdownMenu.d.ts +1 -0
  353. package/lib-esm/__tests__/DropdownMenu.js +139 -0
  354. package/lib-esm/__tests__/FilterList.d.ts +1 -0
  355. package/lib-esm/__tests__/FilterList.js +28 -0
  356. package/lib-esm/__tests__/FilterListItem.d.ts +1 -0
  357. package/lib-esm/__tests__/FilterListItem.js +38 -0
  358. package/lib-esm/__tests__/FilteredSearch.d.ts +1 -0
  359. package/lib-esm/__tests__/FilteredSearch.js +28 -0
  360. package/lib-esm/__tests__/Flash.d.ts +1 -0
  361. package/lib-esm/__tests__/Flash.js +53 -0
  362. package/lib-esm/__tests__/Flex.d.ts +1 -0
  363. package/lib-esm/__tests__/Flex.js +66 -0
  364. package/lib-esm/__tests__/FormGroup.d.ts +1 -0
  365. package/lib-esm/__tests__/FormGroup.js +47 -0
  366. package/lib-esm/__tests__/Grid.d.ts +1 -0
  367. package/lib-esm/__tests__/Grid.js +96 -0
  368. package/lib-esm/__tests__/Header.d.ts +1 -0
  369. package/lib-esm/__tests__/Header.js +52 -0
  370. package/lib-esm/__tests__/Heading.d.ts +1 -0
  371. package/lib-esm/__tests__/Heading.js +101 -0
  372. package/lib-esm/__tests__/Label.d.ts +1 -0
  373. package/lib-esm/__tests__/Label.js +38 -0
  374. package/lib-esm/__tests__/LabelGroup.d.ts +1 -0
  375. package/lib-esm/__tests__/LabelGroup.js +28 -0
  376. package/lib-esm/__tests__/Link.d.ts +1 -0
  377. package/lib-esm/__tests__/Link.js +62 -0
  378. package/lib-esm/__tests__/Overlay.d.ts +1 -0
  379. package/lib-esm/__tests__/Overlay.js +123 -0
  380. package/lib-esm/__tests__/Pagehead.d.ts +1 -0
  381. package/lib-esm/__tests__/Pagehead.js +28 -0
  382. package/lib-esm/__tests__/Pagination/Pagination.d.ts +1 -0
  383. package/lib-esm/__tests__/Pagination/Pagination.js +37 -0
  384. package/lib-esm/__tests__/Pagination/PaginationModel.d.ts +1 -0
  385. package/lib-esm/__tests__/Pagination/PaginationModel.js +182 -0
  386. package/lib-esm/__tests__/PointerBox.d.ts +1 -0
  387. package/lib-esm/__tests__/PointerBox.js +38 -0
  388. package/lib-esm/__tests__/Popover.d.ts +1 -0
  389. package/lib-esm/__tests__/Popover.js +56 -0
  390. package/lib-esm/__tests__/Portal.d.ts +1 -0
  391. package/lib-esm/__tests__/Portal.js +104 -0
  392. package/lib-esm/__tests__/Position.d.ts +1 -0
  393. package/lib-esm/__tests__/Position.js +138 -0
  394. package/lib-esm/__tests__/ProgressBar.d.ts +1 -0
  395. package/lib-esm/__tests__/ProgressBar.js +60 -0
  396. package/lib-esm/__tests__/SelectMenu.d.ts +1 -0
  397. package/lib-esm/__tests__/SelectMenu.js +145 -0
  398. package/lib-esm/__tests__/SelectPanel.d.ts +1 -0
  399. package/lib-esm/__tests__/SelectPanel.js +67 -0
  400. package/lib-esm/__tests__/SideNav.d.ts +1 -0
  401. package/lib-esm/__tests__/SideNav.js +63 -0
  402. package/lib-esm/__tests__/Spinner.d.ts +1 -0
  403. package/lib-esm/__tests__/Spinner.js +45 -0
  404. package/lib-esm/__tests__/StateLabel.d.ts +1 -0
  405. package/lib-esm/__tests__/StateLabel.js +63 -0
  406. package/lib-esm/__tests__/StyledOcticon.d.ts +1 -0
  407. package/lib-esm/__tests__/StyledOcticon.js +31 -0
  408. package/lib-esm/__tests__/SubNav.d.ts +1 -0
  409. package/lib-esm/__tests__/SubNav.js +52 -0
  410. package/lib-esm/__tests__/SubNavLink.d.ts +1 -0
  411. package/lib-esm/__tests__/SubNavLink.js +41 -0
  412. package/lib-esm/__tests__/TabNav.d.ts +1 -0
  413. package/lib-esm/__tests__/TabNav.js +42 -0
  414. package/lib-esm/__tests__/Text.d.ts +1 -0
  415. package/lib-esm/__tests__/Text.js +95 -0
  416. package/lib-esm/__tests__/TextInput.d.ts +1 -0
  417. package/lib-esm/__tests__/TextInput.js +70 -0
  418. package/lib-esm/__tests__/ThemeProvider.d.ts +1 -0
  419. package/lib-esm/__tests__/ThemeProvider.js +408 -0
  420. package/lib-esm/__tests__/Timeline.d.ts +1 -0
  421. package/lib-esm/__tests__/Timeline.js +69 -0
  422. package/lib-esm/__tests__/Tooltip.d.ts +1 -0
  423. package/lib-esm/__tests__/Tooltip.js +61 -0
  424. package/lib-esm/__tests__/Truncate.d.ts +1 -0
  425. package/lib-esm/__tests__/Truncate.js +55 -0
  426. package/lib-esm/__tests__/UnderlineNav.d.ts +1 -0
  427. package/lib-esm/__tests__/UnderlineNav.js +62 -0
  428. package/lib-esm/__tests__/UnderlineNavLink.d.ts +1 -0
  429. package/lib-esm/__tests__/UnderlineNavLink.js +43 -0
  430. package/lib-esm/__tests__/behaviors/anchoredPosition.d.ts +1 -0
  431. package/lib-esm/__tests__/behaviors/anchoredPosition.js +388 -0
  432. package/lib-esm/__tests__/behaviors/focusTrap.d.ts +1 -0
  433. package/lib-esm/__tests__/behaviors/focusTrap.js +227 -0
  434. package/lib-esm/__tests__/behaviors/focusZone.d.ts +1 -0
  435. package/lib-esm/__tests__/behaviors/focusZone.js +487 -0
  436. package/lib-esm/__tests__/behaviors/iterateFocusableElements.d.ts +1 -0
  437. package/lib-esm/__tests__/behaviors/iterateFocusableElements.js +48 -0
  438. package/lib-esm/__tests__/filterObject.d.ts +1 -0
  439. package/lib-esm/__tests__/filterObject.js +27 -0
  440. package/lib-esm/__tests__/hooks/useAnchoredPosition.d.ts +1 -0
  441. package/lib-esm/__tests__/hooks/useAnchoredPosition.js +46 -0
  442. package/lib-esm/__tests__/hooks/useOnEscapePress.d.ts +1 -0
  443. package/lib-esm/__tests__/hooks/useOnEscapePress.js +23 -0
  444. package/lib-esm/__tests__/hooks/useOnOutsideClick.d.ts +1 -0
  445. package/lib-esm/__tests__/hooks/useOnOutsideClick.js +68 -0
  446. package/lib-esm/__tests__/hooks/useOpenAndCloseFocus.d.ts +1 -0
  447. package/lib-esm/__tests__/hooks/useOpenAndCloseFocus.js +52 -0
  448. package/lib-esm/__tests__/hooks/useProvidedStateOrCreate.d.ts +1 -0
  449. package/lib-esm/__tests__/hooks/useProvidedStateOrCreate.js +36 -0
  450. package/lib-esm/__tests__/theme.d.ts +1 -0
  451. package/lib-esm/__tests__/theme.js +33 -0
  452. package/lib-esm/__tests__/themeGet.d.ts +1 -0
  453. package/lib-esm/__tests__/themeGet.js +22 -0
  454. package/lib-esm/__tests__/useSafeTimeout.d.ts +1 -0
  455. package/lib-esm/__tests__/useSafeTimeout.js +39 -0
  456. package/lib-esm/stories/ActionList.stories.js +334 -0
  457. package/lib-esm/stories/ActionMenu.stories.js +293 -0
  458. package/lib-esm/stories/AnchoredOverlay.stories.js +101 -0
  459. package/lib-esm/stories/AvatarStack.stories.js +32 -0
  460. package/lib-esm/stories/Button.stories.js +78 -0
  461. package/lib-esm/stories/ConfirmationDialog.stories.js +86 -0
  462. package/lib-esm/stories/Dialog.stories.js +240 -0
  463. package/lib-esm/stories/DropdownMenu.stories.js +94 -0
  464. package/lib-esm/stories/Overlay.stories.js +154 -0
  465. package/lib-esm/stories/Portal.stories.js +68 -0
  466. package/lib-esm/stories/SelectPanel.stories.js +284 -0
  467. package/lib-esm/stories/ThemeProvider.stories.js +83 -0
  468. package/lib-esm/stories/useAnchoredPosition.stories.js +313 -0
  469. package/lib-esm/stories/useFocusTrap.stories.js +309 -0
  470. package/lib-esm/stories/useFocusZone.stories.js +554 -0
  471. package/migrating.md +250 -0
  472. package/now.json +17 -0
  473. package/package-lock.json +28661 -0
  474. package/package.json +2 -2
  475. package/rollup.config.js +36 -0
  476. package/script/build +19 -0
  477. package/script/setup +12 -0
  478. package/src/ActionList/Divider.tsx +25 -0
  479. package/src/ActionList/Group.tsx +45 -0
  480. package/src/ActionList/Header.tsx +74 -0
  481. package/src/ActionList/Item.tsx +460 -0
  482. package/src/ActionList/List.tsx +253 -0
  483. package/src/ActionList/index.ts +21 -0
  484. package/src/ActionMenu.tsx +106 -0
  485. package/src/AnchoredOverlay/AnchoredOverlay.tsx +180 -0
  486. package/src/AnchoredOverlay/index.ts +2 -0
  487. package/src/Avatar.tsx +46 -0
  488. package/src/AvatarPair.tsx +35 -0
  489. package/src/AvatarStack.tsx +161 -0
  490. package/src/BaseStyles.tsx +53 -0
  491. package/src/BorderBox.tsx +18 -0
  492. package/src/Box.tsx +54 -0
  493. package/src/BranchName.tsx +19 -0
  494. package/src/Breadcrumb.tsx +87 -0
  495. package/src/Button/Button.tsx +40 -0
  496. package/src/Button/ButtonBase.tsx +43 -0
  497. package/src/Button/ButtonClose.tsx +40 -0
  498. package/src/Button/ButtonDanger.tsx +43 -0
  499. package/src/Button/ButtonGroup.tsx +55 -0
  500. package/src/Button/ButtonInvisible.tsx +27 -0
  501. package/src/Button/ButtonOutline.tsx +43 -0
  502. package/src/Button/ButtonPrimary.tsx +41 -0
  503. package/src/Button/ButtonStyles.tsx +36 -0
  504. package/src/Button/ButtonTableList.tsx +58 -0
  505. package/src/Button/index.ts +16 -0
  506. package/src/Caret.tsx +133 -0
  507. package/src/CircleBadge.tsx +55 -0
  508. package/src/CircleOcticon.tsx +37 -0
  509. package/src/CounterLabel.tsx +52 -0
  510. package/src/Details.tsx +23 -0
  511. package/src/Dialog/ConfirmationDialog.tsx +184 -0
  512. package/src/Dialog/Dialog.tsx +419 -0
  513. package/src/Dialog.tsx +149 -0
  514. package/src/Dropdown.tsx +158 -0
  515. package/src/DropdownMenu/DropdownButton.tsx +15 -0
  516. package/src/DropdownMenu/DropdownMenu.tsx +115 -0
  517. package/src/DropdownMenu/index.ts +4 -0
  518. package/src/DropdownStyles.ts +128 -0
  519. package/src/FilterList.tsx +81 -0
  520. package/src/FilteredActionList/FilteredActionList.tsx +152 -0
  521. package/src/FilteredActionList/index.ts +2 -0
  522. package/src/FilteredSearch.tsx +28 -0
  523. package/src/Flash.tsx +77 -0
  524. package/src/Flex.tsx +15 -0
  525. package/src/FormGroup.tsx +27 -0
  526. package/src/Grid.tsx +15 -0
  527. package/src/Header.tsx +84 -0
  528. package/src/Heading.tsx +21 -0
  529. package/src/Label.tsx +75 -0
  530. package/src/LabelGroup.tsx +18 -0
  531. package/src/Link.tsx +46 -0
  532. package/src/Overlay.tsx +194 -0
  533. package/src/Pagehead.tsx +17 -0
  534. package/src/Pagination/Pagination.tsx +214 -0
  535. package/src/Pagination/index.ts +4 -0
  536. package/src/Pagination/model.tsx +187 -0
  537. package/src/PointerBox.tsx +31 -0
  538. package/src/Popover.tsx +236 -0
  539. package/src/Portal/Portal.tsx +96 -0
  540. package/src/Portal/index.ts +5 -0
  541. package/src/Position.tsx +63 -0
  542. package/src/ProgressBar.tsx +52 -0
  543. package/src/SelectMenu/SelectMenu.tsx +125 -0
  544. package/src/SelectMenu/SelectMenuContext.tsx +9 -0
  545. package/src/SelectMenu/SelectMenuDivider.tsx +25 -0
  546. package/src/SelectMenu/SelectMenuFilter.tsx +51 -0
  547. package/src/SelectMenu/SelectMenuFooter.tsx +28 -0
  548. package/src/SelectMenu/SelectMenuHeader.tsx +50 -0
  549. package/src/SelectMenu/SelectMenuItem.tsx +137 -0
  550. package/src/SelectMenu/SelectMenuList.tsx +42 -0
  551. package/src/SelectMenu/SelectMenuLoadingAnimation.tsx +24 -0
  552. package/src/SelectMenu/SelectMenuModal.tsx +121 -0
  553. package/src/SelectMenu/SelectMenuTab.tsx +88 -0
  554. package/src/SelectMenu/SelectMenuTabPanel.tsx +30 -0
  555. package/src/SelectMenu/SelectMenuTabs.tsx +44 -0
  556. package/src/SelectMenu/hooks/useKeyboardNav.js +90 -0
  557. package/src/SelectMenu/index.ts +15 -0
  558. package/src/SelectPanel/SelectPanel.tsx +173 -0
  559. package/src/SelectPanel/index.ts +2 -0
  560. package/src/SideNav.tsx +193 -0
  561. package/src/Spinner.tsx +59 -0
  562. package/src/StateLabel.tsx +110 -0
  563. package/src/StyledOcticon.tsx +24 -0
  564. package/src/SubNav.tsx +129 -0
  565. package/src/TabNav.tsx +77 -0
  566. package/src/Text.tsx +13 -0
  567. package/src/TextInput.tsx +183 -0
  568. package/src/ThemeProvider.tsx +176 -0
  569. package/src/Timeline.tsx +141 -0
  570. package/src/Tooltip.tsx +263 -0
  571. package/src/Truncate.tsx +36 -0
  572. package/src/UnderlineNav.tsx +110 -0
  573. package/src/__tests__/.eslintrc.json +11 -0
  574. package/src/__tests__/ActionList.tsx +49 -0
  575. package/src/__tests__/ActionMenu.tsx +138 -0
  576. package/src/__tests__/AnchoredOverlay.tsx +151 -0
  577. package/src/__tests__/Avatar.tsx +45 -0
  578. package/src/__tests__/AvatarStack.tsx +45 -0
  579. package/src/__tests__/BorderBox.tsx +44 -0
  580. package/src/__tests__/Box.tsx +43 -0
  581. package/src/__tests__/BranchName.tsx +27 -0
  582. package/src/__tests__/Breadcrumb.tsx +31 -0
  583. package/src/__tests__/BreadcrumbItem.tsx +32 -0
  584. package/src/__tests__/Button.tsx +129 -0
  585. package/src/__tests__/Caret.tsx +36 -0
  586. package/src/__tests__/CircleBadge.tsx +69 -0
  587. package/src/__tests__/CircleOcticon.tsx +52 -0
  588. package/src/__tests__/CounterLabel.tsx +51 -0
  589. package/src/__tests__/Details.tsx +116 -0
  590. package/src/__tests__/Dialog.tsx +157 -0
  591. package/src/__tests__/Dropdown.tsx +57 -0
  592. package/src/__tests__/DropdownMenu.tsx +138 -0
  593. package/src/__tests__/FilterList.tsx +27 -0
  594. package/src/__tests__/FilterListItem.tsx +32 -0
  595. package/src/__tests__/FilteredSearch.tsx +27 -0
  596. package/src/__tests__/Flash.tsx +46 -0
  597. package/src/__tests__/Flex.tsx +59 -0
  598. package/src/__tests__/FormGroup.tsx +39 -0
  599. package/src/__tests__/Grid.tsx +83 -0
  600. package/src/__tests__/Header.tsx +50 -0
  601. package/src/__tests__/Heading.tsx +92 -0
  602. package/src/__tests__/Label.tsx +35 -0
  603. package/src/__tests__/LabelGroup.tsx +31 -0
  604. package/src/__tests__/Link.tsx +48 -0
  605. package/src/__tests__/Overlay.tsx +103 -0
  606. package/src/__tests__/Pagehead.tsx +24 -0
  607. package/src/__tests__/Pagination/Pagination.tsx +31 -0
  608. package/src/__tests__/Pagination/PaginationModel.tsx +133 -0
  609. package/src/__tests__/Pagination/__snapshots__/Pagination.tsx.snap +184 -0
  610. package/src/__tests__/PointerBox.tsx +35 -0
  611. package/src/__tests__/Popover.tsx +69 -0
  612. package/src/__tests__/Portal.tsx +103 -0
  613. package/src/__tests__/Position.tsx +118 -0
  614. package/src/__tests__/ProgressBar.tsx +41 -0
  615. package/src/__tests__/SelectMenu.tsx +142 -0
  616. package/src/__tests__/SelectPanel.tsx +65 -0
  617. package/src/__tests__/SideNav.tsx +63 -0
  618. package/src/__tests__/Spinner.tsx +44 -0
  619. package/src/__tests__/StateLabel.tsx +50 -0
  620. package/src/__tests__/StyledOcticon.tsx +28 -0
  621. package/src/__tests__/SubNav.tsx +51 -0
  622. package/src/__tests__/SubNavLink.tsx +32 -0
  623. package/src/__tests__/TabNav.tsx +33 -0
  624. package/src/__tests__/Text.tsx +79 -0
  625. package/src/__tests__/TextInput.tsx +50 -0
  626. package/src/__tests__/ThemeProvider.tsx +441 -0
  627. package/src/__tests__/Timeline.tsx +59 -0
  628. package/src/__tests__/Tooltip.tsx +53 -0
  629. package/src/__tests__/Truncate.tsx +45 -0
  630. package/src/__tests__/UnderlineNav.tsx +59 -0
  631. package/src/__tests__/UnderlineNavLink.tsx +32 -0
  632. package/src/__tests__/__snapshots__/ActionList.tsx.snap +27 -0
  633. package/src/__tests__/__snapshots__/ActionMenu.tsx.snap +80 -0
  634. package/src/__tests__/__snapshots__/AnchoredOverlay.tsx.snap +332 -0
  635. package/src/__tests__/__snapshots__/Avatar.tsx.snap +19 -0
  636. package/src/__tests__/__snapshots__/AvatarStack.tsx.snap +377 -0
  637. package/src/__tests__/__snapshots__/BorderBox.tsx.snap +14 -0
  638. package/src/__tests__/__snapshots__/Box.tsx.snap +201 -0
  639. package/src/__tests__/__snapshots__/BranchName.tsx.snap +17 -0
  640. package/src/__tests__/__snapshots__/Breadcrumb.tsx.snap +29 -0
  641. package/src/__tests__/__snapshots__/BreadcrumbItem.tsx.snap +79 -0
  642. package/src/__tests__/__snapshots__/Button.tsx.snap +832 -0
  643. package/src/__tests__/__snapshots__/Caret.tsx.snap +373 -0
  644. package/src/__tests__/__snapshots__/CircleBadge.tsx.snap +141 -0
  645. package/src/__tests__/__snapshots__/CircleOcticon.tsx.snap +64 -0
  646. package/src/__tests__/__snapshots__/CounterLabel.tsx.snap +22 -0
  647. package/src/__tests__/__snapshots__/Details.tsx.snap +15 -0
  648. package/src/__tests__/__snapshots__/Dialog.tsx.snap +200 -0
  649. package/src/__tests__/__snapshots__/Dropdown.tsx.snap +249 -0
  650. package/src/__tests__/__snapshots__/DropdownMenu.tsx.snap +106 -0
  651. package/src/__tests__/__snapshots__/FilterList.tsx.snap +13 -0
  652. package/src/__tests__/__snapshots__/FilterListItem.tsx.snap +80 -0
  653. package/src/__tests__/__snapshots__/FilteredSearch.tsx.snap +32 -0
  654. package/src/__tests__/__snapshots__/Flash.tsx.snap +32 -0
  655. package/src/__tests__/__snapshots__/Flex.tsx.snap +130 -0
  656. package/src/__tests__/__snapshots__/FormGroup.tsx.snap +25 -0
  657. package/src/__tests__/__snapshots__/Grid.tsx.snap +178 -0
  658. package/src/__tests__/__snapshots__/Header.tsx.snap +79 -0
  659. package/src/__tests__/__snapshots__/Heading.tsx.snap +13 -0
  660. package/src/__tests__/__snapshots__/Label.tsx.snap +74 -0
  661. package/src/__tests__/__snapshots__/LabelGroup.tsx.snap +15 -0
  662. package/src/__tests__/__snapshots__/Link.tsx.snap +213 -0
  663. package/src/__tests__/__snapshots__/Pagehead.tsx.snap +15 -0
  664. package/src/__tests__/__snapshots__/PointerBox.tsx.snap +174 -0
  665. package/src/__tests__/__snapshots__/Popover.tsx.snap +4687 -0
  666. package/src/__tests__/__snapshots__/Position.tsx.snap +44 -0
  667. package/src/__tests__/__snapshots__/ProgressBar.tsx.snap +53 -0
  668. package/src/__tests__/__snapshots__/SelectMenu.tsx.snap +469 -0
  669. package/src/__tests__/__snapshots__/SelectPanel.tsx.snap +123 -0
  670. package/src/__tests__/__snapshots__/SideNav.tsx.snap +143 -0
  671. package/src/__tests__/__snapshots__/Spinner.tsx.snap +33 -0
  672. package/src/__tests__/__snapshots__/StateLabel.tsx.snap +409 -0
  673. package/src/__tests__/__snapshots__/StyledOcticon.tsx.snap +25 -0
  674. package/src/__tests__/__snapshots__/SubNav.tsx.snap +44 -0
  675. package/src/__tests__/__snapshots__/SubNavLink.tsx.snap +199 -0
  676. package/src/__tests__/__snapshots__/TabNav.tsx.snap +58 -0
  677. package/src/__tests__/__snapshots__/Text.tsx.snap +7 -0
  678. package/src/__tests__/__snapshots__/TextInput.tsx.snap +440 -0
  679. package/src/__tests__/__snapshots__/ThemeProvider.tsx.snap +15 -0
  680. package/src/__tests__/__snapshots__/Timeline.tsx.snap +159 -0
  681. package/src/__tests__/__snapshots__/Tooltip.tsx.snap +227 -0
  682. package/src/__tests__/__snapshots__/Truncate.tsx.snap +17 -0
  683. package/src/__tests__/__snapshots__/UnderlineNav.tsx.snap +59 -0
  684. package/src/__tests__/__snapshots__/UnderlineNavLink.tsx.snap +130 -0
  685. package/src/__tests__/behaviors/anchoredPosition.ts +295 -0
  686. package/src/__tests__/behaviors/focusTrap.tsx +236 -0
  687. package/src/__tests__/behaviors/focusZone.tsx +549 -0
  688. package/src/__tests__/behaviors/iterateFocusableElements.tsx +61 -0
  689. package/src/__tests__/filterObject.ts +54 -0
  690. package/src/__tests__/hooks/useAnchoredPosition.tsx +31 -0
  691. package/src/__tests__/hooks/useOnEscapePress.tsx +16 -0
  692. package/src/__tests__/hooks/useOnOutsideClick.tsx +48 -0
  693. package/src/__tests__/hooks/useOpenAndCloseFocus.tsx +48 -0
  694. package/src/__tests__/hooks/useProvidedStateOrCreate.tsx +39 -0
  695. package/src/__tests__/theme.ts +41 -0
  696. package/src/__tests__/themeGet.ts +15 -0
  697. package/src/__tests__/useSafeTimeout.tsx +36 -0
  698. package/src/behaviors/anchoredPosition.ts +442 -0
  699. package/src/behaviors/focusTrap.ts +184 -0
  700. package/src/behaviors/focusZone.ts +713 -0
  701. package/src/constants.ts +62 -0
  702. package/src/hooks/index.ts +11 -0
  703. package/src/hooks/useAnchoredPosition.ts +53 -0
  704. package/src/hooks/useCombinedRefs.ts +40 -0
  705. package/src/hooks/useDetails.tsx +54 -0
  706. package/src/hooks/useDialog.ts +121 -0
  707. package/src/hooks/useFocusTrap.ts +80 -0
  708. package/src/hooks/useFocusZone.ts +64 -0
  709. package/src/hooks/useOnEscapePress.ts +63 -0
  710. package/src/hooks/useOnOutsideClick.tsx +82 -0
  711. package/src/hooks/useOpenAndCloseFocus.ts +27 -0
  712. package/src/hooks/useOverlay.tsx +32 -0
  713. package/src/hooks/useProvidedRefOrCreate.ts +14 -0
  714. package/src/hooks/useProvidedStateOrCreate.ts +27 -0
  715. package/src/hooks/useRenderForcingRef.ts +22 -0
  716. package/src/hooks/useResizeObserver.ts +11 -0
  717. package/src/hooks/useSafeTimeout.ts +38 -0
  718. package/src/hooks/useScrollFlash.ts +21 -0
  719. package/src/index.ts +165 -0
  720. package/src/polyfills/eventListenerSignal.ts +66 -0
  721. package/src/stories/ActionList.stories.tsx +364 -0
  722. package/src/stories/ActionMenu.stories.tsx +322 -0
  723. package/src/stories/AnchoredOverlay.stories.tsx +117 -0
  724. package/src/stories/AvatarStack.stories.tsx +37 -0
  725. package/src/stories/Button.stories.tsx +88 -0
  726. package/src/stories/ConfirmationDialog.stories.tsx +105 -0
  727. package/src/stories/Dialog.stories.tsx +240 -0
  728. package/src/stories/DropdownMenu.stories.tsx +84 -0
  729. package/src/stories/Overlay.stories.tsx +186 -0
  730. package/src/stories/Portal.stories.tsx +109 -0
  731. package/src/stories/SelectPanel.stories.tsx +300 -0
  732. package/src/stories/ThemeProvider.stories.tsx +104 -0
  733. package/src/stories/useAnchoredPosition.stories.tsx +320 -0
  734. package/src/stories/useFocusTrap.stories.tsx +400 -0
  735. package/src/stories/useFocusZone.stories.tsx +663 -0
  736. package/src/sx.ts +9 -0
  737. package/src/theme-preval.js +136 -0
  738. package/src/theme.ts +3 -0
  739. package/src/utils/deprecate.tsx +73 -0
  740. package/src/utils/isNumeric.tsx +4 -0
  741. package/src/utils/iterateFocusableElements.ts +121 -0
  742. package/src/utils/ssr.tsx +1 -0
  743. package/src/utils/test-deprecations.tsx +19 -0
  744. package/src/utils/test-helpers.tsx +7 -0
  745. package/src/utils/test-matchers.tsx +109 -0
  746. package/src/utils/testing.tsx +243 -0
  747. package/src/utils/theme.js +64 -0
  748. package/src/utils/types.ts +90 -0
  749. package/src/utils/uniqueId.ts +6 -0
  750. package/src/utils/userAgent.ts +7 -0
  751. package/stats.html +3279 -0
  752. package/tsconfig.build.json +7 -0
  753. package/tsconfig.json +20 -0
@@ -0,0 +1,163 @@
1
+ ---
2
+ title: Anchored Position Behavior
3
+ ---
4
+
5
+ The `getAnchoredPosition` behavior and `useAnchoredPosition` hook are used to calculate the position of a "floating" element that is anchored to another DOM element. This is useful for implementing overlay UI, such as dialogs, popovers, tooltips, toasts, and dropdown-style menus.
6
+
7
+ At a high level, the `getAnchoredPosition` algorithm will attempt to find the most suitable position for the floating element based on the passed-in settings, its containing element, and the size and position of the anchor element. Specifically, the calculated position should try to ensure that the floating element, when positioned at the calculated coordinates, does not overflow or underflow the container's bounding box.
8
+
9
+ Settings for this behavior allow the user to customize several aspects of this calculation. See **PositionSettings** below for a detailed description of these settings.
10
+
11
+ ### Positioning algorithm
12
+
13
+ When calculating the position of the floating element, the algorithm relies on different measurements from three separate elements:
14
+
15
+ 1. The floating element's width and height
16
+ 2. The anchor element's x/y position and its width and height
17
+ 3. The floating element's clipping container (for x/y position, width and height, and border sizes)
18
+
19
+ The public API only asks for the first two elements; the floating element's container is discovered via DOM traversal.
20
+
21
+ #### Finding the floating element's clipping container
22
+
23
+ The returned anchored position calculation is relative to the floating element's closest [_positioned_](https://developer.mozilla.org/en-US/docs/Web/CSS/position#types_of_positioning) ancestor. To find this ancestor, we try to check parents of the floating element until we find one that has a position set to anything other than `static` and use that element's bounding box as the container. If we can't find such an element, we will try to use `document.body`.
24
+
25
+ Once we have found the appropriate relative ancestor, we attempt to find the floating element's _clipping container_. The clipping container is an element that: 1) has `overflow` set to something other than `visible`, and 2) is either an ancestor of the relative ancestor, or is itself the relative ancestor. Again, if we cannot locate such an element, we will use `document.body` as the clipping container.
26
+
27
+ Once we have the clipping container, its bounding box is used as the viewport for the position calculation (see the next section). If the clipping container ends up being `document.body`, we take one additional step, allowing the clipping rectangle to be at least as tall as the window. This is done because the `body` element doesn't take up the full window size by default, but we still want to allow the entire space to be used as the viewport for the position calculation. It may be a good idea to ensure that this clipping container element _also_ contains the anchor element and is scrollable. This will ensure that if scrolled, the anchor and floating element will move together.
28
+
29
+ #### Positioning and overflow
30
+
31
+ With the positions and sizes of the above DOM elements, the algorithm calculates the (x, y) coordinate for the floating element. Then, it checks to see if, based on the floating element's size, if it would overflow the bounds of the container. If it would, it does one of two things:
32
+
33
+ A) If the overflow happens in the same direction as the anchor side (e.g. side is `'outside-bottom'` and the overflowing portion of the floating element is the bottom), try to find a different side, recalculate the position, and check for overflow again. If we check all four sides and don't find one that fits, revert to the bottom side, in hopes that a scrollbar might appear.
34
+ B) Otherwise, adjust the alignment offset so that the floating element can stay inside the container's bounds.
35
+
36
+ For a more in-depth explanation of the positioning settings, see `PositionSettings` below.
37
+
38
+ ### Demo
39
+
40
+ Deploy Storybook to see a live demo of `anchoredPosition`.
41
+
42
+ ### Usage
43
+
44
+ ```ts
45
+ const settings = {
46
+ side: 'outside-right',
47
+ align: 'center',
48
+ alignmentOffset: 10,
49
+ anchorOffset: -10
50
+ } as Partial<PositionSettings>
51
+ const float = document.getElementById('floatingElement')
52
+ const anchor = document.getElementById('anchorElement')
53
+ const {top, left} = getAnchoredPosition(float, anchor, settings)
54
+ float.style.top = `${top}px`
55
+ float.style.left = `${left}px`
56
+ ```
57
+
58
+ ### API
59
+
60
+ The `getAnchoredPosition` function takes the following arguments.
61
+
62
+ | Name | Type | Default | Description |
63
+ | :-------------- | :----------------- | :-----: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
64
+ | floatingElement | `Element` | | This is an Element that is currently rendered on the page. `getAnchoredPosition` needs to be able to measure this element's `width` and `height`. |
65
+ | anchorElement | `Element` | | This is an Element that the floating element will be "anchored" to. In other words, the calculated position of the floating element will be based on this element's position and size. |
66
+ | settings | `PositionSettings` | `{}` | Settings to customize the positioning algorithm. See below for a description of each setting. |
67
+
68
+ #### PositionSettings interface
69
+
70
+ `PositionSettings` is an object with the following interface
71
+
72
+ | Name | Type | Default | Description |
73
+ | :--------------- | :---------------- | :----------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
74
+ | side | `AnchorSide` | `"outside-bottom"` | Sets the side of the anchor element that the floating element should be pinned to. This side is given by a string starting with either `inside` or `outside`, followed by a hyphen, followed by either `top`, `right`, `bottom`, or `left`. Additionally, `"inside-center"` is an allowed value.<br /><br />The first part of this string, `inside` or `outside`, determines whether the floating element should be attempted to be placed "inside" the anchor element or "outside" of it. Using `inside` is useful for making it appear that the anchor _contains_ the floating element, and it can be used for implementing a dialog that is centered on the screen. The `outside` value is more common and can be used for tooltips, popovers, menus, etc.<br /><br />The second part of this string determines the _edge_ on the anchor element that the floating element will be anchored to. If side is `"inside-center"`, then the floating element will be centered in the X-direction (while `align` is used to position it in the Y-direction). |
75
+ | align | `AnchorAlignment` | `"start"` | Determines how the floating element should align with the anchor element. If set to `"start"`, the floating element's first edge (top or left) will align with the anchor element's first edge. If set to `"center"`, the floating element will be centered along the axis of the anchor edge. If set to `"end"`, the floating element's last edge will align with the anchor element's last edge. |
76
+ | anchorOffset | `number` | `4`\* | The number of pixels between the anchor edge and the floating element. Positive values move the floating element farther from the anchor element (for outside positioning) or further inside the anchor element (for inside positioning). Negative values have the opposite effect. |
77
+ | alignmentOffset | `number` | `4`\*\* | An additional offset, in pixels, to move the floating element from the aligning edge. Positive values move the floating element in the direction of center-alignment. Negative values move the floating element away from center-alignment. When align is `"center"`, positive offsets move the floating element right (top or bottom anchor side) or down (left or right anchor side). |
78
+ | allowOutOfBounds | `boolean` | `false` | If false, when the above settings result in rendering the floating element wholly or partially off-screen, attempt to adjust the settings to prevent this. Only applies to `outside` positioning.<br /><br />First, attempt to flip to the opposite edge of the anchor if the floating element is getting clipped in that direction. If flipping results in a similar clipping, try moving to the adjacent sides.<br /><br />Once we find a side that does not clip the overlay in its own dimension, check the rest of the sides to see if we need to adjust the alignment offset to fit in other dimensions.<br /><br />If we try all four sides and get clipped each time, settle for overflowing and use the `bottom` side, since the ability to scroll is most likely in this direction. |
79
+
80
+ \* If `side` is set to `"inside-center"`, this defaults to `0` instead of `4`.
81
+
82
+ \*\* If using outside positioning, or if `align` is set to `"center"`, this defaults to `0` instead of `4`.
83
+
84
+ #### AnchorSide
85
+
86
+ `AnchorSide` can be any of the following strings:
87
+
88
+ `'inside-top'`, `'inside-bottom'`, `'inside-left'`, `'inside-right'`, `'inside-center'`, `'outside-top'`, `'outside-bottom'`, `'outside-left'`, `'outside-right'`
89
+
90
+ #### AnchorAlignment
91
+
92
+ `AnchorAlignment` can be any of the following strings:
93
+
94
+ `'start'`, `'center'`, `'end'`
95
+
96
+ ### Best practices
97
+
98
+ As discussed above, the positioning algorithm needs to first measure the size of three different elements. Therefore, all three of these elements (anchor element, floating element, and the floating element's closest positioned container) must be rendered at the time `getAnchoredPosition` is called. To avoid a frame where the floating element is rendered at the `(0, 0)` position, give it a style of `visibility: hidden` until its position is returned at set. This allows the element to be measured without showing up on the page.
99
+
100
+ ### A note on performance
101
+
102
+ Every time `getAnchoredPosition` is called, it causes a [reflow](https://developers.google.com/speed/docs/insights/browser-reflow) because it needs to query the rendering engine for the positions of 3 elements: the anchor element, the floating element, and the closest ancestor of the floating element that is [_positioned_](https://developer.mozilla.org/en-US/docs/Web/CSS/position#types_of_positioning). Therefore, this function should not be called until it is needed (e.g. an overlay-style menu is invoked and displayed).
103
+
104
+ ## useAnchoredPosition hook
105
+
106
+ The `useAnchoredPosition` hook is used to provide anchored positioning data for React components. The hook returns refs that must be added to the anchor and floating elements, and a `position` object containing `top` and `left`. This position is tracked as state, so the component will re-render whenever it changes. It is the responsibility of the consumer to apply the top and left styles to the floating element in question.
107
+
108
+ ### Using your own refs
109
+
110
+ The `useAnchoredPosition` hook will return two refs for the anchor element and the floating element, which must be added to their respective JSX. If you would like to use your own refs, you can pass them into the hook as part of the settings object (see the interface below).
111
+
112
+ ### Recalculating position
113
+
114
+ Like other hooks such as `useCallback` and `useEffect`, this hook takes a dependencies array. If defined, the position will only be recalculated when one of the dependencies in this array changes. Otherwise, the position will be calculated when the component is first mounted, but never again.
115
+
116
+ ### Usage
117
+
118
+ ```jsx
119
+ export const AnchoredPositionExample = () => {
120
+ const {floatingElementRef, anchorElementRef, position} = useAnchoredPosition({side: 'outside-bottom', align: 'center'})
121
+ return (
122
+ <div>
123
+ <Box
124
+ position="absolute"
125
+ top={position?.top ?? 0}
126
+ left={position?.left ?? 0}
127
+ width={150}
128
+ height={150}
129
+ ref={floatingElementRef as React.RefObject<HTMLDivElement>}
130
+ >
131
+ Floating element
132
+ </Box>
133
+ <Box borderWidth='1px' borderStyle='solid' borderColor='border.primary' borderRadius={2} width={400} height={75} ref={anchorElementRef as React.RefObject<HTMLDivElement>}>
134
+ Anchor Element
135
+ </Box>
136
+ </div>
137
+ )
138
+ }
139
+ ```
140
+
141
+ ### useAnchoredPosition hook
142
+
143
+ | Name | Type | Default | Description |
144
+ | :----------- | :----------------------------- | :-------: | :------------------------------------------------------------------------------------------------------------------- |
145
+ | settings | `AnchoredPositionHookSettings` | undefined | Optional settings to control how the anchored position is calculated. See below. |
146
+ | dependencies | `React.DependencyList` | undefined | Dependencies to determine when to re-calculate the position. If undefined or `[]`, only calculate the position once. |
147
+
148
+ **Return value**
149
+
150
+ | Name | Type | Description |
151
+ | :----------------- | :---------------------------- | :------------------------------------------------- |
152
+ | floatingElementRef | `React.RefObject<Element>` | This ref must be added to the floating element JSX |
153
+ | anchorElementRef | `React.RefObject<Element>` | This ref must be added to the anchor element JSX |
154
+ | position | `{top: number, left: number}` | The calculated position |
155
+
156
+ ### AnchoredPositionHookSettings interface
157
+
158
+ `AnchoredPositionHookSettings` is an object with an interface that extends `PositionSettings` (see above). Additionally, it adds the following properties:
159
+
160
+ | Name | Type | Default | Description |
161
+ | :----------------- | :----------------------------- | :---------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
162
+ | floatingElementRef | `React.RefObject<HTMLElement>` | `undefined` | If provided, this will be the ref used to access the element that will be used for the floating element. Its size measurements are needed by the underlying `useAnchoredPosition` behavior. Otherwise, this hook will create the ref for you and return it. In both cases, the ref must be provided to the floating element's JSX. |
163
+ | anchorElementRef | `React.RefObject<HTMLElement>` | `undefined` | If provided, this will be the ref used to access the element that will be used for the anchor element. Its position and size measurements are needed by the underlying `useAnchoredPosition` behavior. Otherwise, this hook will create the ref for you and return it. In both cases, the ref must be provided to the anchor element's JSX. |
@@ -0,0 +1,70 @@
1
+ ---
2
+ title: Core Concepts
3
+ ---
4
+
5
+ This document aims to discuss some of the core concepts of building with Primer React.
6
+
7
+ ## Responsive props
8
+
9
+ It's really easy to set different values for most of our component props based on screen size! We take advantage of [styled-system](https://github.com/styled-system/styled-system)'s responsive props API in our components.
10
+
11
+ ```
12
+ <Button display={['flex', 'flex', 'none']}/>
13
+
14
+ or
15
+
16
+ <Text fontSize={[1,1,1,4]}/>
17
+ ```
18
+
19
+ ## Providing your own theme
20
+
21
+ You can provide your own theme to Primer React! There are a few ways of doing this to varying degrees, checkout the [theme docs](https://primer.style/components/primer-theme) for more information.
22
+
23
+ ## The `css` prop
24
+
25
+ When push comes to shove and you just _really_ need to add a custom CSS rule, you can do that with the `css` prop. Please don't abuse this :)
26
+
27
+ ```
28
+ <Box css='border-bottom-right-radius: 0px' />
29
+
30
+ ```
31
+
32
+ Please note that you will need to have the **[styled-components babel plugin](https://www.styled-components.com/docs/tooling#babel-plugin)** set up in your project in order to use the `css` prop.
33
+
34
+ ## Types of components
35
+
36
+ We categorize our components into 3 general types. Building block components, pattern components, and helper components. Understanding how these types of components interact with each other can help you better understand how to get the most out of Primer React.
37
+
38
+ - Building Blocks
39
+
40
+ Building block components are components that are basic in their functions and can be used together with other components to build just about any UI. Some examples of building block components are `Box`, `Avatar`, `Details`, and `Link`.
41
+
42
+ - Pattern Components
43
+
44
+ Pattern components are components that are made up of several building block components to represent a commonly used pattern in our UI. Some examples of pattern components are `UnderlineNav` and `FilterList`. We plan on expanding our offering of pattern components in the near future.
45
+
46
+ - Helper Components
47
+
48
+ Helper components are components that help the user achieve common CSS patterns while maintaining some control over values used. Some examples of helper components are `Flex`, `Text`, `Grid`, and the `Position` components.
49
+
50
+ ## The `as` prop
51
+
52
+ The `as` prop is a feature that all of our components get from [styled-components](https://www.styled-components.com). It allows you to pass a HTML tag or another component to a Primer Component to be rendered as the base tag of that component along with all of it's styles and props.
53
+
54
+ For example, say you are using a `Button` component, and you really need to apply `Box` styles to it. You can compose `Box` and `Button` like so:
55
+
56
+ ```.jsx
57
+ <Box display="flex" as={Button} href='https://github.com'>Hello</Box>
58
+ ```
59
+
60
+ This will allow you to use all of the `Button` props _and_ all of the `Box` props without having to wrap your `Button` component in another `Box` component.
61
+
62
+ **This pattern does have some limitations.** Usage of the `as` prop can lead to unexpected output. In the example above, if the user had done `<Button as={Box}/>` instead, because the `Box`'s render method is ultimately applied, and `Box` components render `div`'s, you'll see that the rendered component is a `div` when ideally you'd like it to be a `button`. It is also not always clear how the styles in both components will interact and/or override each other.
63
+
64
+ For these reasons, **we recommend only using the `as` prop when you cannot achieve the same result by nesting components.** The `Box` / `Button` example could be done like so:
65
+
66
+ ```.jsx
67
+ <Box display="flex">
68
+ <Button href='https://github.com'>Hi</Button>
69
+ </Box>
70
+ ```
@@ -0,0 +1,103 @@
1
+ ---
2
+ title: Focus Trap Behavior
3
+ ---
4
+
5
+ The `focusTrap` behavior and `useFocusTrap` hook are used prevent focus from leaving a particular element. This is useful for implementing modal dialogs: only the content within the dialog should be interactive, even though the UI underneath may still be visible.
6
+
7
+ ### Behavior
8
+
9
+ - Activation: As soon as the focus trap is activated, it will ensure that an element within the container has focus. If it doesn't, it will focus the first focusable element within the container, or, if provided, the element indicated by the `initialFocus` parameter (see API below).
10
+ - External focus changes: If an external cause (e.g. mouse click, scripts, or accessibility software) results in an element outside the container to be focused, focus will immediately be redirected to the last-focused element that is inside the container.
11
+ - Circular tab focus: Using the `TAB` key on the last focusable element within the container will result in the first focusable element within the container receiving focus. Similarly, `Shift+TAB` can be used to focus the last element from the first.
12
+ - Global: Only one focus trap can be _active_ at a time. When a focus trap is enabled, if there is already an active focus trap, it becomes suspended and pushed onto a stack. Once the newly-active focus trap is disabled, the most recently-suspended trap will reactivate. Suspended focus traps can be disabled, causing them to be removed from the stack of suspended traps.
13
+
14
+ ### Demo
15
+
16
+ To see a demo, deploy Storybook and find the `useFocusTrap` stories.
17
+
18
+ ### Usage
19
+
20
+ ```ts
21
+ function showDialog() {
22
+ const dialog = document.getElementById('myDialog')
23
+ if (dialog instanceof HTMLElement) {
24
+ dialog.style.display = ''
25
+ return focusTrap(dialog)
26
+ }
27
+ }
28
+ function hideDialog(controller: AbortController) {
29
+ document.getElementById('myDialog')?.style.display = 'none'
30
+ controller.abort()
31
+ }
32
+ const dialogController = showDialog()
33
+
34
+ // later
35
+ if (dialogController) {
36
+ hideDialog(controller)
37
+ }
38
+ ```
39
+
40
+ ### API
41
+
42
+ The `focusTrap` function takes the following arguments.
43
+
44
+ | Name | Type | Default | Description |
45
+ | :----------- | :------------- | :---------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
46
+ | container | `HTMLElement` | | When active, only elements within this container (along with the container itself) can be focused. |
47
+ | initialFocus | `HTMLElement` | | Specifies the element which will receive focus when the focus trap is activated. Defaults to the first tabbable element inside the container. |
48
+ | signal | `AbortSignal?` | `undefined` | Optional abort signal to control the focus trap. If one is not provided, an `AbortController` will be returned, which can be used to disable the focus trap. |
49
+
50
+ #### Return value
51
+
52
+ If the `signal` argument is omitted, `focusTrap()` will return an `AbortController`. This object has an `abort()` method, which can be called to disable the focus trap.
53
+
54
+ ### Best practices
55
+
56
+ - Focus management is an important consideration for accessible applications. Sometimes poor focus management can make certain tasks impossible to complete for users not using a mouse. To learn more, read the [ARIA guidelines for keyboard focus](https://www.w3.org/TR/wai-aria-practices/#kbd_focus_discernable_predictable).
57
+ - Only activate a focus trap if all UI outside of the trap container should be inert (non-interactive).
58
+ - Avoid situations where multiple focus traps may be active (e.g. dialogs that open more dialogs). This behavior handles those situations, but the pattern may indicate poor UX.
59
+
60
+ ### A note on performance
61
+
62
+ When focus trap is activated, it must perform [reflow](https://developers.google.com/speed/docs/insights/browser-reflow) to discover focusable elements. Use caution not to rapidly enable and disable focus traps.
63
+
64
+ ## useFocusTrap hook
65
+
66
+ The `useFocusTrap` hook is used to achieve focus trapping for React components. The hook returns a `ref` that must be applied to the focus trap container. The hook also returns a ref that can be used to indicate the initially-focused element when a focus trap is activated.
67
+
68
+ The focus trap can be disabled in two ways:
69
+
70
+ 1. Simply do not render the component. When a component that uses focus trapping is unmounted, its focus trap will be aborted automatically.
71
+ 2. Pass `disabled: true` to the settings argument of `useFocusTrap`.
72
+
73
+ The `useFocusTrap` hook also has an additional setting, `restoreFocusOnCleanUp`. If this is set to true, when the hook is either disabled (called with `disabled: true` or unmounted), we will attempt to re-focus the element that was focused immediately before the focus trap was enabled.
74
+
75
+ ### Using your own refs
76
+
77
+ If you would like to use your own refs, you can pass them into the hook as part of the settings object (see the interface below).
78
+
79
+ ### Usage
80
+
81
+ ```jsx
82
+ export const FocusTrapExample = () => {
83
+ const {containerRef} = useFocusTrap()
84
+ return (
85
+ <div ref={containerRef as React.RefObject<HTMLDivElement>}>
86
+ <Button>Apple</Button>
87
+ <Button>Banana</Button>
88
+ <Button>Cantaloupe</Button>
89
+ </div>
90
+ )
91
+ }
92
+ ```
93
+
94
+ ### FocusTrapHookSettings interface
95
+
96
+ `FocusTrapHookSettings` has the following properties:
97
+
98
+ | Name | Type | Default | Description |
99
+ | :-------------------- | :---------------- | :---------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
100
+ | containerRef | `React.RefObject` | `undefined` | If provided, this will be the ref used to access the focus trap container. Otherwise, this hook will create the ref for you and return it. In both cases, the ref must be provided to the container element's JSX. |
101
+ | initialFocusRef | `React.RefObject` | `undefined` | If provided, this will be the ref used to access the element that should receive initial focus when the focus trap is activated. Otherwise, this hook will create the ref for you and return it. If unused, the first tabbable element inside the container will be focused. |
102
+ | disabled | `boolean` | `false` | If true, the previously-established focus trap for this container will be aborted. |
103
+ | restoreFocusOnCleanUp | `boolean` | `false` | If true, attempt to restore focus to the previously-focused element when the trap is disabled or unmounted. |
@@ -0,0 +1,145 @@
1
+ ---
2
+ title: Focus Zone Behavior
3
+ ---
4
+
5
+ The `focusZone` behavior and `useFocusZone` hook are used to designate a container where focus can be moved using keys other than `Tab`. This is useful for implementing many of the patterns described in [Section 6](https://www.w3.org/TR/wai-aria-practices-1.1/#keyboard) of the WAI-ARIA Authoring Practices document. The most common use case of this behavior is to allow arrow keys (up and down or left and right) to move focus between related elements, such as items in a menu.
6
+
7
+ At a high level, the `focusZone` behavior works by adjusting the `tabindex` attribute on focusable elements and setting up event listeners on the container that respond to the relevant key presses.
8
+
9
+ Settings for this behavior allow the user to customize several aspects of the focus zone. See **FocusZoneSettings** below for a detailed description of these settings.
10
+
11
+ ### Focusability: which elements participate in the Focus Zone?
12
+
13
+ When the `focusZone` behavior is established, it will discover all _focusable_ elements within the given container and allow them to be focused with the bound keys. _Focusable_ elements are those that either are normally focusable via the Tab key OR have a valid `tabindex` attribute (including `"-1"`). The easiest way to ensure an element participates in the focus zone is by applying the attribute `tabindex="-1"`. If you need to prevent a focusable element from participating in the focus zone, you can provide a `focusableElementFilter`.
14
+
15
+ ### Focus order
16
+
17
+ The `focusZone` behavior uses the natural DOM ordering of elements to determine focus order. This means that a key that moves focus will either move to a "next" element or to a "previous" element. For example, the left arrow key and the up arrow key would both move focus to the previous element in the DOM order, while the right arrow key and the down arrow key would both move focus to the next element in the DOM order.
18
+
19
+ Focus cannot be moved beyond the last element of the container (other than using the Tab key). The `focusOutBehavior` option can be used to allow focus to wrap around from last to first element (or vice-versa).
20
+
21
+ For a more customized focus movement behavior, the consumer has the ability to supply a custom callback that identifies the next element to focus.
22
+
23
+ #### Entering the focus zone
24
+
25
+ By default, when focus enters a focus zone, the element that receives focus will be the most recently-focused element within that focus zone. If no element had previously been focused, or if that previously-focused element was removed, focus will revert to the first focusable element within the focus zone, regardless of the direction of focus movement.
26
+
27
+ Using the `focusInStrategy` option, you can change this behavior. Setting this option to `"first"` will simply cause the first focusable element in the container to be focused whenever focus enters the focus zone. Setting it to `"closest"` will cause either the first or last focusable element in the container to be focused depending on the direction of focus movement (for example, a shift+tab that brings focus to the container will cause the last focusable element to be focused, whereas a regular tab would cause the first focusable element to be focused). Otherwise, you may provide a callback to choose a custom element to receive initial focus. One scenario where this would be useful is if you wanted to focus an item that is "selected" in a list.
28
+
29
+ For more information on choosing the right focus in behavior, see [6.6 Keyboard Navigation Inside Components](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_general_within) from the ARIA Authoring Practices document.
30
+
31
+ ### Supported keys
32
+
33
+ The `focusZone` behavior supports different sets of keys for moving focus around. The `bindKeys` option is used to set which of the following keys can be used to move focus.
34
+
35
+ | Key(s) | Notes | Use case |
36
+ | :-------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------- |
37
+ | ArrowVertical | Prevents default behavior of scrolling where applicable | Most focus zones with vertically-positioned elements |
38
+ | ArrowHorizontal | Prevents default behavior of scrolling where applicable | Most focus zones with horizontally-positioned elements |
39
+ | HomeAndEnd | Causes focus to jump to the first or last focusable item in the container. Does not move focus if the currently-focused element is a text box. | Generally used with arrow keys |
40
+ | PageUpDown | Works the same as the Home and End keys. Advisable only when supplying a custom callback that supports paging. | In a long, scrollable list |
41
+ | Tab/Shift+Tab | Unlike other keys, the Tab key will always allow movement outside of the focus zone (use the Focus Trap behavior to prevent this). Tab moves to the next item, Shift+Tab moves to the previous. | Bind Tab if you want to continue allowing tab to move focus between elements in your container rather than jumping out of the container. |
42
+ | JK | J moves focus to the next item, K moves to the previous. Does not move focus if the currently-focused element is a text box. [Originally from](https://catonmat.net/why-vim-uses-hjkl-as-arrow-keys) the vi keybindings | Used in certain lists |
43
+ | HL | H moves focus to the previous item, L moves to the next. Does not move focus if the currently-focused element is a text box. [Originally from](https://catonmat.net/why-vim-uses-hjkl-as-arrow-keys) the vi keybindings | Used in certain lists |
44
+ | WS | W moves focus to the previous item, S moves to the next. Does not move focus if the currently-focused element is a text box. | Any situation where it is more ergonomic for the left hand to perform this action, such as in a gaming context (rare) |
45
+ | AD | A moves focus to the previous item, D moves to the next. Does not move focus if the currently-focused element is a text box. | Any situation where it is more ergonomic for the left hand to perform this action, such as in a gaming context (rare) |
46
+
47
+ ### DOM Focus vs. Active Descendant
48
+
49
+ The `focusZone` behavior supports two modes of operation: DOM Focus and Active Descendant.
50
+
51
+ - DOM Focus is the default mode and by far the most commonly needed. When a key is used to move focus, we call `.focus()` directly on the element to receive focus. This results in `document.activeElement` getting set to this new element, and it will receive any necessary styles via `:focus` and `:focus-within`.
52
+ - Active Descendant mode does _not_ move DOM focus. Instead, focus remains on the _control_ element, and its `aria-activedescendant` attribute is set to the ID of the relevant element. Because there are no `:focus` styles applied and no `focus` events fired, you can supply an `onActiveDescendantChanged` callback to handle any necessary styles or other logic as the active descendant changes. For more information on the Active Descendant focus pattern, see [6.6.2 Managing Focus in Composites Using `aria-activedescendant`](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) from the ARIA Authoring Practices document.
53
+
54
+ ### Demo
55
+
56
+ Deploy Storybook to see live demos of `focusZone`.
57
+
58
+ ### Usage
59
+
60
+ ```ts
61
+ const settings = {
62
+ bindKeys: FocusKeys.ArrowVertical | FocusKeys.HomeAndEnd
63
+ } as FocusZoneSettings
64
+ const focusZone = document.getElementById('focusZoneContainer')
65
+ focusZone(focusZone, settings)
66
+ ```
67
+
68
+ ### API
69
+
70
+ The `focusZone` function takes the following arguments.
71
+
72
+ | Name | Type | Default | Description |
73
+ | :-------- | :------------------ | :-----: | :--------------------------------------------------------------------------------- |
74
+ | container | `Element` | | The focus zone will apply to this container and all of its focusable descendants. |
75
+ | settings | `FocusZoneSettings` | `{}` | Settings to customize the focus zone. See below for a description of each setting. |
76
+
77
+ #### FocusZoneSettings interface
78
+
79
+ `FocusZoneSettings` is an object with the following interface. All properties are optional and have default behaviors.
80
+
81
+ | Name | Type | Default | Description |
82
+ | :------------------------ | :-------------------------------------------- | :----------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
83
+ | bindKeys | `FocusKeys` (numeric enum) | `FocusKeys.ArrowVertical │ FocusKeys.HomeAndEnd` | Bit flags that identify keys that will move focus around the focus zone. Each available key either moves focus to the "next", "previous", "start", or "end" element, so it is best to only bind the keys that make sense to move focus in your UI. Use the `FocusKeys` object to discover supported keys (listed in the "Supported keys" section above). <br /><br />Use the bitwise "OR" operator (&#124;) to combine key types. For example, `FocusKeys.WASD │ FocusKeys.HJKL` represents all of W, A, S, D, H, J, K, and L.<br /><br />The default for this setting is `FocusKeys.ArrowVertical │ FocusKeys.HomeAndEnd`, unless `getNextFocusable` is provided, in which case `FocusKeys.ArrowAll │ FocusKeys.HomeAndEnd` is used as the default. |
84
+ | focusOutBehavior | `"stop" │ "wrap"` | `"stop"` | Choose the behavior applied in cases where focus is currently at either the first or last element of the container. `"stop"` - do nothing and keep focus where it was; `"wrap"` - wrap focus around to the first element from the last, or the last element from the first |
85
+ | focusInStrategy | `"first" │ "closest" │ "previous" │ Function` | `"previous"` | This option allows customization of the behavior that determines which of the focusable elements should be focused when focus enters the container via the Tab key.<br /><br />When set to `"first"`, whenever focus enters the container via Tab, we will focus the first focusable element. When set to `"previous"`, the most recently focused element will be focused (fallback to first if there was no previous).<br /><br />The "closest" strategy works like "first", except either the first or the last element of the container will be focused, depending on the direction from which focus comes.<br /><br />If a function is provided, this function should return the `HTMLElement` intended to receive focus. This is useful if you want to focus the currently "selected" item or element. |
86
+ | getNextFocusable | `Function` | | This is a callback used to customize the next element to focus when a bound key is pressed. The function takes 3 arguments: `direction` (`"previous"`, `"next"`, `"start"`, or `"end"`), `from` (Element or `undefined`), and `event` (KeyboardEvent). The function should return the next element to focus, or `undefined`. If `undefined` is returned, the regular algorithm to select the next element to focus will be used. |
87
+ | focusableElementFilter | `Function` | | This is a callback used to cull focusable elements from participating in the focus zone. |
88
+ | abortSignal | `AbortSignal` | | If passed, the focus zone will be deactivated and all event listeners removed when this signal is aborted. If not passed, an `AbortSignal` will be returned by the `focusZone` function. |
89
+ | activeDescendantControl | `HTMLElement` | | If `activeDescendantControl` is supplied, do not move focus or alter `tabindex` on any element. Instead, manage `aria-activedescendant` according to the [ARIA best practices guidelines](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant).<br /><br />The given `activeDescendantControl` will be given an `aria-controls` attribute that references the ID of the `container`. Additionally, it will be given an `aria-activedescendant` attribute that references the ID of the currently-active descendant.<br /><br />This element will retain DOM focus as arrow keys are pressed. |
90
+ | onActiveDescendantChanged | `Function` | | This function is called each time the active descendant changes (only applicable if `activeDescendantControl` is given). The function takes two arguments: `newActiveDescendant` and `previousActiveDescendant`, both `HTMLElement`, either of which can be undefined (e.g. when an element in the container first becomes active, or when the controlling element becomes unfocused). |
91
+
92
+ ### Best practices
93
+
94
+ We highly recommend reading [Section 6: Developing a Keyboard Interface](https://www.w3.org/TR/wai-aria-practices-1.1/#keyboard) from the WAI-ARIA Authoring Practices document.
95
+
96
+ ## useFocusZone hook
97
+
98
+ The `useFocusZone` hook is used to provide focus zone behavior to React components. The hook returns a ref that must be added to the container element.
99
+
100
+ ### Using your own refs
101
+
102
+ If you would like to use your own refs, you can pass them into the hook as part of the settings object (see the interface below).
103
+
104
+ ### Hook dependencies
105
+
106
+ Like other hooks such as `useCallback` and `useEffect`, this hook takes a dependencies array. If defined, the focus zone will be re-applied when a dependency changes (and the old one will be cleaned up).
107
+
108
+ ### Usage
109
+
110
+ ```jsx
111
+ export const FocusZoneExample = () => {
112
+ const {containerRef} = useFocusZone({bindKeys: FocusKeys.ArrowVertical | FocusKeys.HomeAndEnd})
113
+ return (
114
+ <div ref={containerRef}>
115
+ <button>First</button>
116
+ <button>Second</button>
117
+ <button>Third</button>
118
+ </div>
119
+ )
120
+ }
121
+ ```
122
+
123
+ ### useFocusZone hook
124
+
125
+ | Name | Type | Default | Description |
126
+ | :----------- | :---------------------- | :-------: | :------------------------------------------------------------------ |
127
+ | settings | `FocusZoneHookSettings` | undefined | Optional settings to control how the focus zone behaves. See below. |
128
+ | dependencies | `React.DependencyList` | undefined | Dependencies to determine when to initialize the focus zone. |
129
+
130
+ **Return value**
131
+
132
+ | Name | Type | Description |
133
+ | :------------------------- | :----------------------------- | :---------------------------------------------------------------------------------------- |
134
+ | containerRef | `React.RefObject<HTMLElement>` | This ref must be added to the container's JSX. |
135
+ | activeDescendantControlRef | `React.RefObject<HTMLElement>` | If using active descendant focusing, this ref must be added to the control element's JSX. |
136
+
137
+ ### FocusZoneHookSettings interface
138
+
139
+ `FocusZoneHookSettings` is an object with an interface that extends `FocusZoneSettings` (see above), however, the `activeDescendantControl` prop is omitted (instead see the `activeDescendantFocus` prop below). Additionally, it adds the following properties:
140
+
141
+ | Name | Type | Default | Description |
142
+ | :-------------------- | :--------------------------------------- | :---------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
143
+ | containerRef | `React.RefObject` | `undefined` | If provided, this will be the ref used to access the element that will become the container of the focus zone. Otherwise, this hook will create the ref for you and return it. In both cases, the ref must be provided to the container's JSX. |
144
+ | activeDescendantFocus | `boolean │ React.RefObject<HTMLElement>` | `false` | If false, the focus zone will apply normal DOM focusing (see **DOM Focus vs. Active Descendant** above). If true, or if a ref is provided, the focus zone will use "active descendant" focusing. If a ref is applied, it will be used as the control element for active descendant focus. If `true` is given, a ref will be created and returned by the hook. |
145
+ | disabled | `boolean` | `false` | Set to true to disable the focus zone and clean up listeners. Can be re-enabled at any time. |