@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.
- package/LICENSE +21 -0
- package/README.md +70 -0
- package/package.json +138 -0
- package/src/components/Alert/Alert.constants.ts +19 -0
- package/src/components/Alert/Alert.mdx +29 -0
- package/src/components/Alert/Alert.module.scss +74 -0
- package/src/components/Alert/Alert.stories.tsx +102 -0
- package/src/components/Alert/Alert.test.tsx +187 -0
- package/src/components/Alert/Alert.tsx +157 -0
- package/src/components/Alert/Alert.types.ts +14 -0
- package/src/components/Badge/Badge.mdx +28 -0
- package/src/components/Badge/Badge.module.scss +155 -0
- package/src/components/Badge/Badge.stories.tsx +52 -0
- package/src/components/Badge/Badge.test.tsx +74 -0
- package/src/components/Badge/Badge.tsx +70 -0
- package/src/components/Box/Box.mdx +259 -0
- package/src/components/Box/Box.module.scss +16 -0
- package/src/components/Box/Box.stories.tsx +1679 -0
- package/src/components/Box/Box.test.tsx +478 -0
- package/src/components/Box/Box.tsx +636 -0
- package/src/components/Button/Button.constants.ts +10 -0
- package/src/components/Button/Button.mdx +71 -0
- package/src/components/Button/Button.module.scss +312 -0
- package/src/components/Button/Button.stories.tsx +117 -0
- package/src/components/Button/Button.test.tsx +460 -0
- package/src/components/Button/Button.tsx +241 -0
- package/src/components/Card/Card.mdx +46 -0
- package/src/components/Card/Card.module.scss +6 -0
- package/src/components/Card/Card.stories.tsx +101 -0
- package/src/components/Card/Card.test.tsx +11 -0
- package/src/components/Card/Card.tsx +61 -0
- package/src/components/Card/components/CardFooter/CardFooter.test.tsx +11 -0
- package/src/components/Card/components/CardFooter/CardFooter.tsx +35 -0
- package/src/components/Card/components/CardHeader/CardHeader.test.tsx +23 -0
- package/src/components/Card/components/CardHeader/CardHeader.tsx +54 -0
- package/src/components/Card/components/CardSection/CardSection.test.tsx +28 -0
- package/src/components/Card/components/CardSection/CardSection.tsx +102 -0
- package/src/components/Card/components/index.ts +3 -0
- package/src/components/CheckboxInput/CheckboxInput.mdx +98 -0
- package/src/components/CheckboxInput/CheckboxInput.stories.tsx +254 -0
- package/src/components/CheckboxInput/CheckboxInput.test.tsx +436 -0
- package/src/components/CheckboxInput/CheckboxInput.tsx +171 -0
- package/src/components/CheckboxInput/components/Checkbox.module.scss +174 -0
- package/src/components/CheckboxInput/components/Checkbox.test.tsx +201 -0
- package/src/components/CheckboxInput/components/Checkbox.tsx +176 -0
- package/src/components/CheckboxInput/components/CheckboxIcon.tsx +71 -0
- package/src/components/DateInput/DateInput.mdx +61 -0
- package/src/components/DateInput/DateInput.stories.tsx +168 -0
- package/src/components/DateInput/DateInput.test.tsx +258 -0
- package/src/components/DateInput/DateInput.tsx +189 -0
- package/src/components/DatePicker/DatePicker.mdx +52 -0
- package/src/components/DatePicker/DatePicker.module.scss +603 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +199 -0
- package/src/components/DatePicker/DatePicker.test.tsx +26 -0
- package/src/components/DatePicker/DatePicker.tsx +138 -0
- package/src/components/Details/Details.mdx +30 -0
- package/src/components/Details/Details.module.scss +32 -0
- package/src/components/Details/Details.stories.tsx +38 -0
- package/src/components/Details/Details.test.tsx +189 -0
- package/src/components/Details/Details.tsx +51 -0
- package/src/components/Details/DetailsSummary.tsx +65 -0
- package/src/components/Drawer/Drawer.mdx +117 -0
- package/src/components/Drawer/Drawer.module.scss +96 -0
- package/src/components/Drawer/Drawer.stories.tsx +380 -0
- package/src/components/Drawer/Drawer.test.tsx +90 -0
- package/src/components/Drawer/Drawer.tsx +249 -0
- package/src/components/FormControl/FormControl.tsx +78 -0
- package/src/components/FormLabel/FormLabel.mdx +24 -0
- package/src/components/FormLabel/FormLabel.module.scss +19 -0
- package/src/components/FormLabel/FormLabel.stories.tsx +20 -0
- package/src/components/FormLabel/FormLabel.test.tsx +35 -0
- package/src/components/FormLabel/FormLabel.tsx +96 -0
- package/src/components/Formik/Formik.mdx +10 -0
- package/src/components/Formik/Formik.stories.tsx +307 -0
- package/src/components/Formik/FormikCheckboxInput/FormikCheckboxInput.test.tsx +172 -0
- package/src/components/Formik/FormikCheckboxInput/FormikCheckboxInput.tsx +41 -0
- package/src/components/Formik/FormikRadioGroup/FormikRadioGroup.test.tsx +205 -0
- package/src/components/Formik/FormikRadioGroup/FormikRadioGroup.tsx +37 -0
- package/src/components/Formik/FormikSelectInput/FormikSelectInput.test.tsx +210 -0
- package/src/components/Formik/FormikSelectInput/FormikSelectInput.tsx +41 -0
- package/src/components/Formik/FormikSelectInputInset/FormikSelectInputInset.test.tsx +153 -0
- package/src/components/Formik/FormikSelectInputInset/FormikSelectInputInset.tsx +44 -0
- package/src/components/Formik/FormikSelectInputNative/FormikSelectInputNative.test.tsx +161 -0
- package/src/components/Formik/FormikSelectInputNative/FormikSelectInputNative.tsx +46 -0
- package/src/components/Formik/FormikTextInput/FormikTextInput.test.tsx +176 -0
- package/src/components/Formik/FormikTextInput/FormikTextInput.tsx +38 -0
- package/src/components/Formik/FormikTextInputInset/FormikTextInputInset.test.tsx +170 -0
- package/src/components/Formik/FormikTextInputInset/FormikTextInputInset.tsx +42 -0
- package/src/components/Formik/FormikTextareaInput/FormikTextareaInput.test.tsx +186 -0
- package/src/components/Formik/FormikTextareaInput/FormikTextareaInput.tsx +42 -0
- package/src/components/Formik/FormikTextareaInputInset/FormikTextareaInputInset.test.tsx +179 -0
- package/src/components/Formik/FormikTextareaInputInset/FormikTextareaInputInset.tsx +42 -0
- package/src/components/Formik/FormikTimePicker/FormikTimePicker.test.tsx +224 -0
- package/src/components/Formik/FormikTimePicker/FormikTimePicker.tsx +37 -0
- package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.test.tsx +175 -0
- package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.tsx +38 -0
- package/src/components/Formik/FormikToggle/FormikToggle.test.tsx +172 -0
- package/src/components/Formik/FormikToggle/FormikToggle.tsx +38 -0
- package/src/components/Heading/Heading.constants.ts +19 -0
- package/src/components/Heading/Heading.mdx +35 -0
- package/src/components/Heading/Heading.module.scss +5 -0
- package/src/components/Heading/Heading.stories.tsx +90 -0
- package/src/components/Heading/Heading.test.tsx +67 -0
- package/src/components/Heading/Heading.tsx +67 -0
- package/src/components/HelpText/HelpText.module.scss +14 -0
- package/src/components/HelpText/HelpText.tsx +33 -0
- package/src/components/Icon/Icon.mdx +40 -0
- package/src/components/Icon/Icon.stories.tsx +72 -0
- package/src/components/Icon/Icon.test.tsx +30 -0
- package/src/components/Icon/Icon.tsx +61 -0
- package/src/components/InputValidationMessage/InputValidationMessage.module.scss +3 -0
- package/src/components/InputValidationMessage/InputValidationMessage.tsx +27 -0
- package/src/components/Modal/Modal.mdx +60 -0
- package/src/components/Modal/Modal.module.scss +135 -0
- package/src/components/Modal/Modal.stories.tsx +194 -0
- package/src/components/Modal/Modal.test.tsx +81 -0
- package/src/components/Modal/Modal.tsx +174 -0
- package/src/components/Modal/components/ModalBody/ModalBody.test.tsx +20 -0
- package/src/components/Modal/components/ModalBody/ModalBody.tsx +24 -0
- package/src/components/Modal/components/ModalFooter/ModalFooter.test.tsx +32 -0
- package/src/components/Modal/components/ModalFooter/ModalFooter.tsx +37 -0
- package/src/components/Modal/components/ModalHeader/ModalHeader.test.tsx +29 -0
- package/src/components/Modal/components/ModalHeader/ModalHeader.tsx +58 -0
- package/src/components/Modal/components/index.ts +5 -0
- package/src/components/Pagination/Pagination.mdx +26 -0
- package/src/components/Pagination/Pagination.stories.tsx +55 -0
- package/src/components/Pagination/Pagination.test.tsx +225 -0
- package/src/components/Pagination/Pagination.tsx +162 -0
- package/src/components/Pagination/Pagination.utilities.test.ts +133 -0
- package/src/components/Pagination/Pagination.utilities.ts +101 -0
- package/src/components/Popover/Popover.mdx +104 -0
- package/src/components/Popover/Popover.module.scss +74 -0
- package/src/components/Popover/Popover.stories.tsx +471 -0
- package/src/components/Popover/Popover.test.tsx +128 -0
- package/src/components/Popover/Popover.tsx +277 -0
- package/src/components/RadioGroup/RadioGroup.mdx +81 -0
- package/src/components/RadioGroup/RadioGroup.module.scss +23 -0
- package/src/components/RadioGroup/RadioGroup.stories.tsx +375 -0
- package/src/components/RadioGroup/RadioGroup.test.tsx +282 -0
- package/src/components/RadioGroup/RadioGroup.tsx +145 -0
- package/src/components/RadioGroup/RadioInput/RadioInput.module.scss +114 -0
- package/src/components/RadioGroup/RadioInput/RadioInput.test.tsx +156 -0
- package/src/components/RadioGroup/RadioInput/RadioInput.tsx +148 -0
- package/src/components/RadioGroup/RadioInput/RadioInputIcon.tsx +59 -0
- package/src/components/ResponsiveProvider/ResponsiveProvider.mdx +36 -0
- package/src/components/ResponsiveProvider/ResponsiveProvider.stories.tsx +54 -0
- package/src/components/ResponsiveProvider/ResponsiveProvider.test.tsx +70 -0
- package/src/components/ResponsiveProvider/ResponsiveProvider.tsx +73 -0
- package/src/components/SelectInput/SelectInput.mdx +115 -0
- package/src/components/SelectInput/SelectInput.module.scss +357 -0
- package/src/components/SelectInput/SelectInput.stories.tsx +373 -0
- package/src/components/SelectInput/SelectInput.test.tsx +403 -0
- package/src/components/SelectInput/SelectInput.tsx +245 -0
- package/src/components/SelectInputInset/SelectInputInset.mdx +56 -0
- package/src/components/SelectInputInset/SelectInputInset.module.scss +397 -0
- package/src/components/SelectInputInset/SelectInputInset.stories.tsx +189 -0
- package/src/components/SelectInputInset/SelectInputInset.test.tsx +305 -0
- package/src/components/SelectInputInset/SelectInputInset.tsx +235 -0
- package/src/components/SelectInputNative/SelectInputNative.mdx +87 -0
- package/src/components/SelectInputNative/SelectInputNative.module.scss +356 -0
- package/src/components/SelectInputNative/SelectInputNative.stories.tsx +282 -0
- package/src/components/SelectInputNative/SelectInputNative.test.tsx +341 -0
- package/src/components/SelectInputNative/SelectInputNative.tsx +121 -0
- package/src/components/Spinner/Spinner.mdx +29 -0
- package/src/components/Spinner/Spinner.module.scss +16 -0
- package/src/components/Spinner/Spinner.stories.tsx +48 -0
- package/src/components/Spinner/Spinner.test.tsx +47 -0
- package/src/components/Spinner/Spinner.tsx +116 -0
- package/src/components/Table/Table.mdx +216 -0
- package/src/components/Table/Table.module.scss +61 -0
- package/src/components/Table/Table.stories.tsx +884 -0
- package/src/components/Table/Table.test.tsx +437 -0
- package/src/components/Table/Table.tsx +171 -0
- package/src/components/Table/TableBody/TableBody.module.scss +19 -0
- package/src/components/Table/TableBody/TableBody.test.tsx +38 -0
- package/src/components/Table/TableBody/TableBody.tsx +96 -0
- package/src/components/Table/TableBody/TableBodyCell/TableBodyCell.module.scss +47 -0
- package/src/components/Table/TableBody/TableBodyCell/TableBodyCell.test.tsx +81 -0
- package/src/components/Table/TableBody/TableBodyCell/TableBodyCell.tsx +94 -0
- package/src/components/Table/TableHead/TableHead.test.tsx +20 -0
- package/src/components/Table/TableHead/TableHead.tsx +78 -0
- package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.module.scss +72 -0
- package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.test.tsx +187 -0
- package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.tsx +192 -0
- package/src/components/Table/common/TableRow/TableRow.module.scss +5 -0
- package/src/components/Table/common/TableRow/TableRow.test.tsx +52 -0
- package/src/components/Table/common/TableRow/TableRow.tsx +155 -0
- package/src/components/TextInput/TextInput.mdx +96 -0
- package/src/components/TextInput/TextInput.module.scss +405 -0
- package/src/components/TextInput/TextInput.stories.tsx +268 -0
- package/src/components/TextInput/TextInput.test.tsx +231 -0
- package/src/components/TextInput/TextInput.tsx +263 -0
- package/src/components/TextInputInset/TextInputInset.mdx +62 -0
- package/src/components/TextInputInset/TextInputInset.module.scss +418 -0
- package/src/components/TextInputInset/TextInputInset.stories.tsx +213 -0
- package/src/components/TextInputInset/TextInputInset.test.tsx +222 -0
- package/src/components/TextInputInset/TextInputInset.tsx +261 -0
- package/src/components/TextareaInput/TextareaInput.mdx +117 -0
- package/src/components/TextareaInput/TextareaInput.module.scss +275 -0
- package/src/components/TextareaInput/TextareaInput.stories.tsx +293 -0
- package/src/components/TextareaInput/TextareaInput.test.tsx +195 -0
- package/src/components/TextareaInput/TextareaInput.tsx +182 -0
- package/src/components/TextareaInputInset/TextareaInputInset.mdx +55 -0
- package/src/components/TextareaInputInset/TextareaInputInset.module.scss +337 -0
- package/src/components/TextareaInputInset/TextareaInputInset.stories.tsx +160 -0
- package/src/components/TextareaInputInset/TextareaInputInset.test.tsx +199 -0
- package/src/components/TextareaInputInset/TextareaInputInset.tsx +213 -0
- package/src/components/ThemeProvider/ThemeProvider.mdx +11 -0
- package/src/components/ThemeProvider/ThemeProvider.stories.tsx +56 -0
- package/src/components/ThemeProvider/ThemeProvider.tsx +75 -0
- package/src/components/TimePicker/TimePicker.mdx +75 -0
- package/src/components/TimePicker/TimePicker.stories.tsx +149 -0
- package/src/components/TimePicker/TimePicker.test.tsx +97 -0
- package/src/components/TimePicker/TimePicker.tsx +83 -0
- package/src/components/TimePickerNative/TimePickerNative.mdx +67 -0
- package/src/components/TimePickerNative/TimePickerNative.stories.tsx +151 -0
- package/src/components/TimePickerNative/TimePickerNative.test.tsx +117 -0
- package/src/components/TimePickerNative/TimePickerNative.tsx +93 -0
- package/src/components/Toast/Toast.mdx +134 -0
- package/src/components/Toast/Toast.store.ts +280 -0
- package/src/components/Toast/Toast.stories.tsx +283 -0
- package/src/components/Toast/Toast.test.tsx +784 -0
- package/src/components/Toast/Toast.types.ts +98 -0
- package/src/components/Toast/ToastContainer.tsx +170 -0
- package/src/components/Toast/ToastNotification.module.scss +63 -0
- package/src/components/Toast/ToastNotification.tsx +176 -0
- package/src/components/Toast/index.ts +4 -0
- package/src/components/Toast/toast.ts +102 -0
- package/src/components/Toast/useToasts.ts +102 -0
- package/src/components/Toggle/Toggle.mdx +51 -0
- package/src/components/Toggle/Toggle.module.scss +294 -0
- package/src/components/Toggle/Toggle.stories.tsx +128 -0
- package/src/components/Toggle/Toggle.test.tsx +308 -0
- package/src/components/Toggle/Toggle.tsx +184 -0
- package/src/constants/keyCodes.ts +2 -0
- package/src/docs/Brands.mdx +153 -0
- package/src/docs/Colors.mdx +158 -0
- package/src/docs/DesignTokens.mdx +415 -0
- package/src/docs/GetStarted.mdx +47 -0
- package/src/docs/intro.mdx +12 -0
- package/src/fonts/AvenirBold.otf +0 -0
- package/src/fonts/AvenirBold.woff +0 -0
- package/src/fonts/AvenirBold.woff2 +0 -0
- package/src/fonts/AvenirLight.otf +0 -0
- package/src/fonts/AvenirLight.woff +0 -0
- package/src/fonts/AvenirLight.woff2 +0 -0
- package/src/fonts/AvenirRegular.otf +0 -0
- package/src/fonts/AvenirRegular.woff +0 -0
- package/src/fonts/AvenirRegular.woff2 +0 -0
- package/src/fonts/Geist-Bold.otf +0 -0
- package/src/fonts/Geist-Bold.woff +0 -0
- package/src/fonts/Geist-Bold.woff2 +0 -0
- package/src/fonts/Geist-Medium.otf +0 -0
- package/src/fonts/Geist-Medium.woff +0 -0
- package/src/fonts/Geist-Medium.woff2 +0 -0
- package/src/fonts/Geist-Regular.otf +0 -0
- package/src/fonts/Geist-Regular.woff +0 -0
- package/src/fonts/Geist-Regular.woff2 +0 -0
- package/src/fonts/Geist-SemiBold.otf +0 -0
- package/src/fonts/Geist-SemiBold.woff +0 -0
- package/src/fonts/Geist-SemiBold.woff2 +0 -0
- package/src/fonts/GeistMono-Regular.otf +0 -0
- package/src/fonts/GeistMono-Regular.woff +0 -0
- package/src/fonts/GeistMono-Regular.woff2 +0 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useBreakpoint/useBreakpoint.mdx +26 -0
- package/src/hooks/useBreakpoint/useBreakpoint.stories.tsx +30 -0
- package/src/hooks/useBreakpoint/useBreakpoint.test.tsx +19 -0
- package/src/hooks/useBreakpoint/useBreakpoint.ts +50 -0
- package/src/hooks/useIsomorphicLayoutEffect/useIsomorphicLayouEffect.ts +5 -0
- package/src/hooks/useOpenClose/useOpenClose.mdx +15 -0
- package/src/hooks/useOpenClose/useOpenClose.stories.tsx +41 -0
- package/src/hooks/useOpenClose/useOpenClose.test.tsx +119 -0
- package/src/hooks/useOpenClose/useOpenClose.tsx +95 -0
- package/src/hooks/useWindowSize/useWindowSize.mdx +25 -0
- package/src/hooks/useWindowSize/useWindowSize.stories.tsx +35 -0
- package/src/hooks/useWindowSize/useWindowSize.ts +24 -0
- package/src/index.ts +48 -0
- package/src/lib/cssShorthandToClasses.test.ts +149 -0
- package/src/lib/cssShorthandToClasses.ts +133 -0
- package/src/lib/doesStringIncludeCssUnit.ts +6 -0
- package/src/lib/generateResponsiveClasses.test.ts +24 -0
- package/src/lib/generateResponsiveClasses.ts +30 -0
- package/src/lib/getAutoCompleteValue.test.ts +27 -0
- package/src/lib/getAutoCompleteValue.ts +12 -0
- package/src/lib/getColumnKeys.ts +27 -0
- package/src/lib/getDimensionCss.test.ts +148 -0
- package/src/lib/getDimensionCss.ts +73 -0
- package/src/lib/getElementType.test.tsx +42 -0
- package/src/lib/getElementType.ts +42 -0
- package/src/lib/getFlexCss.test.ts +122 -0
- package/src/lib/getFlexCss.ts +67 -0
- package/src/lib/index.ts +15 -0
- package/src/lib/isFunction.ts +6 -0
- package/src/lib/mergeRefs.ts +15 -0
- package/src/lib/prefersReducedMotion.ts +12 -0
- package/src/lib/react-children-utilities/filter.ts +12 -0
- package/src/lib/react-children-utilities/index.ts +1 -0
- package/src/lib/reactRouterClickHandler.ts +37 -0
- package/src/lib/resolveValue.ts +7 -0
- package/src/lib/tokens.ts +139 -0
- package/src/modes.ts +8 -0
- package/src/styles/animation.scss +152 -0
- package/src/styles/cursor.scss +43 -0
- package/src/styles/display.scss +119 -0
- package/src/styles/flex.scss +453 -0
- package/src/styles/fonts.scss +44 -0
- package/src/styles/globals/utilities.scss +4 -0
- package/src/styles/mixins.scss +14 -0
- package/src/styles/overflow.scss +41 -0
- package/src/styles/position.scss +45 -0
- package/src/styles/reset.scss +108 -0
- package/src/styles/text-align.scss +21 -0
- package/src/styles/utilities.scss +9 -0
- package/src/styles/variables/forms.scss +71 -0
- package/src/styles/variables/index.scss +3 -0
- package/src/styles/white-space.scss +21 -0
- package/src/types/index.ts +201 -0
- 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
|
+
};
|