@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,83 @@
|
|
|
1
|
+
import React, { FC } from 'react';
|
|
2
|
+
import { SelectInput, SelectInputProps } from '../SelectInput/SelectInput';
|
|
3
|
+
|
|
4
|
+
export type TimePickerProps = Omit<SelectInputProps, 'options'> & {
|
|
5
|
+
/**
|
|
6
|
+
* Options to govern the display of the option labels in the select.
|
|
7
|
+
* This is a direct passthrough to the second argument of JS `toLocaleTimeString`.
|
|
8
|
+
* [More](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString)
|
|
9
|
+
*/
|
|
10
|
+
dateDisplayOptions?: Intl.DateTimeFormatOptions;
|
|
11
|
+
/**
|
|
12
|
+
* End hour and minute
|
|
13
|
+
*/
|
|
14
|
+
endTime?: { hour: number; minute: number };
|
|
15
|
+
/**
|
|
16
|
+
* Interval of displayed times (in seconds). Defaults to 900 seconds (15 minutes).
|
|
17
|
+
*/
|
|
18
|
+
interval?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Locale(s) to be passed down in order to format the label values in the select.
|
|
21
|
+
* This corresponds to the first argument of JS `toLocaleTimeString`.
|
|
22
|
+
* [More](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString)
|
|
23
|
+
*/
|
|
24
|
+
locales?: string | string[];
|
|
25
|
+
/**
|
|
26
|
+
* Start hour and minute
|
|
27
|
+
*/
|
|
28
|
+
startTime?: { hour: number; minute: number };
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const TimePicker: FC<TimePickerProps> = ({
|
|
32
|
+
id,
|
|
33
|
+
name,
|
|
34
|
+
label,
|
|
35
|
+
onChange,
|
|
36
|
+
value,
|
|
37
|
+
dateDisplayOptions = { hour: '2-digit', minute: '2-digit' },
|
|
38
|
+
endTime = undefined,
|
|
39
|
+
interval = 900,
|
|
40
|
+
locales = 'en-US',
|
|
41
|
+
placeholder = 'HH:MM',
|
|
42
|
+
startTime = undefined,
|
|
43
|
+
...restProps
|
|
44
|
+
}) => {
|
|
45
|
+
const generateTimes = () => {
|
|
46
|
+
const first = new Date();
|
|
47
|
+
first.setHours(startTime?.hour || 0, startTime?.minute || 0, 0, 0);
|
|
48
|
+
|
|
49
|
+
const last = new Date();
|
|
50
|
+
last.setHours(
|
|
51
|
+
endTime?.hour || first.getHours() + 24,
|
|
52
|
+
endTime?.minute || 0,
|
|
53
|
+
0,
|
|
54
|
+
0
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const timeOptions = [];
|
|
58
|
+
const currentTime: Date = new Date(first);
|
|
59
|
+
|
|
60
|
+
while (currentTime < last) {
|
|
61
|
+
timeOptions.push({
|
|
62
|
+
value: currentTime.toISOString(),
|
|
63
|
+
label: currentTime.toLocaleTimeString(locales, dateDisplayOptions),
|
|
64
|
+
});
|
|
65
|
+
currentTime.setSeconds(first.getSeconds() + interval);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return timeOptions;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<SelectInput
|
|
73
|
+
{...restProps}
|
|
74
|
+
id={id}
|
|
75
|
+
name={name}
|
|
76
|
+
label={label}
|
|
77
|
+
onChange={onChange}
|
|
78
|
+
options={generateTimes()}
|
|
79
|
+
placeholder={placeholder}
|
|
80
|
+
value={value}
|
|
81
|
+
/>
|
|
82
|
+
);
|
|
83
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Canvas, Meta, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import { TimePickerNative } from './TimePickerNative';
|
|
3
|
+
import * as Stories from './TimePickerNative.stories';
|
|
4
|
+
|
|
5
|
+
<Meta of={Stories} />
|
|
6
|
+
|
|
7
|
+
# TimePickerNative
|
|
8
|
+
|
|
9
|
+
Use a TimePickerNative when you want users to select from a list of a available times agnostic of date.
|
|
10
|
+
|
|
11
|
+
_NOTE:_ This component is abstracted from the [SelectInputNative](?path=/docs/components-selectinputnative-overview--default-story)
|
|
12
|
+
and as such includes the same underlying props interface with an added method for generating the time options automatically.
|
|
13
|
+
|
|
14
|
+
_ABOUT TIME FORMAT:_ The value returned will always be a JS ISO date string, like this: `2016-07-13T18:46:01.933Z`.
|
|
15
|
+
|
|
16
|
+
## Props
|
|
17
|
+
|
|
18
|
+
<ArgTypes of={TimePickerNative} />
|
|
19
|
+
|
|
20
|
+
## Default
|
|
21
|
+
|
|
22
|
+
<Canvas of={Stories.Default} />
|
|
23
|
+
|
|
24
|
+
## With A Specific Interval
|
|
25
|
+
|
|
26
|
+
Pass an `interval` (seconds) value to determine how many times get generated as options.
|
|
27
|
+
The example below uses `3600` --> 1 Hour Intervals
|
|
28
|
+
|
|
29
|
+
<Canvas of={Stories.WithASpecificInterval} />
|
|
30
|
+
|
|
31
|
+
## With Min and Max Times
|
|
32
|
+
|
|
33
|
+
You can determine the range of times to be shown by capping the start and end times.
|
|
34
|
+
Use `startTime` and `endTime` for this. The expected values for `hour` and `minute` properties
|
|
35
|
+
are `0-24` and `0-60` respectively.
|
|
36
|
+
|
|
37
|
+
IMPORTANT: `startTime` is inclusive, and `endTime` is exclusive. This is to avoid
|
|
38
|
+
the options showing the startTime twice when using a 24-hour cycle.
|
|
39
|
+
|
|
40
|
+
See example below where we want to show 15 minute increments starting at 9:00AM and ending at 3:30PM.
|
|
41
|
+
|
|
42
|
+
<Canvas of={Stories.WithMinAndMaxTimes} />
|
|
43
|
+
|
|
44
|
+
## With Custom Date Display
|
|
45
|
+
|
|
46
|
+
The labels for the dropdwon options are governed by JS `toLocaleTimeString`, and as such
|
|
47
|
+
options are available to customize these.
|
|
48
|
+
|
|
49
|
+
NOTE: that the option values are always returned as ISO strings regardless of the label display option.
|
|
50
|
+
|
|
51
|
+
The example below is shown in military (24-hour) time.
|
|
52
|
+
|
|
53
|
+
<Canvas of={Stories.WithCustomDateDisplay} />
|
|
54
|
+
|
|
55
|
+
## Help Text
|
|
56
|
+
|
|
57
|
+
<Canvas of={Stories.HelpText} />
|
|
58
|
+
|
|
59
|
+
## Sizes
|
|
60
|
+
|
|
61
|
+
Set the size of the input to `sm`, `md` or `lg`. `md` is the default size.
|
|
62
|
+
|
|
63
|
+
<Canvas of={Stories.Sizes} />
|
|
64
|
+
|
|
65
|
+
## Component Design Tokens
|
|
66
|
+
|
|
67
|
+
This component shares component design tokens with all form controls. For a complete list of tokens, see the [Theming Form Controls documentation](/docs/theming-form-controls--custom-theme-form).
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import type { Meta } from '@storybook/react';
|
|
2
|
+
import React, { ChangeEvent, useState } from 'react';
|
|
3
|
+
import { TimePickerNative } from './TimePickerNative';
|
|
4
|
+
import { Box } from '../Box/Box';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof TimePickerNative> = {
|
|
7
|
+
title: 'Components/TimePickerNative',
|
|
8
|
+
component: TimePickerNative,
|
|
9
|
+
parameters: {
|
|
10
|
+
controls: { hideNoControlsWarning: true },
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
|
|
16
|
+
export const Default = () => {
|
|
17
|
+
const [value, setValue] = useState<string | null>(null);
|
|
18
|
+
return (
|
|
19
|
+
<Box>
|
|
20
|
+
<TimePickerNative
|
|
21
|
+
id="defaultTimePickerNative"
|
|
22
|
+
name="defaultTimePickerNative"
|
|
23
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
24
|
+
console.log(event.target.value);
|
|
25
|
+
setValue(event.target.value);
|
|
26
|
+
}}
|
|
27
|
+
label="Pick a Time"
|
|
28
|
+
value={value}
|
|
29
|
+
/>
|
|
30
|
+
</Box>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const WithASpecificInterval = () => {
|
|
35
|
+
const [value, setValue] = useState<string | null>(null);
|
|
36
|
+
return (
|
|
37
|
+
<Box>
|
|
38
|
+
<TimePickerNative
|
|
39
|
+
id="intervalTimePickerNative"
|
|
40
|
+
name="intervalTimePickerNative"
|
|
41
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) =>
|
|
42
|
+
setValue(event.target.value)
|
|
43
|
+
}
|
|
44
|
+
value={value}
|
|
45
|
+
label="Pick a Time"
|
|
46
|
+
interval={3600}
|
|
47
|
+
/>
|
|
48
|
+
</Box>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const WithMinAndMaxTimes = () => {
|
|
53
|
+
const [value, setValue] = useState<string | null>(null);
|
|
54
|
+
return (
|
|
55
|
+
<Box>
|
|
56
|
+
<TimePickerNative
|
|
57
|
+
id="startEnd"
|
|
58
|
+
name="startEnd"
|
|
59
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) =>
|
|
60
|
+
setValue(event.target.value)
|
|
61
|
+
}
|
|
62
|
+
value={value}
|
|
63
|
+
label="Pick a Time"
|
|
64
|
+
startTime={{ hour: 9, minute: 0 }}
|
|
65
|
+
endTime={{ hour: 15, minute: 31 }}
|
|
66
|
+
/>
|
|
67
|
+
</Box>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const WithCustomDateDisplay = () => {
|
|
72
|
+
const [value, setValue] = useState<string | null>(null);
|
|
73
|
+
return (
|
|
74
|
+
<Box>
|
|
75
|
+
<TimePickerNative
|
|
76
|
+
id="customDate"
|
|
77
|
+
name="customDate"
|
|
78
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) =>
|
|
79
|
+
setValue(event.target.value)
|
|
80
|
+
}
|
|
81
|
+
value={value}
|
|
82
|
+
label="Pick a Time"
|
|
83
|
+
startTime={{ hour: 9, minute: 0 }}
|
|
84
|
+
endTime={{ hour: 15, minute: 31 }}
|
|
85
|
+
dateDisplayOptions={{
|
|
86
|
+
hour12: false,
|
|
87
|
+
hour: '2-digit',
|
|
88
|
+
minute: '2-digit',
|
|
89
|
+
}}
|
|
90
|
+
/>
|
|
91
|
+
</Box>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const HelpText = () => {
|
|
96
|
+
const [value, setValue] = useState<string | null>(null);
|
|
97
|
+
return (
|
|
98
|
+
<Box>
|
|
99
|
+
<TimePickerNative
|
|
100
|
+
id="helpText"
|
|
101
|
+
name="helpText"
|
|
102
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
103
|
+
setValue(event.target.value);
|
|
104
|
+
}}
|
|
105
|
+
label="Pick a Time"
|
|
106
|
+
value={value}
|
|
107
|
+
helpText="pick a time, any time..."
|
|
108
|
+
/>
|
|
109
|
+
</Box>
|
|
110
|
+
);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export const Sizes = () => {
|
|
114
|
+
const [value, setValue] = useState<string | null>(null);
|
|
115
|
+
const [value1, setValue1] = useState<string | null>(null);
|
|
116
|
+
const [value2, setValue2] = useState<string | null>(null);
|
|
117
|
+
return (
|
|
118
|
+
<Box gap="md">
|
|
119
|
+
<TimePickerNative
|
|
120
|
+
id="smTimePickerNative"
|
|
121
|
+
name="smTimePickerNative"
|
|
122
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
123
|
+
setValue(event.target.value);
|
|
124
|
+
}}
|
|
125
|
+
label="Small"
|
|
126
|
+
value={value}
|
|
127
|
+
size="sm"
|
|
128
|
+
/>
|
|
129
|
+
<TimePickerNative
|
|
130
|
+
id="mdTimePickerNative"
|
|
131
|
+
name="mdTimePickerNative"
|
|
132
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
133
|
+
setValue1(event.target.value);
|
|
134
|
+
}}
|
|
135
|
+
label="Medium"
|
|
136
|
+
value={value1}
|
|
137
|
+
size="md"
|
|
138
|
+
/>
|
|
139
|
+
<TimePickerNative
|
|
140
|
+
id="lgTimePickerNative"
|
|
141
|
+
name="lgTimePickerNative"
|
|
142
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
143
|
+
setValue2(event.target.value);
|
|
144
|
+
}}
|
|
145
|
+
label="Large"
|
|
146
|
+
value={value2}
|
|
147
|
+
size="lg"
|
|
148
|
+
/>
|
|
149
|
+
</Box>
|
|
150
|
+
);
|
|
151
|
+
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { screen, render, fireEvent } from '@testing-library/react';
|
|
3
|
+
import { TimePickerNative } from './TimePickerNative';
|
|
4
|
+
|
|
5
|
+
describe('TimePickerNative', () => {
|
|
6
|
+
describe('Default', () => {
|
|
7
|
+
it('Renders a TimePickerNative (select) with default props', () => {
|
|
8
|
+
render(
|
|
9
|
+
<TimePickerNative
|
|
10
|
+
name="timePicker"
|
|
11
|
+
id="timePicker"
|
|
12
|
+
onChange={() => null}
|
|
13
|
+
value={null}
|
|
14
|
+
label="Select Time"
|
|
15
|
+
/>
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const timePicker = screen.getByLabelText('Select Time');
|
|
19
|
+
|
|
20
|
+
const expectedTimes = [
|
|
21
|
+
'12:00 AM',
|
|
22
|
+
'12:15 AM',
|
|
23
|
+
'12:30 AM',
|
|
24
|
+
'12:45 AM',
|
|
25
|
+
'01:00 AM',
|
|
26
|
+
'01:15 AM',
|
|
27
|
+
];
|
|
28
|
+
expect(timePicker).toBeInTheDocument();
|
|
29
|
+
expectedTimes.forEach((time) => {
|
|
30
|
+
expect(screen.queryByText(time)).toBeInTheDocument();
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('Min/Max & Interval', () => {
|
|
36
|
+
it('Renders correct options based on interval and start end times.', () => {
|
|
37
|
+
render(
|
|
38
|
+
<TimePickerNative
|
|
39
|
+
name="timePicker"
|
|
40
|
+
id="timePicker"
|
|
41
|
+
onChange={() => null}
|
|
42
|
+
value={null}
|
|
43
|
+
label="Select Time"
|
|
44
|
+
interval={3600}
|
|
45
|
+
startTime={{ hour: 9, minute: 0 }}
|
|
46
|
+
endTime={{ hour: 12, minute: 0 }}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const timePicker = screen.getByLabelText('Select Time');
|
|
51
|
+
|
|
52
|
+
const expectedTimes = ['09:00 AM', '10:00 AM', '11:00 AM'];
|
|
53
|
+
|
|
54
|
+
const notExpected = ['12:00 PM', '12:45 AM', '01:00 AM', '01:15 AM'];
|
|
55
|
+
expect(timePicker).toBeInTheDocument();
|
|
56
|
+
expectedTimes.forEach((time) => {
|
|
57
|
+
expect(screen.queryByText(time)).toBeInTheDocument();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
notExpected.forEach((time) => {
|
|
61
|
+
expect(screen.queryByText(time)).toBe(null);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('Custom Date Display', () => {
|
|
67
|
+
it('renders the times based on the options provided', () => {
|
|
68
|
+
render(
|
|
69
|
+
<TimePickerNative
|
|
70
|
+
name="timePicker"
|
|
71
|
+
id="timePicker"
|
|
72
|
+
onChange={() => null}
|
|
73
|
+
value={null}
|
|
74
|
+
label="Select Time"
|
|
75
|
+
dateDisplayOptions={{ hour12: false }}
|
|
76
|
+
startTime={{ hour: 13, minute: 0 }}
|
|
77
|
+
endTime={{ hour: 15, minute: 1 }}
|
|
78
|
+
interval={3600}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const timePicker = screen.getByLabelText('Select Time');
|
|
83
|
+
|
|
84
|
+
const expectedTimes = ['13:00:00', '14:00:00', '15:00:00'];
|
|
85
|
+
expect(timePicker).toBeInTheDocument();
|
|
86
|
+
expectedTimes.forEach((time) => {
|
|
87
|
+
expect(screen.queryByText(time)).toBeInTheDocument();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('Callback Handling', () => {
|
|
93
|
+
it('it fires an onchange callback with the correct value', async () => {
|
|
94
|
+
const mockedHandleChange = jest.fn(() => {}); // eslint-disable-line
|
|
95
|
+
|
|
96
|
+
render(
|
|
97
|
+
<TimePickerNative
|
|
98
|
+
name="timePicker"
|
|
99
|
+
id="timePicker"
|
|
100
|
+
onChange={mockedHandleChange}
|
|
101
|
+
value={null}
|
|
102
|
+
label="Select Time"
|
|
103
|
+
dateDisplayOptions={{ hour12: false }}
|
|
104
|
+
startTime={{ hour: 13, minute: 0 }}
|
|
105
|
+
endTime={{ hour: 15, minute: 1 }}
|
|
106
|
+
interval={3600}
|
|
107
|
+
/>
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const timePicker = screen.getByLabelText('Select Time');
|
|
111
|
+
|
|
112
|
+
fireEvent.change(timePicker, { target: { value: 'hello' } });
|
|
113
|
+
|
|
114
|
+
expect(mockedHandleChange).toBeCalledTimes(1);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React, { FC } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
SelectInputNative,
|
|
4
|
+
SelectInputNativeProps,
|
|
5
|
+
} from '../SelectInputNative/SelectInputNative';
|
|
6
|
+
|
|
7
|
+
export interface TimePickerNativeProps
|
|
8
|
+
extends Omit<SelectInputNativeProps, 'options'> {
|
|
9
|
+
/**
|
|
10
|
+
* Options to govern the display of the option labels in the select.
|
|
11
|
+
* This is a direct passthrough to the second argument of JS `toLocaleTimeString`.
|
|
12
|
+
* [More](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString)
|
|
13
|
+
*/
|
|
14
|
+
dateDisplayOptions?: Intl.DateTimeFormatOptions;
|
|
15
|
+
/**
|
|
16
|
+
* End hour and minute
|
|
17
|
+
*/
|
|
18
|
+
endTime?: { hour: number; minute: number };
|
|
19
|
+
/**
|
|
20
|
+
* Interval of displayed times (in seconds). Defaults to 900 seconds (15 minutes).
|
|
21
|
+
*/
|
|
22
|
+
interval?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Locale(s) to be passed down in order to format the label values in the select.
|
|
25
|
+
* This corresponds to the first argument of JS `toLocaleTimeString`.
|
|
26
|
+
* [More](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString)
|
|
27
|
+
*/
|
|
28
|
+
locales?: string | string[];
|
|
29
|
+
/**
|
|
30
|
+
* Start hour and minute
|
|
31
|
+
*/
|
|
32
|
+
startTime?: { hour: number; minute: number };
|
|
33
|
+
/**
|
|
34
|
+
* Should be ISO timestamp as returned by `onChange`, and matching value of option object.
|
|
35
|
+
*/
|
|
36
|
+
value: SelectInputNativeProps['value'];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const TimePickerNative: FC<TimePickerNativeProps> = ({
|
|
40
|
+
id,
|
|
41
|
+
name,
|
|
42
|
+
label,
|
|
43
|
+
onChange,
|
|
44
|
+
value,
|
|
45
|
+
dateDisplayOptions = { hour: '2-digit', minute: '2-digit' },
|
|
46
|
+
endTime = undefined,
|
|
47
|
+
interval = 900,
|
|
48
|
+
locales = 'en-US',
|
|
49
|
+
placeholder = 'HH:MM',
|
|
50
|
+
startTime = undefined,
|
|
51
|
+
...restProps
|
|
52
|
+
}) => {
|
|
53
|
+
const generateTimes = () => {
|
|
54
|
+
const first = new Date();
|
|
55
|
+
first.setHours(startTime?.hour || 0, startTime?.minute || 0, 0, 0);
|
|
56
|
+
|
|
57
|
+
const last = new Date();
|
|
58
|
+
last.setHours(
|
|
59
|
+
endTime?.hour || first.getHours() + 24,
|
|
60
|
+
endTime?.minute || 0,
|
|
61
|
+
0,
|
|
62
|
+
0
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const timeOptions = [];
|
|
66
|
+
const currentTime: Date = new Date(first);
|
|
67
|
+
|
|
68
|
+
while (currentTime < last) {
|
|
69
|
+
timeOptions.push({
|
|
70
|
+
value: currentTime.toISOString(),
|
|
71
|
+
label: currentTime.toLocaleTimeString(locales, dateDisplayOptions),
|
|
72
|
+
});
|
|
73
|
+
currentTime.setSeconds(first.getSeconds() + interval);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return timeOptions;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const options = generateTimes();
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<SelectInputNative
|
|
83
|
+
{...restProps}
|
|
84
|
+
id={id}
|
|
85
|
+
name={name}
|
|
86
|
+
label={label}
|
|
87
|
+
onChange={onChange}
|
|
88
|
+
options={options}
|
|
89
|
+
placeholder={placeholder}
|
|
90
|
+
value={value}
|
|
91
|
+
/>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Canvas, Meta, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import { ToastContainer } from './';
|
|
3
|
+
import * as Stories from './Toast.stories';
|
|
4
|
+
|
|
5
|
+
<Meta of={Stories} />
|
|
6
|
+
|
|
7
|
+
<ToastContainer />
|
|
8
|
+
|
|
9
|
+
# Toast
|
|
10
|
+
|
|
11
|
+
Use a toast to communicate non-critical information or feedback to a user about the result of an action.
|
|
12
|
+
Typically you'd reserve toasts for non-essential notifications, since they are meant to disappear automatically
|
|
13
|
+
under normal circumstances.
|
|
14
|
+
|
|
15
|
+
## Usage Guidelines
|
|
16
|
+
|
|
17
|
+
- Keep messages short. Typically if a toast results in a multiline message, than it is too long.
|
|
18
|
+
- Avoid adding actions inside of a toast. If you include an action (other than dismiss) in a toast,
|
|
19
|
+
try and have that action available somewhere else on the page.
|
|
20
|
+
E.G: a `retry` action can also be triggered by re-submitting a form.
|
|
21
|
+
- The main exception that makes for a useful toast action is an `undo` button, which is unlikely to make sense
|
|
22
|
+
in most pages, but is a great escape hatch for a user that wants to take back an action.
|
|
23
|
+
|
|
24
|
+
### Toast or Alert or Modal?
|
|
25
|
+
|
|
26
|
+
When to use Toast:
|
|
27
|
+
|
|
28
|
+
- Confirmations, success messages, and simple notifications
|
|
29
|
+
- Non-critical errors that are relevant in the moment and do not need to interrupt the user experience, such as "No internet connection"
|
|
30
|
+
|
|
31
|
+
When not to use Toast:
|
|
32
|
+
|
|
33
|
+
- Do not use toasts for error messages. Instead, use [Alert](?path=/docs/components-alert-overview--default-story) to prominently inform users of persistent errors.
|
|
34
|
+
- Do not use toasts as a blocking alert or interstitial (i.e. restrict or contextualize user actions). In these
|
|
35
|
+
cases, use a [Modal](?path=/docs/components-modal-overview--default-story).
|
|
36
|
+
|
|
37
|
+
## Content Guidelines
|
|
38
|
+
|
|
39
|
+
Keep the contents of a toast as short as possible by placing only the most important information in it. Toasts are meant to unobtrusively provide non-critical information or feedback. In general, toast messages should be:
|
|
40
|
+
|
|
41
|
+
- Short and affirmative
|
|
42
|
+
- Written in a pattern of noun + verb, such as "File saved" or "Role added".
|
|
43
|
+
|
|
44
|
+
<Canvas isExpanded of={Stories.Example} />
|
|
45
|
+
|
|
46
|
+
## Required Setup
|
|
47
|
+
|
|
48
|
+
1. Include the `<ToastContainer />` in your React app. (at the highest possible level of the DOM tree);
|
|
49
|
+
2. Create a toast anywhere in your app `toast('Hello')`.
|
|
50
|
+
|
|
51
|
+
**NOTE:** All examples of this page exclusively showcase step 2 above, as the ToastContainer is added globally on the page.
|
|
52
|
+
|
|
53
|
+
### Example
|
|
54
|
+
|
|
55
|
+
```jsx
|
|
56
|
+
// App.jsx
|
|
57
|
+
import { ToastContainer } from '@hyphen/hyphen-components';
|
|
58
|
+
|
|
59
|
+
export const App = () => {
|
|
60
|
+
<MyAppContainer>
|
|
61
|
+
<ToastContainer {/* custom props */} />
|
|
62
|
+
{/* Routes, other providers, etc */}
|
|
63
|
+
</MyAppContainer>
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// SomeAppPage.jsx
|
|
67
|
+
import { toast } from '@palmetto/palmetto-components';
|
|
68
|
+
|
|
69
|
+
export const SomeAppPage = () => {
|
|
70
|
+
<button onClick={() => toast('Hello')}>
|
|
71
|
+
gimme a toast
|
|
72
|
+
</button>
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Props (for `<ToastContainer />`)
|
|
77
|
+
|
|
78
|
+
<ArgTypes of={ToastContainer} />
|
|
79
|
+
|
|
80
|
+
## Toast Options
|
|
81
|
+
|
|
82
|
+
```jsx
|
|
83
|
+
// Example
|
|
84
|
+
toast('my toast', { duration: 3000, position: 'top-center' });
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
<Canvas of={Stories.Column} />
|
|
88
|
+
|
|
89
|
+
### Position
|
|
90
|
+
|
|
91
|
+
<Canvas isExpanded of={Stories.Position} />
|
|
92
|
+
### Duration
|
|
93
|
+
|
|
94
|
+
We've included sensible defaults for the duration of a toast before it disappears, but if you require custom duration, follow these guidelines:
|
|
95
|
+
|
|
96
|
+
1. Error toasts should likely stay on the screen
|
|
97
|
+
longer than success toasts, since they are arguably more important.
|
|
98
|
+
2. Toasts with actions, should stay on screen for at least 10 seconds.
|
|
99
|
+
3. async toasts with loading states should always included success and failure conditions,
|
|
100
|
+
to avoid an infinite spinner.
|
|
101
|
+
|
|
102
|
+
<Canvas isExpanded of={Stories.Duration} />
|
|
103
|
+
|
|
104
|
+
### Dismissible (or lack thereof)
|
|
105
|
+
|
|
106
|
+
By default, toasts are dismissible since they
|
|
107
|
+
should not hinder the user experience, but we still wish to provide a quick and easy
|
|
108
|
+
escape hatch, should a user want to clear it out of their view.
|
|
109
|
+
|
|
110
|
+
In cases where you'd like the toast to remain for a set amount of time
|
|
111
|
+
without the user being able to clear it, you can use `canDismiss: false`.
|
|
112
|
+
|
|
113
|
+
<Canvas isExpanded of={Stories.NotDismissible} />
|
|
114
|
+
|
|
115
|
+
### Programmatic Dismiss
|
|
116
|
+
|
|
117
|
+
In some cases you'll want to be able to dismiss a toast programmatically based on some other condition in the business logic.
|
|
118
|
+
For these cases, you can use `toast.dismiss`.
|
|
119
|
+
|
|
120
|
+
<Canvas isExpanded of={Stories.ProgrammaticDismiss} />
|
|
121
|
+
|
|
122
|
+
### Compact
|
|
123
|
+
|
|
124
|
+
Use the `isCompact` prop for a toast the uses less screen real estate.
|
|
125
|
+
|
|
126
|
+
<Canvas isExpanded of={Stories.Compact} />
|
|
127
|
+
|
|
128
|
+
### Toast Types
|
|
129
|
+
|
|
130
|
+
To give toasts an additional visual indication of feedback, `success`, `loading`, and `error` types add a contextual icon to the toast message.
|
|
131
|
+
|
|
132
|
+
<Canvas isExpanded of={Stories.BasicTypes} />
|
|
133
|
+
|
|
134
|
+
<Canvas isExpanded of={Stories.AdvancedTypes} />
|