@hyphen/hyphen-components 2.9.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 (319) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -0
  3. package/package.json +138 -0
  4. package/src/components/Alert/Alert.constants.ts +19 -0
  5. package/src/components/Alert/Alert.mdx +29 -0
  6. package/src/components/Alert/Alert.module.scss +74 -0
  7. package/src/components/Alert/Alert.stories.tsx +102 -0
  8. package/src/components/Alert/Alert.test.tsx +187 -0
  9. package/src/components/Alert/Alert.tsx +157 -0
  10. package/src/components/Alert/Alert.types.ts +14 -0
  11. package/src/components/Badge/Badge.mdx +28 -0
  12. package/src/components/Badge/Badge.module.scss +155 -0
  13. package/src/components/Badge/Badge.stories.tsx +52 -0
  14. package/src/components/Badge/Badge.test.tsx +74 -0
  15. package/src/components/Badge/Badge.tsx +70 -0
  16. package/src/components/Box/Box.mdx +259 -0
  17. package/src/components/Box/Box.module.scss +16 -0
  18. package/src/components/Box/Box.stories.tsx +1679 -0
  19. package/src/components/Box/Box.test.tsx +478 -0
  20. package/src/components/Box/Box.tsx +636 -0
  21. package/src/components/Button/Button.constants.ts +10 -0
  22. package/src/components/Button/Button.mdx +71 -0
  23. package/src/components/Button/Button.module.scss +312 -0
  24. package/src/components/Button/Button.stories.tsx +117 -0
  25. package/src/components/Button/Button.test.tsx +460 -0
  26. package/src/components/Button/Button.tsx +241 -0
  27. package/src/components/Card/Card.mdx +46 -0
  28. package/src/components/Card/Card.module.scss +6 -0
  29. package/src/components/Card/Card.stories.tsx +101 -0
  30. package/src/components/Card/Card.test.tsx +11 -0
  31. package/src/components/Card/Card.tsx +61 -0
  32. package/src/components/Card/components/CardFooter/CardFooter.test.tsx +11 -0
  33. package/src/components/Card/components/CardFooter/CardFooter.tsx +35 -0
  34. package/src/components/Card/components/CardHeader/CardHeader.test.tsx +23 -0
  35. package/src/components/Card/components/CardHeader/CardHeader.tsx +54 -0
  36. package/src/components/Card/components/CardSection/CardSection.test.tsx +28 -0
  37. package/src/components/Card/components/CardSection/CardSection.tsx +102 -0
  38. package/src/components/Card/components/index.ts +3 -0
  39. package/src/components/CheckboxInput/CheckboxInput.mdx +98 -0
  40. package/src/components/CheckboxInput/CheckboxInput.stories.tsx +254 -0
  41. package/src/components/CheckboxInput/CheckboxInput.test.tsx +436 -0
  42. package/src/components/CheckboxInput/CheckboxInput.tsx +171 -0
  43. package/src/components/CheckboxInput/components/Checkbox.module.scss +174 -0
  44. package/src/components/CheckboxInput/components/Checkbox.test.tsx +201 -0
  45. package/src/components/CheckboxInput/components/Checkbox.tsx +176 -0
  46. package/src/components/CheckboxInput/components/CheckboxIcon.tsx +71 -0
  47. package/src/components/DateInput/DateInput.mdx +61 -0
  48. package/src/components/DateInput/DateInput.stories.tsx +168 -0
  49. package/src/components/DateInput/DateInput.test.tsx +258 -0
  50. package/src/components/DateInput/DateInput.tsx +189 -0
  51. package/src/components/DatePicker/DatePicker.mdx +52 -0
  52. package/src/components/DatePicker/DatePicker.module.scss +603 -0
  53. package/src/components/DatePicker/DatePicker.stories.tsx +199 -0
  54. package/src/components/DatePicker/DatePicker.test.tsx +26 -0
  55. package/src/components/DatePicker/DatePicker.tsx +138 -0
  56. package/src/components/Details/Details.mdx +30 -0
  57. package/src/components/Details/Details.module.scss +32 -0
  58. package/src/components/Details/Details.stories.tsx +38 -0
  59. package/src/components/Details/Details.test.tsx +189 -0
  60. package/src/components/Details/Details.tsx +51 -0
  61. package/src/components/Details/DetailsSummary.tsx +65 -0
  62. package/src/components/Drawer/Drawer.mdx +117 -0
  63. package/src/components/Drawer/Drawer.module.scss +96 -0
  64. package/src/components/Drawer/Drawer.stories.tsx +380 -0
  65. package/src/components/Drawer/Drawer.test.tsx +90 -0
  66. package/src/components/Drawer/Drawer.tsx +249 -0
  67. package/src/components/FormControl/FormControl.tsx +78 -0
  68. package/src/components/FormLabel/FormLabel.mdx +24 -0
  69. package/src/components/FormLabel/FormLabel.module.scss +19 -0
  70. package/src/components/FormLabel/FormLabel.stories.tsx +20 -0
  71. package/src/components/FormLabel/FormLabel.test.tsx +35 -0
  72. package/src/components/FormLabel/FormLabel.tsx +96 -0
  73. package/src/components/Formik/Formik.mdx +10 -0
  74. package/src/components/Formik/Formik.stories.tsx +307 -0
  75. package/src/components/Formik/FormikCheckboxInput/FormikCheckboxInput.test.tsx +172 -0
  76. package/src/components/Formik/FormikCheckboxInput/FormikCheckboxInput.tsx +41 -0
  77. package/src/components/Formik/FormikRadioGroup/FormikRadioGroup.test.tsx +205 -0
  78. package/src/components/Formik/FormikRadioGroup/FormikRadioGroup.tsx +37 -0
  79. package/src/components/Formik/FormikSelectInput/FormikSelectInput.test.tsx +210 -0
  80. package/src/components/Formik/FormikSelectInput/FormikSelectInput.tsx +41 -0
  81. package/src/components/Formik/FormikSelectInputInset/FormikSelectInputInset.test.tsx +153 -0
  82. package/src/components/Formik/FormikSelectInputInset/FormikSelectInputInset.tsx +44 -0
  83. package/src/components/Formik/FormikSelectInputNative/FormikSelectInputNative.test.tsx +161 -0
  84. package/src/components/Formik/FormikSelectInputNative/FormikSelectInputNative.tsx +46 -0
  85. package/src/components/Formik/FormikTextInput/FormikTextInput.test.tsx +176 -0
  86. package/src/components/Formik/FormikTextInput/FormikTextInput.tsx +38 -0
  87. package/src/components/Formik/FormikTextInputInset/FormikTextInputInset.test.tsx +170 -0
  88. package/src/components/Formik/FormikTextInputInset/FormikTextInputInset.tsx +42 -0
  89. package/src/components/Formik/FormikTextareaInput/FormikTextareaInput.test.tsx +186 -0
  90. package/src/components/Formik/FormikTextareaInput/FormikTextareaInput.tsx +42 -0
  91. package/src/components/Formik/FormikTextareaInputInset/FormikTextareaInputInset.test.tsx +179 -0
  92. package/src/components/Formik/FormikTextareaInputInset/FormikTextareaInputInset.tsx +42 -0
  93. package/src/components/Formik/FormikTimePicker/FormikTimePicker.test.tsx +224 -0
  94. package/src/components/Formik/FormikTimePicker/FormikTimePicker.tsx +37 -0
  95. package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.test.tsx +175 -0
  96. package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.tsx +38 -0
  97. package/src/components/Formik/FormikToggle/FormikToggle.test.tsx +172 -0
  98. package/src/components/Formik/FormikToggle/FormikToggle.tsx +38 -0
  99. package/src/components/Heading/Heading.constants.ts +19 -0
  100. package/src/components/Heading/Heading.mdx +35 -0
  101. package/src/components/Heading/Heading.module.scss +5 -0
  102. package/src/components/Heading/Heading.stories.tsx +90 -0
  103. package/src/components/Heading/Heading.test.tsx +67 -0
  104. package/src/components/Heading/Heading.tsx +67 -0
  105. package/src/components/HelpText/HelpText.module.scss +14 -0
  106. package/src/components/HelpText/HelpText.tsx +33 -0
  107. package/src/components/Icon/Icon.mdx +40 -0
  108. package/src/components/Icon/Icon.stories.tsx +72 -0
  109. package/src/components/Icon/Icon.test.tsx +30 -0
  110. package/src/components/Icon/Icon.tsx +61 -0
  111. package/src/components/InputValidationMessage/InputValidationMessage.module.scss +3 -0
  112. package/src/components/InputValidationMessage/InputValidationMessage.tsx +27 -0
  113. package/src/components/Modal/Modal.mdx +60 -0
  114. package/src/components/Modal/Modal.module.scss +135 -0
  115. package/src/components/Modal/Modal.stories.tsx +194 -0
  116. package/src/components/Modal/Modal.test.tsx +81 -0
  117. package/src/components/Modal/Modal.tsx +174 -0
  118. package/src/components/Modal/components/ModalBody/ModalBody.test.tsx +20 -0
  119. package/src/components/Modal/components/ModalBody/ModalBody.tsx +24 -0
  120. package/src/components/Modal/components/ModalFooter/ModalFooter.test.tsx +32 -0
  121. package/src/components/Modal/components/ModalFooter/ModalFooter.tsx +37 -0
  122. package/src/components/Modal/components/ModalHeader/ModalHeader.test.tsx +29 -0
  123. package/src/components/Modal/components/ModalHeader/ModalHeader.tsx +58 -0
  124. package/src/components/Modal/components/index.ts +5 -0
  125. package/src/components/Pagination/Pagination.mdx +26 -0
  126. package/src/components/Pagination/Pagination.stories.tsx +55 -0
  127. package/src/components/Pagination/Pagination.test.tsx +225 -0
  128. package/src/components/Pagination/Pagination.tsx +162 -0
  129. package/src/components/Pagination/Pagination.utilities.test.ts +133 -0
  130. package/src/components/Pagination/Pagination.utilities.ts +101 -0
  131. package/src/components/Popover/Popover.mdx +104 -0
  132. package/src/components/Popover/Popover.module.scss +74 -0
  133. package/src/components/Popover/Popover.stories.tsx +471 -0
  134. package/src/components/Popover/Popover.test.tsx +128 -0
  135. package/src/components/Popover/Popover.tsx +277 -0
  136. package/src/components/RadioGroup/RadioGroup.mdx +81 -0
  137. package/src/components/RadioGroup/RadioGroup.module.scss +23 -0
  138. package/src/components/RadioGroup/RadioGroup.stories.tsx +375 -0
  139. package/src/components/RadioGroup/RadioGroup.test.tsx +282 -0
  140. package/src/components/RadioGroup/RadioGroup.tsx +145 -0
  141. package/src/components/RadioGroup/RadioInput/RadioInput.module.scss +114 -0
  142. package/src/components/RadioGroup/RadioInput/RadioInput.test.tsx +156 -0
  143. package/src/components/RadioGroup/RadioInput/RadioInput.tsx +148 -0
  144. package/src/components/RadioGroup/RadioInput/RadioInputIcon.tsx +59 -0
  145. package/src/components/ResponsiveProvider/ResponsiveProvider.mdx +36 -0
  146. package/src/components/ResponsiveProvider/ResponsiveProvider.stories.tsx +54 -0
  147. package/src/components/ResponsiveProvider/ResponsiveProvider.test.tsx +70 -0
  148. package/src/components/ResponsiveProvider/ResponsiveProvider.tsx +73 -0
  149. package/src/components/SelectInput/SelectInput.mdx +115 -0
  150. package/src/components/SelectInput/SelectInput.module.scss +357 -0
  151. package/src/components/SelectInput/SelectInput.stories.tsx +373 -0
  152. package/src/components/SelectInput/SelectInput.test.tsx +403 -0
  153. package/src/components/SelectInput/SelectInput.tsx +245 -0
  154. package/src/components/SelectInputInset/SelectInputInset.mdx +56 -0
  155. package/src/components/SelectInputInset/SelectInputInset.module.scss +397 -0
  156. package/src/components/SelectInputInset/SelectInputInset.stories.tsx +189 -0
  157. package/src/components/SelectInputInset/SelectInputInset.test.tsx +305 -0
  158. package/src/components/SelectInputInset/SelectInputInset.tsx +235 -0
  159. package/src/components/SelectInputNative/SelectInputNative.mdx +87 -0
  160. package/src/components/SelectInputNative/SelectInputNative.module.scss +356 -0
  161. package/src/components/SelectInputNative/SelectInputNative.stories.tsx +282 -0
  162. package/src/components/SelectInputNative/SelectInputNative.test.tsx +341 -0
  163. package/src/components/SelectInputNative/SelectInputNative.tsx +121 -0
  164. package/src/components/Spinner/Spinner.mdx +29 -0
  165. package/src/components/Spinner/Spinner.module.scss +16 -0
  166. package/src/components/Spinner/Spinner.stories.tsx +48 -0
  167. package/src/components/Spinner/Spinner.test.tsx +47 -0
  168. package/src/components/Spinner/Spinner.tsx +116 -0
  169. package/src/components/Table/Table.mdx +216 -0
  170. package/src/components/Table/Table.module.scss +61 -0
  171. package/src/components/Table/Table.stories.tsx +884 -0
  172. package/src/components/Table/Table.test.tsx +437 -0
  173. package/src/components/Table/Table.tsx +171 -0
  174. package/src/components/Table/TableBody/TableBody.module.scss +19 -0
  175. package/src/components/Table/TableBody/TableBody.test.tsx +38 -0
  176. package/src/components/Table/TableBody/TableBody.tsx +96 -0
  177. package/src/components/Table/TableBody/TableBodyCell/TableBodyCell.module.scss +47 -0
  178. package/src/components/Table/TableBody/TableBodyCell/TableBodyCell.test.tsx +81 -0
  179. package/src/components/Table/TableBody/TableBodyCell/TableBodyCell.tsx +94 -0
  180. package/src/components/Table/TableHead/TableHead.test.tsx +20 -0
  181. package/src/components/Table/TableHead/TableHead.tsx +78 -0
  182. package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.module.scss +72 -0
  183. package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.test.tsx +187 -0
  184. package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.tsx +192 -0
  185. package/src/components/Table/common/TableRow/TableRow.module.scss +5 -0
  186. package/src/components/Table/common/TableRow/TableRow.test.tsx +52 -0
  187. package/src/components/Table/common/TableRow/TableRow.tsx +155 -0
  188. package/src/components/TextInput/TextInput.mdx +96 -0
  189. package/src/components/TextInput/TextInput.module.scss +405 -0
  190. package/src/components/TextInput/TextInput.stories.tsx +268 -0
  191. package/src/components/TextInput/TextInput.test.tsx +231 -0
  192. package/src/components/TextInput/TextInput.tsx +263 -0
  193. package/src/components/TextInputInset/TextInputInset.mdx +62 -0
  194. package/src/components/TextInputInset/TextInputInset.module.scss +418 -0
  195. package/src/components/TextInputInset/TextInputInset.stories.tsx +213 -0
  196. package/src/components/TextInputInset/TextInputInset.test.tsx +222 -0
  197. package/src/components/TextInputInset/TextInputInset.tsx +261 -0
  198. package/src/components/TextareaInput/TextareaInput.mdx +117 -0
  199. package/src/components/TextareaInput/TextareaInput.module.scss +275 -0
  200. package/src/components/TextareaInput/TextareaInput.stories.tsx +293 -0
  201. package/src/components/TextareaInput/TextareaInput.test.tsx +195 -0
  202. package/src/components/TextareaInput/TextareaInput.tsx +182 -0
  203. package/src/components/TextareaInputInset/TextareaInputInset.mdx +55 -0
  204. package/src/components/TextareaInputInset/TextareaInputInset.module.scss +337 -0
  205. package/src/components/TextareaInputInset/TextareaInputInset.stories.tsx +160 -0
  206. package/src/components/TextareaInputInset/TextareaInputInset.test.tsx +199 -0
  207. package/src/components/TextareaInputInset/TextareaInputInset.tsx +213 -0
  208. package/src/components/ThemeProvider/ThemeProvider.mdx +11 -0
  209. package/src/components/ThemeProvider/ThemeProvider.stories.tsx +56 -0
  210. package/src/components/ThemeProvider/ThemeProvider.tsx +75 -0
  211. package/src/components/TimePicker/TimePicker.mdx +75 -0
  212. package/src/components/TimePicker/TimePicker.stories.tsx +149 -0
  213. package/src/components/TimePicker/TimePicker.test.tsx +97 -0
  214. package/src/components/TimePicker/TimePicker.tsx +83 -0
  215. package/src/components/TimePickerNative/TimePickerNative.mdx +67 -0
  216. package/src/components/TimePickerNative/TimePickerNative.stories.tsx +151 -0
  217. package/src/components/TimePickerNative/TimePickerNative.test.tsx +117 -0
  218. package/src/components/TimePickerNative/TimePickerNative.tsx +93 -0
  219. package/src/components/Toast/Toast.mdx +134 -0
  220. package/src/components/Toast/Toast.store.ts +280 -0
  221. package/src/components/Toast/Toast.stories.tsx +283 -0
  222. package/src/components/Toast/Toast.test.tsx +784 -0
  223. package/src/components/Toast/Toast.types.ts +98 -0
  224. package/src/components/Toast/ToastContainer.tsx +170 -0
  225. package/src/components/Toast/ToastNotification.module.scss +63 -0
  226. package/src/components/Toast/ToastNotification.tsx +176 -0
  227. package/src/components/Toast/index.ts +4 -0
  228. package/src/components/Toast/toast.ts +102 -0
  229. package/src/components/Toast/useToasts.ts +102 -0
  230. package/src/components/Toggle/Toggle.mdx +51 -0
  231. package/src/components/Toggle/Toggle.module.scss +294 -0
  232. package/src/components/Toggle/Toggle.stories.tsx +128 -0
  233. package/src/components/Toggle/Toggle.test.tsx +308 -0
  234. package/src/components/Toggle/Toggle.tsx +184 -0
  235. package/src/constants/keyCodes.ts +2 -0
  236. package/src/docs/Brands.mdx +153 -0
  237. package/src/docs/Colors.mdx +158 -0
  238. package/src/docs/DesignTokens.mdx +415 -0
  239. package/src/docs/GetStarted.mdx +47 -0
  240. package/src/docs/intro.mdx +12 -0
  241. package/src/fonts/AvenirBold.otf +0 -0
  242. package/src/fonts/AvenirBold.woff +0 -0
  243. package/src/fonts/AvenirBold.woff2 +0 -0
  244. package/src/fonts/AvenirLight.otf +0 -0
  245. package/src/fonts/AvenirLight.woff +0 -0
  246. package/src/fonts/AvenirLight.woff2 +0 -0
  247. package/src/fonts/AvenirRegular.otf +0 -0
  248. package/src/fonts/AvenirRegular.woff +0 -0
  249. package/src/fonts/AvenirRegular.woff2 +0 -0
  250. package/src/fonts/Geist-Bold.otf +0 -0
  251. package/src/fonts/Geist-Bold.woff +0 -0
  252. package/src/fonts/Geist-Bold.woff2 +0 -0
  253. package/src/fonts/Geist-Medium.otf +0 -0
  254. package/src/fonts/Geist-Medium.woff +0 -0
  255. package/src/fonts/Geist-Medium.woff2 +0 -0
  256. package/src/fonts/Geist-Regular.otf +0 -0
  257. package/src/fonts/Geist-Regular.woff +0 -0
  258. package/src/fonts/Geist-Regular.woff2 +0 -0
  259. package/src/fonts/Geist-SemiBold.otf +0 -0
  260. package/src/fonts/Geist-SemiBold.woff +0 -0
  261. package/src/fonts/Geist-SemiBold.woff2 +0 -0
  262. package/src/fonts/GeistMono-Regular.otf +0 -0
  263. package/src/fonts/GeistMono-Regular.woff +0 -0
  264. package/src/fonts/GeistMono-Regular.woff2 +0 -0
  265. package/src/hooks/index.ts +4 -0
  266. package/src/hooks/useBreakpoint/useBreakpoint.mdx +26 -0
  267. package/src/hooks/useBreakpoint/useBreakpoint.stories.tsx +30 -0
  268. package/src/hooks/useBreakpoint/useBreakpoint.test.tsx +19 -0
  269. package/src/hooks/useBreakpoint/useBreakpoint.ts +50 -0
  270. package/src/hooks/useIsomorphicLayoutEffect/useIsomorphicLayouEffect.ts +5 -0
  271. package/src/hooks/useOpenClose/useOpenClose.mdx +15 -0
  272. package/src/hooks/useOpenClose/useOpenClose.stories.tsx +41 -0
  273. package/src/hooks/useOpenClose/useOpenClose.test.tsx +119 -0
  274. package/src/hooks/useOpenClose/useOpenClose.tsx +95 -0
  275. package/src/hooks/useWindowSize/useWindowSize.mdx +25 -0
  276. package/src/hooks/useWindowSize/useWindowSize.stories.tsx +35 -0
  277. package/src/hooks/useWindowSize/useWindowSize.ts +24 -0
  278. package/src/index.ts +48 -0
  279. package/src/lib/cssShorthandToClasses.test.ts +149 -0
  280. package/src/lib/cssShorthandToClasses.ts +133 -0
  281. package/src/lib/doesStringIncludeCssUnit.ts +6 -0
  282. package/src/lib/generateResponsiveClasses.test.ts +24 -0
  283. package/src/lib/generateResponsiveClasses.ts +30 -0
  284. package/src/lib/getAutoCompleteValue.test.ts +27 -0
  285. package/src/lib/getAutoCompleteValue.ts +12 -0
  286. package/src/lib/getColumnKeys.ts +27 -0
  287. package/src/lib/getDimensionCss.test.ts +148 -0
  288. package/src/lib/getDimensionCss.ts +73 -0
  289. package/src/lib/getElementType.test.tsx +42 -0
  290. package/src/lib/getElementType.ts +42 -0
  291. package/src/lib/getFlexCss.test.ts +122 -0
  292. package/src/lib/getFlexCss.ts +67 -0
  293. package/src/lib/index.ts +15 -0
  294. package/src/lib/isFunction.ts +6 -0
  295. package/src/lib/mergeRefs.ts +15 -0
  296. package/src/lib/prefersReducedMotion.ts +12 -0
  297. package/src/lib/react-children-utilities/filter.ts +12 -0
  298. package/src/lib/react-children-utilities/index.ts +1 -0
  299. package/src/lib/reactRouterClickHandler.ts +37 -0
  300. package/src/lib/resolveValue.ts +7 -0
  301. package/src/lib/tokens.ts +139 -0
  302. package/src/modes.ts +8 -0
  303. package/src/styles/animation.scss +152 -0
  304. package/src/styles/cursor.scss +43 -0
  305. package/src/styles/display.scss +119 -0
  306. package/src/styles/flex.scss +453 -0
  307. package/src/styles/fonts.scss +44 -0
  308. package/src/styles/globals/utilities.scss +4 -0
  309. package/src/styles/mixins.scss +14 -0
  310. package/src/styles/overflow.scss +41 -0
  311. package/src/styles/position.scss +45 -0
  312. package/src/styles/reset.scss +108 -0
  313. package/src/styles/text-align.scss +21 -0
  314. package/src/styles/utilities.scss +9 -0
  315. package/src/styles/variables/forms.scss +71 -0
  316. package/src/styles/variables/index.scss +3 -0
  317. package/src/styles/white-space.scss +21 -0
  318. package/src/types/index.ts +201 -0
  319. package/src/types/lib.types.ts +3 -0
@@ -0,0 +1,104 @@
1
+ import { Canvas, Meta, ArgTypes } from '@storybook/blocks';
2
+ import { Popover } from './Popover';
3
+ import * as Stories from './Popover.stories';
4
+
5
+ <Meta of={Stories} />
6
+
7
+ # Popover
8
+
9
+ Use popovers to show content of any kind behind the context of a specific trigger, some examples
10
+ of uses for a popover include:
11
+
12
+ 1. Dropdowns
13
+ 2. Tooltips
14
+ 3. Context Menus
15
+
16
+ <Canvas withSource="open" of={Stories.BasicUsage} />
17
+
18
+ The popover requires a `children` node that will act as a trigger, as well as a `content` prop that has the contents of the Popover.
19
+
20
+ Use the `isOpen` prop to govern the state of the Popover. This is done by attaching a `onClick` event to the trigger element.
21
+
22
+ By default the Popover will render with placement on the right, as well as a white background and some base padding on the container. All of these
23
+ items, however are fully customizable.
24
+
25
+ ## Props
26
+
27
+ <ArgTypes of={Popover} />
28
+
29
+ ## Popover Styling
30
+
31
+ Because the rendered Popover is powered by our `Box` component ([Read More](/?path=/docs/components-box-overview--background)) you
32
+ can use all known box props to style it. The below example includes some of the basics, but is not representative of
33
+ the entire gamut of styling options.
34
+
35
+ <Canvas withSource="open" of={Stories.PopoverStyling} />
36
+
37
+ ## Placement
38
+
39
+ Based on layout, it is beneficial to place the popover in a variety of positions relative to its trigger element.
40
+ Note that in case where the popover is in danger of overflowing, the component will fallback to `auto` in order to
41
+ prevent the content from getting cut off.
42
+
43
+ <Canvas withSource="open" of={Stories.Placement} />
44
+
45
+ ## With a Portal
46
+
47
+ Popovers in lots of cases need to break away from the HTML structure of their parent elements
48
+ in order to maintain semantic order on the page. This can also help with z-index conflicts
49
+ and ensure content isn't cut off in certain cases by the popover's parent container.
50
+
51
+ To render the Popover outside in an element other than its parent container, we
52
+ use a (React Portal)[https://reactjs.org/docs/portals.html].
53
+
54
+ By default the element is portaled into the document `body` but you can use the `portalTarget` prop
55
+ in order to render the element anywhere on the page.
56
+
57
+ <Canvas withSource="open" of={Stories.WithAPortal} />
58
+
59
+ ## Hover Trigger
60
+
61
+ In cases where small amounts of additional context are needed for a particular item,
62
+ it might be beneficial to trigger the Popover on hover. Since the component is fully controlled
63
+ this can be done easily by attaching mouse events to the trigger element as show below.
64
+
65
+ NOTE: this should be use sparingly since context dependent on hover, isn't an optimal experience for mobile users.
66
+
67
+ <Canvas withSource="open" of={Stories.HoverTrigger} />
68
+
69
+ ## Respond to Outside Clicks
70
+
71
+ Since Popovers are by nature rendered on top of existing content, it
72
+ is beneficial in most cases to close the Popover when a user clicks any item outside
73
+ the trigger and popover content.
74
+
75
+ Our component provides a `onClickOutside` prop that fires a callback whenever there is a click
76
+ event outside the Popover content, OR, when the user taps the `Escape` key.
77
+ You can use the callback to set `isOpen` to false.
78
+
79
+ NOTE: the click event is attached to the `document.body`, but will not bubble up the event
80
+ in cases where the click target includes the Popover trigger or content nodes.
81
+
82
+ <Canvas withSource="open" of={Stories.RespondToOutsideClicks} />
83
+
84
+ ## Trapping Focus
85
+
86
+ Trapping focus in a Popover is valuable in many cases to preserve accessibility. It consists
87
+ of constraining the items available for focusing to ONLY the content of the Popover, hence preventing
88
+ users from focusing on elements that might be behind or outside the Popover content.
89
+
90
+ Use the `trapFocus` prop to constrain focus to popover content elements.
91
+
92
+ <Canvas withSource="open" of={Stories.TrappingFocus} />
93
+
94
+ ## Without An Arrow
95
+
96
+ Render the popover with no arrow by passing `hasArrow` false.
97
+
98
+ <Canvas withSource="open" of={Stories.WithoutAnArrow} />
99
+
100
+ ## Offset Distance
101
+
102
+ Place the popover closer or farther from its trigger with the `offsetFromTarget` prop.
103
+
104
+ <Canvas withSource="open" of={Stories.OffsetDistance} />
@@ -0,0 +1,74 @@
1
+ @keyframes fadeIn {
2
+ 0% {
3
+ opacity: 0;
4
+ }
5
+
6
+ 100% {
7
+ opacity: 1;
8
+ }
9
+ }
10
+
11
+ .popover {
12
+ z-index: var(--size-z-index-popover);
13
+ animation: fadeIn 0.2s;
14
+ }
15
+
16
+ .popover-arrow {
17
+ position: absolute;
18
+ width: 0.8rem;
19
+ height: 0.8rem;
20
+
21
+ &::before {
22
+ position: absolute;
23
+ transform: rotate(45deg);
24
+ z-index: -1;
25
+ background-color: inherit;
26
+ width: 0.8rem;
27
+ height: 0.8rem;
28
+ content: '';
29
+ }
30
+ }
31
+
32
+ [data-popper-placement*='bottom'] {
33
+ .popover-arrow {
34
+ top: -0.1rem;
35
+
36
+ &::before {
37
+ bottom: 0.25rem;
38
+ box-shadow: rgb(0 0 0 / 5%) -1px -1px 1px 0;
39
+ }
40
+ }
41
+ }
42
+
43
+ [data-popper-placement*='top'] {
44
+ .popover-arrow {
45
+ bottom: -0.1rem;
46
+
47
+ &::before {
48
+ top: 0.25rem;
49
+ box-shadow: rgb(0 0 0 / 8%) 3px 3px 3px 0;
50
+ }
51
+ }
52
+ }
53
+
54
+ [data-popper-placement*='left'] {
55
+ .popover-arrow {
56
+ right: -0.1rem;
57
+
58
+ &::before {
59
+ left: 0.25rem;
60
+ box-shadow: rgb(0 0 0 / 8%) 1px -1px 1px 0;
61
+ }
62
+ }
63
+ }
64
+
65
+ [data-popper-placement*='right'] {
66
+ .popover-arrow {
67
+ left: -0.1rem;
68
+
69
+ &::before {
70
+ right: 0.25rem;
71
+ box-shadow: rgb(0 0 0 / 5%) -2px 2px 2px 0;
72
+ }
73
+ }
74
+ }
@@ -0,0 +1,471 @@
1
+ import { Popover } from './Popover';
2
+ import type { Meta } from '@storybook/react';
3
+ import React, { ChangeEvent } from 'react';
4
+ import { useState } from 'react';
5
+ import { Button } from '../Button/Button';
6
+ import { Box } from '../Box/Box';
7
+ import { SelectInput } from '../SelectInput/SelectInput';
8
+ import { TextInput } from '../TextInput/TextInput';
9
+ import { Heading } from '../Heading/Heading';
10
+ import { useOpenClose } from '../../hooks/useOpenClose/useOpenClose';
11
+ import {
12
+ BackgroundColor,
13
+ FontColor,
14
+ } from '@hyphen/hyphen-design-tokens/build/types';
15
+
16
+ const meta: Meta<typeof Popover> = {
17
+ title: 'Components/Popover',
18
+ component: Popover,
19
+ };
20
+
21
+ export default meta;
22
+
23
+ export const BasicUsage = () => {
24
+ const {
25
+ isOpen: isPopoverOpen,
26
+ handleToggle: togglePopover,
27
+ handleClose: closePopover,
28
+ } = useOpenClose();
29
+ const popoverContent = <>Hello!</>;
30
+ return (
31
+ <>
32
+ <Popover
33
+ content={popoverContent}
34
+ isOpen={isPopoverOpen}
35
+ placement="right"
36
+ contentContainerProps={{
37
+ padding: 'sm',
38
+ }}
39
+ onClickOutside={closePopover}
40
+ >
41
+ <Button onClick={togglePopover} variant="primary">
42
+ Toggle Popover
43
+ </Button>
44
+ </Popover>
45
+ </>
46
+ );
47
+ };
48
+
49
+ type PopoverStylingType = {
50
+ value: string;
51
+ label: string;
52
+ } | null;
53
+
54
+ export const PopoverStyling = () => {
55
+ const { isOpen: isPopoverOpen, handleToggle: togglePopover } = useOpenClose();
56
+ const [popoverBackground, setPopoverBackground] =
57
+ useState<PopoverStylingType>({
58
+ value: 'primary-500',
59
+ label: 'Primary 500',
60
+ });
61
+ const [popoverFontColor, setPopoverFontColor] = useState<PopoverStylingType>({
62
+ value: 'black-500',
63
+ label: 'Black 500',
64
+ });
65
+ const [popoverRadius, setPopoverRadius] = useState<PopoverStylingType>({
66
+ value: 'sm',
67
+ label: 'Small',
68
+ });
69
+ const backgroundOptions = [
70
+ { value: 'primary', label: 'primary' },
71
+ { value: 'secondary', label: 'secondary' },
72
+ { value: 'info', label: 'info' },
73
+ { value: 'warning', label: 'warn' },
74
+ { value: 'danger', label: 'danger' },
75
+ ];
76
+ const fontColorOptions = [
77
+ { value: 'base', label: 'base' },
78
+ { value: 'inverse', label: 'inverse' },
79
+ ];
80
+ const borderRadiusOptions = [
81
+ { value: 'sm', label: 'Small' },
82
+ { value: 'md', label: 'Medium' },
83
+ { value: 'lg', label: 'Large' },
84
+ ];
85
+ return (
86
+ <Box height="400px">
87
+ <Box direction="row" gap="md" wrap>
88
+ <Popover
89
+ content={
90
+ <>
91
+ <p>Hello world!</p>
92
+ <p>Style me any way you want</p>
93
+ </>
94
+ }
95
+ isOpen={isPopoverOpen}
96
+ placement={'right'}
97
+ contentContainerProps={{
98
+ padding: 'sm',
99
+ background: popoverBackground!.value as BackgroundColor,
100
+ color: popoverFontColor!.value as FontColor,
101
+ radius: popoverRadius!.value,
102
+ }}
103
+ >
104
+ <Button onClick={togglePopover} variant="primary">
105
+ Toggle Popover
106
+ </Button>
107
+ </Popover>
108
+ </Box>
109
+ <Box direction="row" gap="sm" wrap margin="3xl 0 0 0">
110
+ <Box width="200px">
111
+ <SelectInput
112
+ id="backgroundOptions"
113
+ options={backgroundOptions}
114
+ onChange={(event) => {
115
+ // @ts-ignore
116
+ setPopoverBackground(event.target.value);
117
+ }}
118
+ value={popoverBackground}
119
+ label="Background Color"
120
+ />
121
+ </Box>
122
+ <Box width="200px">
123
+ <SelectInput
124
+ id="fontColorOptions"
125
+ options={fontColorOptions}
126
+ onChange={(event) => {
127
+ // @ts-ignore
128
+ setPopoverFontColor(event.target.value);
129
+ }}
130
+ value={popoverFontColor}
131
+ label="Font Color"
132
+ />
133
+ </Box>
134
+ <Box width="200px">
135
+ <SelectInput
136
+ id="borderRadiusOptions"
137
+ options={borderRadiusOptions}
138
+ onChange={(event) => {
139
+ // @ts-ignore
140
+ setPopoverRadius(event.target.value);
141
+ }}
142
+ value={popoverRadius}
143
+ label="Border Radius"
144
+ />
145
+ </Box>
146
+ </Box>
147
+ </Box>
148
+ );
149
+ };
150
+
151
+ export const Placement = () => {
152
+ const [isPopoverOpen, setPopoverOpen] = useState({
153
+ auto: false,
154
+ 'auto-start': false,
155
+ 'auto-end': false,
156
+ top: false,
157
+ bottom: false,
158
+ right: false,
159
+ left: false,
160
+ 'top-start': false,
161
+ 'top-end': false,
162
+ 'bottom-start': false,
163
+ 'bottom-end': false,
164
+ 'right-start': false,
165
+ 'right-end': false,
166
+ 'left-start': false,
167
+ 'left-end': false,
168
+ });
169
+ const handleOpenPopover = (key: string) => {
170
+ // @ts-ignore
171
+ setPopoverOpen({ ...isPopoverOpen, [key]: !isPopoverOpen[key] });
172
+ };
173
+ const positions = [
174
+ 'auto',
175
+ 'auto-start',
176
+ 'auto-end',
177
+ 'top',
178
+ 'bottom',
179
+ 'right',
180
+ 'left',
181
+ 'top-start',
182
+ 'top-end',
183
+ 'bottom-start',
184
+ 'bottom-end',
185
+ 'right-start',
186
+ 'right-end',
187
+ 'left-start',
188
+ 'left-end',
189
+ ];
190
+
191
+ return (
192
+ <Box direction="row" gap="md" wrap>
193
+ {positions.map((position) => (
194
+ <Box height="100px" padding="5xl" display="inline-block" key={position}>
195
+ <Popover
196
+ content={<>{position}</>}
197
+ // @ts-ignore
198
+ isOpen={isPopoverOpen[position]}
199
+ // @ts-ignore
200
+ placement={position}
201
+ contentContainerProps={{
202
+ padding: 'sm',
203
+ background: 'info',
204
+ color: 'base',
205
+ }}
206
+ >
207
+ <Button
208
+ onClick={() => handleOpenPopover(position)}
209
+ variant="primary"
210
+ >
211
+ {position}
212
+ </Button>
213
+ </Popover>
214
+ </Box>
215
+ ))}
216
+ </Box>
217
+ );
218
+ };
219
+
220
+ export const WithAPortal = () => {
221
+ const {
222
+ isOpen: isPopoverOpen,
223
+ handleToggle: togglePopover,
224
+ handleClose: closePopover,
225
+ } = useOpenClose();
226
+ const popoverContent = (
227
+ <>
228
+ <Heading style={{ marginBottom: '0.5rem' }}>
229
+ I am living in the body element!
230
+ </Heading>
231
+ <p>That's why I can break out of my container without getting cut off</p>
232
+ </>
233
+ );
234
+ return (
235
+ <Box display="inline-block">
236
+ <Popover
237
+ content={popoverContent}
238
+ isOpen={isPopoverOpen}
239
+ placement="right-start"
240
+ contentContainerProps={{
241
+ padding: 'md',
242
+ background: 'danger',
243
+ color: 'base',
244
+ }}
245
+ withPortal
246
+ portalTarget={document.body}
247
+ onClickOutside={closePopover}
248
+ >
249
+ <Button onClick={togglePopover} variant="primary">
250
+ Toggle Popover
251
+ </Button>
252
+ </Popover>
253
+ </Box>
254
+ );
255
+ };
256
+
257
+ export const HoverTrigger = () => {
258
+ const {
259
+ isOpen: isPopoverOpen,
260
+ handleClose: closePopover,
261
+ handleOpen: openPopover,
262
+ } = useOpenClose();
263
+ const popoverContent = (
264
+ <>
265
+ <Heading style={{ marginBottom: '0.5rem' }}>
266
+ I just appeared on hover!
267
+ </Heading>
268
+ <p>
269
+ My visibility can easily be managed by attaching listeners to the
270
+ trigger element
271
+ </p>
272
+ </>
273
+ );
274
+ return (
275
+ <Box display="inline-block">
276
+ <Popover
277
+ content={popoverContent}
278
+ isOpen={isPopoverOpen}
279
+ placement="right-start"
280
+ contentContainerProps={{
281
+ padding: 'md',
282
+ background: 'info',
283
+ }}
284
+ >
285
+ <Button
286
+ onMouseOver={openPopover}
287
+ onMouseOut={closePopover}
288
+ variant="primary"
289
+ >
290
+ Hover Me
291
+ </Button>
292
+ </Popover>
293
+ </Box>
294
+ );
295
+ };
296
+
297
+ export const RespondToOutsideClicks = () => {
298
+ const {
299
+ isOpen: isPopoverOpen,
300
+ handleClose: closePopover,
301
+ handleToggle: togglePopover,
302
+ } = useOpenClose();
303
+ const popoverContent = (
304
+ <>
305
+ <Heading style={{ marginBottom: '0.5rem' }}>
306
+ I will close if you click outside!
307
+ </Heading>
308
+ <p>The event listener is attached to the document body.</p>
309
+ </>
310
+ );
311
+ return (
312
+ <Box display="inline-block">
313
+ <Popover
314
+ content={popoverContent}
315
+ isOpen={isPopoverOpen}
316
+ placement="right-start"
317
+ withPortal
318
+ portalTarget={document.body}
319
+ onClickOutside={closePopover}
320
+ contentContainerProps={{
321
+ padding: 'md',
322
+ background: 'success',
323
+ }}
324
+ >
325
+ <Button onClick={togglePopover} variant="primary">
326
+ Toggle Popover
327
+ </Button>
328
+ </Popover>
329
+ </Box>
330
+ );
331
+ };
332
+
333
+ export const TrappingFocus = () => {
334
+ const [inputValue, setInputValue] = useState<string>('');
335
+ const {
336
+ isOpen: isPopoverOpen,
337
+ handleClose: closePopover,
338
+ handleToggle: togglePopover,
339
+ } = useOpenClose();
340
+ const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
341
+ setInputValue(event.target.value);
342
+ };
343
+ const popoverContent = (
344
+ <>
345
+ <Box direction="column" gap="sm">
346
+ <Heading>Only the elements on this Popover can be tabbed into</Heading>
347
+ <TextInput
348
+ id="textInput"
349
+ label="Text Input"
350
+ onChange={handleInputChange}
351
+ value={inputValue}
352
+ />
353
+ <Button>Submit</Button>
354
+ </Box>
355
+ </>
356
+ );
357
+ return (
358
+ <Box display="inline-block">
359
+ <Popover
360
+ content={popoverContent}
361
+ isOpen={isPopoverOpen}
362
+ placement="right-start"
363
+ contentContainerProps={{
364
+ padding: 'md',
365
+ background: 'primary',
366
+ }}
367
+ withPortal
368
+ portalTarget={document.body}
369
+ onClickOutside={closePopover}
370
+ trapFocus
371
+ >
372
+ <Button onClick={togglePopover} variant="primary">
373
+ Toggle Popover
374
+ </Button>
375
+ </Popover>
376
+ </Box>
377
+ );
378
+ };
379
+
380
+ export const WithoutAnArrow = () => {
381
+ const {
382
+ isOpen: isPopoverOpen,
383
+ handleToggle: togglePopover,
384
+ handleClose: closePopover,
385
+ } = useOpenClose();
386
+ const popoverContent = (
387
+ <>
388
+ <Box direction="column" gap="sm">
389
+ <Heading>With no arrow</Heading>
390
+ <p>I am floating in space</p>
391
+ </Box>
392
+ </>
393
+ );
394
+ return (
395
+ <>
396
+ <Popover
397
+ content={popoverContent}
398
+ isOpen={isPopoverOpen}
399
+ placement="right"
400
+ contentContainerProps={{
401
+ padding: 'sm',
402
+ }}
403
+ onClickOutside={closePopover}
404
+ hasArrow={false}
405
+ >
406
+ <Button onClick={togglePopover} variant="primary">
407
+ Toggle Popover
408
+ </Button>
409
+ </Popover>
410
+ </>
411
+ );
412
+ };
413
+
414
+ export const OffsetDistance = () => {
415
+ const [offset, setOffset] = useState<number>(12);
416
+ const { isOpen: isPopoverOpen, handleToggle: togglePopover } = useOpenClose();
417
+
418
+ const popoverContent = (
419
+ <>
420
+ <Box direction="column" gap="sm">
421
+ <Heading>Custom Offset</Heading>
422
+ <p>Near, far, wherever your are...</p>
423
+ </Box>
424
+ </>
425
+ );
426
+ return (
427
+ <>
428
+ <Box display="inline-block">
429
+ <Popover
430
+ content={popoverContent}
431
+ isOpen={isPopoverOpen}
432
+ placement="right-start"
433
+ contentContainerProps={{
434
+ padding: 'md',
435
+ background: 'secondary',
436
+ }}
437
+ withPortal
438
+ portalTarget={document.body}
439
+ hasArrow={false}
440
+ offsetFromTarget={offset}
441
+ >
442
+ <Button onClick={togglePopover} variant="primary">
443
+ Toggle Popover
444
+ </Button>
445
+ </Popover>
446
+ </Box>
447
+ <Box margin="2xl 0 0 0" maxWidth="300px">
448
+ <label
449
+ htmlFor="offset"
450
+ style={{ fontWeight: 'bold', marginBottom: '0.25rem' }}
451
+ >
452
+ Offset
453
+ </label>
454
+ <input
455
+ type="range"
456
+ id="offset"
457
+ name="offset"
458
+ min="0"
459
+ max="24"
460
+ step="1"
461
+ value={offset}
462
+ onChange={(event) => {
463
+ setOffset(event.target.value as unknown as number);
464
+ }}
465
+ style={{ marginBottom: '0.25rem' }}
466
+ />
467
+ <span style={{ display: 'inline' }}>Value: {offset}</span>
468
+ </Box>
469
+ </>
470
+ );
471
+ };