From f6004efedb7ac40c804db3f06abf45723d9a668b Mon Sep 17 00:00:00 2001 From: Anurag Hazra Date: Thu, 5 Nov 2020 17:07:57 +0530 Subject: [PATCH] chore: storybook migrate segment, timepicker, select, toast (#137) * chore: migrated segment * chore: storybook addon typescript fix * chore: segment component types * chore: timepicker migrate * chore: wip migrate Toast * chore: use createPreviewTabs * chore: migrate toast * chore: migrate select * chore: removed comments and add MultiCheckbox component * chore: updated imports and improved toast components * chore: trying to fix build * chore: trying to fix build 2 --- .storybook/main.ts | 15 ++ scripts/create-preview-tabs.ts | 28 +++ src/segment/SegmentState.ts | 12 ++ src/segment/stories/Segment.component.tsx | 30 ++++ .../stories/{index.css => Segment.css} | 0 src/segment/stories/Segment.stories.tsx | 51 +++--- src/select/SelectState.ts | 21 +++ src/select/stories/Combobox.component.tsx | 90 ++++++++++ src/select/stories/Combobox.stories.tsx | 117 ++++-------- src/select/stories/Select.component.tsx | 71 ++++++++ src/select/stories/{style.css => Select.css} | 0 src/select/stories/Select.stories.tsx | 128 ++++--------- .../stories/TimePicker.component.tsx | 96 ++++++++++ .../stories/{index.css => TimePicker.css} | 0 src/timepicker/stories/TimePicker.stories.tsx | 133 ++++---------- .../stories/CSSAnimatedToast.stories.tsx | 68 +++++++ src/toast/stories/Demo.tsx | 169 ------------------ .../stories/ReactSpringToast.stories.tsx | 68 +++++++ ...cToast.stories.tsx => Toast.component.tsx} | 18 +- src/toast/stories/{style.css => Toast.css} | 0 src/toast/stories/Toast.stories.tsx | 68 +++++++ .../stories/ToastCSSAnimated.component.tsx | 56 ++++++ ...ies.tsx => ToastReactSpring.component.tsx} | 98 ++++------ src/toast/stories/ToastUtils.component.tsx | 85 +++++++++ 24 files changed, 883 insertions(+), 539 deletions(-) create mode 100644 src/segment/stories/Segment.component.tsx rename src/segment/stories/{index.css => Segment.css} (100%) create mode 100644 src/select/stories/Combobox.component.tsx create mode 100644 src/select/stories/Select.component.tsx rename src/select/stories/{style.css => Select.css} (100%) create mode 100644 src/timepicker/stories/TimePicker.component.tsx rename src/timepicker/stories/{index.css => TimePicker.css} (100%) create mode 100644 src/toast/stories/CSSAnimatedToast.stories.tsx delete mode 100644 src/toast/stories/Demo.tsx create mode 100644 src/toast/stories/ReactSpringToast.stories.tsx rename src/toast/stories/{BasicToast.stories.tsx => Toast.component.tsx} (79%) rename src/toast/stories/{style.css => Toast.css} (100%) create mode 100644 src/toast/stories/Toast.stories.tsx create mode 100644 src/toast/stories/ToastCSSAnimated.component.tsx rename src/toast/stories/{AnimatedToast.stories.tsx => ToastReactSpring.component.tsx} (50%) create mode 100644 src/toast/stories/ToastUtils.component.tsx diff --git a/.storybook/main.ts b/.storybook/main.ts index 4e3fe6106..562ef40c3 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,3 +1,6 @@ +const path = require("path"); +const tsconfig = path.resolve(__dirname, "../tsconfig.json"); + module.exports = { stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"], addons: [ @@ -7,4 +10,16 @@ module.exports = { "@storybook/addon-a11y", "@storybook/addon-essentials", ], + // Need to configure typescript manually otherwise addons will not infer from types + // https://github.com/storybookjs/storybook/issues/11146#issuecomment-643878741 + typescript: { + check: false, + checkOptions: { tsconfig }, + reactDocgen: "react-docgen-typescript", + reactDocgenTypescriptOptions: { + shouldExtractLiteralValuesFromEnum: true, + tsconfigPath: tsconfig, + propFilter: (prop: { name: string }) => !/^(testID)$/.test(prop.name), + }, + }, }; diff --git a/scripts/create-preview-tabs.ts b/scripts/create-preview-tabs.ts index 09e524d14..fe4ec44a0 100644 --- a/scripts/create-preview-tabs.ts +++ b/scripts/create-preview-tabs.ts @@ -1,4 +1,5 @@ import { + CodeSandboxTemplate, DEFAULT_REACT_CODESANDBOX, DEFAULT_REACTJS_CODESANDBOX, } from "storybook-addon-preview"; @@ -46,3 +47,30 @@ export function createPreviewTabs(props: Props) { return tabs; } + +const joinStrs = (strs: string[]) => { + return `[${strs.map(str => `"${str}"`).join(", ")}]`; +}; + +export const CreateToastSandbox = ({ + type = "tsx", + deps = [], +}: { + type?: string; + deps?: string[]; +}) => { + const utilTab = type === "tsx" ? "Utils.tsx" : "Utils.jsx"; + const ReactTab = type === "tsx" ? "React" : "ReactJS"; + + return new Function(` + var previews = arguments[0]; + return { + framework: "${ReactTab.toLowerCase()}", + files: { + "src/App.${type}": previews["${ReactTab}"][0], + "src/styles.css": previews["CSS"] ? previews["CSS"][0] : "", + "src/ToastUtils.component.${type}": previews["${utilTab}"] ? previews["${utilTab}"][0] : "", + }, + userDependencies: ${joinStrs(deps)}, + };`) as CodeSandboxTemplate; +}; diff --git a/src/segment/SegmentState.ts b/src/segment/SegmentState.ts index 876df80a5..240c541ea 100644 --- a/src/segment/SegmentState.ts +++ b/src/segment/SegmentState.ts @@ -46,7 +46,13 @@ const TYPE_MAPPING = { }; export interface SegmentStateProps { + /** + * segment value + */ value?: Date; + /** + * default segment value + */ defaultValue?: Date; /** * Sets formmating of date based on Intl.DateFormatOptions @@ -63,7 +69,13 @@ export interface SegmentStateProps { * */ formatOptions?: DateTimeFormatOpts; + /** + * placeholder date + */ placeholderDate?: Date; + /** + * callback to fire on value change + */ onChange?: (value: Date, ...args: any[]) => void; } diff --git a/src/segment/stories/Segment.component.tsx b/src/segment/stories/Segment.component.tsx new file mode 100644 index 000000000..1aabd96e3 --- /dev/null +++ b/src/segment/stories/Segment.component.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import { + Segment, + SegmentField, + useSegmentState, + SegmentStateProps, +} from "renderless-components"; + +interface AppProps extends SegmentStateProps {} + +export const App: React.FC = props => { + const state = useSegmentState(props); + + return ( +
+ + {state.segments.map((segment, i) => ( + + ))} + +
+ ); +}; + +export default App; diff --git a/src/segment/stories/index.css b/src/segment/stories/Segment.css similarity index 100% rename from src/segment/stories/index.css rename to src/segment/stories/Segment.css diff --git a/src/segment/stories/Segment.stories.tsx b/src/segment/stories/Segment.stories.tsx index 05da4cbb6..8af7c5e7c 100644 --- a/src/segment/stories/Segment.stories.tsx +++ b/src/segment/stories/Segment.stories.tsx @@ -1,40 +1,37 @@ +import "./Segment.css"; import * as React from "react"; -import { Meta } from "@storybook/react"; +import { Meta, Story } from "@storybook/react"; -import "./index.css"; -import { Segment } from "../Segment"; -import { SegmentField } from "../SegmentField"; -import { useSegmentState, SegmentStateProps } from "../SegmentState"; +import { App as Segment } from "./Segment.component"; +import { + segmentTemplate, + segmentTemplateJs, + segmentCssTemplate, +} from "./templates"; +import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; export default { + component: Segment, title: "Segment", + parameters: { + preview: { + preview: createPreviewTabs({ + ts: segmentTemplate, + js: segmentTemplateJs, + css: segmentCssTemplate, + }), + }, + }, } as Meta; -const SegmentSpinnerComp: React.FC = props => { - const state = useSegmentState(props); - - return ( -
- - {state.segments.map((segment, i) => ( - - ))} - -
- ); -}; +const Base: Story = args => ; export const Default = () => (
       year: "numeric", month: "2-digit", day: "2-digit", weekday: "long",
     
- ( />
timeStyle: "long", dateStyle: "short"
- ( />
timeStyle: "short", dateStyle: "long"
- ( />
timeStyle: "full", dateStyle: "full"
- ; + +export const App: React.FC = props => { + const state = useSelectState({ + ...props, + allowMultiselect: true, + selected: "india", + isCombobox: true, + }); + + return ( + + ); +}; + +export default App; diff --git a/src/select/stories/Combobox.stories.tsx b/src/select/stories/Combobox.stories.tsx index dfc3a35a9..fd308c228 100644 --- a/src/select/stories/Combobox.stories.tsx +++ b/src/select/stories/Combobox.stories.tsx @@ -1,94 +1,53 @@ import React from "react"; -import { Meta } from "@storybook/react"; +import { Meta, Story } from "@storybook/react"; +import { + selectCssTemplate, + comboboxTemplate, + comboboxTemplateJs, +} from "./templates"; +import { App as Combobox } from "./Combobox.component"; +import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; import { Select, - SelectOption, - SelectInput, SelectMenu, + SelectInput, + SelectOption, useSelectState, -} from "../"; -import "./style.css"; +} from ".."; export default { - title: "Select-Combobox", + component: Combobox, + title: "Select/Combobox", + parameters: { + preview: createPreviewTabs({ + js: comboboxTemplateJs, + ts: comboboxTemplate, + css: selectCssTemplate, + }), + }, } as Meta; -interface Country { - name: string; -} - -const countries: Country[] = [ - { name: "australia" }, - { name: "russia" }, - { name: "new zealand" }, - { name: "india" }, - { name: "california" }, - { name: "ireland" }, - { name: "indonesia" }, - { name: "chennai" }, - { name: "mexico" }, - { name: "sydney" }, - { name: "africa" }, - { name: "las vagas" }, - { name: "vietnam" }, - { name: "zimbabwe" }, +const countries = [ + { name: "australia", emoji: "🇦🇺" }, + { name: "russia", emoji: "🇷🇺" }, + { name: "new zealand", emoji: "🇳🇿" }, + { name: "india", emoji: "🇮🇳" }, + { name: "niger", emoji: "🇳🇪" }, + { name: "canada", emoji: "🇨🇦" }, + { name: "indonesia", emoji: "🇮🇩" }, + { name: "portugal", emoji: "🇵🇹" }, + { name: "norway", emoji: "🇳🇴" }, + { name: "switzerland", emoji: "🇨🇭" }, + { name: "africa", emoji: "🇨🇫" }, + { name: "colombia", emoji: "🇨🇴" }, + { name: "costa rica", emoji: "🇨🇷" }, + { name: "zimbabwe", emoji: "🇿🇼" }, ]; -export const Default: React.FC = () => { - const state = useSelectState({ - allowMultiselect: true, - selected: "india", - isCombobox: true, - }); +const Base: Story = args => ; - return ( - - ); -}; +export const Default = Base.bind({}); export const WithoutFilter: React.FC = () => { const state = useSelectState({ @@ -99,8 +58,8 @@ export const WithoutFilter: React.FC = () => { return ( console.log(value)} + > + + + {state.isPlaceholder ? "Select one.." : state.selected.join(" ")} + + + + + {countries.map(item => { + return ( + + {item.emoji} - {item.name} + + ); + })} + + + ); +}; + +export default App; diff --git a/src/select/stories/style.css b/src/select/stories/Select.css similarity index 100% rename from src/select/stories/style.css rename to src/select/stories/Select.css diff --git a/src/select/stories/Select.stories.tsx b/src/select/stories/Select.stories.tsx index b67091f32..60166bd6f 100644 --- a/src/select/stories/Select.stories.tsx +++ b/src/select/stories/Select.stories.tsx @@ -1,17 +1,32 @@ +import "./Select.css"; import React from "react"; -import { Meta } from "@storybook/react"; +import { Meta, Story } from "@storybook/react"; +import { App as Select } from "./Select.component"; import { - Select, + selectTemplate, + selectTemplateJs, + selectCssTemplate, +} from "./templates"; +import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; +import { + SelectMenu, SelectOption, SelectTrigger, - SelectMenu, useSelectState, -} from "../"; -import "./style.css"; + Select as SelectComponent, +} from ".."; export default { - title: "Select", + component: Select, + title: "Select/Basic", + parameters: { + preview: createPreviewTabs({ + js: selectTemplateJs, + ts: selectTemplate, + css: selectCssTemplate, + }), + }, } as Meta; const countries = [ @@ -31,81 +46,20 @@ const countries = [ { name: "zimbabwe", emoji: "🇿🇼" }, ]; -const SelectPicker: React.FC<{ state: any }> = ({ state }) => { - return ( - - ); -}; - -export const Default: React.FC = () => { - const state = useSelectState({}); +const Base: Story = args => console.log(value)} - > - - - {state.isPlaceholder ? "Select one.." : state.selected.join(" ")} - - - - - {countries.map(item => { - return ( - - {item.emoji} - {item.name} - - ); - })} - - +
+ console.log(value)} @@ -150,22 +104,6 @@ export const MultiSelectCheckboxes: React.FC = () => { ); })} - - ); -}; - -export const DefaultSelected: React.FC = () => { - const state = useSelectState({ selected: "india" }); - - return ; -}; - -export const Scrolling: React.FC = () => { - const state = useSelectState({ selected: "india" }); - - return ( -
- -
+ ); }; diff --git a/src/timepicker/stories/TimePicker.component.tsx b/src/timepicker/stories/TimePicker.component.tsx new file mode 100644 index 000000000..037b97171 --- /dev/null +++ b/src/timepicker/stories/TimePicker.component.tsx @@ -0,0 +1,96 @@ +import React from "react"; +import { + TimePicker, + TimePickerColumn, + TimePickerSegment, + TimePickerTrigger, + TimePickerContent, + useTimePickerState, + TimePickerColumnValue, + TimePickerSegmentField, + TimePickerStateProps, +} from "renderless-components"; + +const CalendarIcon = () => ( + +); + +interface AppProps extends TimePickerStateProps {} + +export const App: React.FC = props => { + const state = useTimePickerState(props); + + return ( + <> + +
+ + {state.segments.map((segment, i) => ( + + ))} + + + + +
+
+ + + {state.hours.map(n => { + return ( + + {n} + + ); + })} + + + {state.minutes.map((n, i) => { + return ( + + {n} + + ); + })} + + + {state.meridies.map((n, i) => { + return ( + + {n} + + ); + })} + + + + ); +}; + +export default App; diff --git a/src/timepicker/stories/index.css b/src/timepicker/stories/TimePicker.css similarity index 100% rename from src/timepicker/stories/index.css rename to src/timepicker/stories/TimePicker.css diff --git a/src/timepicker/stories/TimePicker.stories.tsx b/src/timepicker/stories/TimePicker.stories.tsx index e46731493..c56fa5af5 100644 --- a/src/timepicker/stories/TimePicker.stories.tsx +++ b/src/timepicker/stories/TimePicker.stories.tsx @@ -1,107 +1,36 @@ +import "./TimePicker.css"; import * as React from "react"; -import { Meta } from "@storybook/react"; +import { Meta, Story } from "@storybook/react"; -import "./index.css"; +import { App as TimePicker } from "./TimePicker.component"; import { - useTimePickerState, - TimePicker, - TimePickerColumn, - TimePickerColumnValue, - TimePickerContent, - TimePickerStateProps, - TimePickerTrigger, - TimePickerSegment, - TimePickerSegmentField, -} from "../index"; + timePickerTemplate, + timePickerTemplateJs, + timePickerCssTemplate, +} from "./templates"; +import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; export default { + component: TimePicker, title: "TimePicker", + parameters: { + preview: createPreviewTabs({ + ts: timePickerTemplate, + js: timePickerTemplateJs, + css: timePickerCssTemplate, + }), + }, } as Meta; -const CalendarIcon = () => ( - -); +const Base: Story = args => ; -const TimePickerComp: React.FC = props => { - const state = useTimePickerState(props); +export const Default = Base.bind({}); - return ( - <> - -
- - {state.segments.map((segment, i) => ( - - ))} - - - - -
-
- - - {state.hours.map(n => { - return ( - - {n} - - ); - })} - - - {state.minutes.map((n, i) => { - return ( - - {n} - - ); - })} - - - {state.meridies.map((n, i) => { - return ( - - {n} - - ); - })} - - - - ); +export const DefaultValue = Base.bind({}); +DefaultValue.args = { + defaultValue: "01:30", }; -export const Default = () => ; - -export const InitialDate = () => ; - export const ControllableState = () => { const [value, setValue] = React.useState("12:30:20"); @@ -113,7 +42,7 @@ export const ControllableState = () => { step="1" value={value} /> - { ); }; -export const isDisabled = () => ; +export const Disabled = Base.bind({}); +Disabled.args = { + isDisabled: true, +}; -export const isReadOnly = () => ; +export const ReadOnly = Base.bind({}); +ReadOnly.args = { + isReadOnly: true, +}; -export const autoFocus = () => ( - // eslint-disable-next-line jsx-a11y/no-autofocus - -); +export const AutoFocus = Base.bind({}); +AutoFocus.args = { + autoFocus: true, +}; diff --git a/src/toast/stories/CSSAnimatedToast.stories.tsx b/src/toast/stories/CSSAnimatedToast.stories.tsx new file mode 100644 index 000000000..d229a5e46 --- /dev/null +++ b/src/toast/stories/CSSAnimatedToast.stories.tsx @@ -0,0 +1,68 @@ +import "./Toast.css"; +import React from "react"; +import { Meta } from "@storybook/react"; + +import { + toastCssTemplate, + toastUtilsTemplate, + toastUtilsTemplateJs, + toastCssAnimatedTemplate, + toastCssAnimatedTemplateJs, +} from "./templates"; +import { App as CSSAnimatedToast } from "./ToastCSSAnimated.component"; +import { CreateToastSandbox } from "../../../scripts/create-preview-tabs"; + +const sandboxJs = CreateToastSandbox({ + type: "jsx", + deps: ["renderless-components@alpha", "react-transition-group"], +}); +const sandboxTs = CreateToastSandbox({ + type: "tsx", + deps: ["renderless-components@alpha", "react-transition-group"], +}); + +export default { + component: CSSAnimatedToast, + title: "Toast/CSSAnimatedToast", + parameters: { + preview: [ + { + tab: "ReactJS", + template: toastCssAnimatedTemplateJs, + language: "jsx", + copy: true, + codesandbox: sandboxJs, + }, + { + tab: "React", + template: toastCssAnimatedTemplate, + language: "tsx", + copy: true, + codesandbox: sandboxTs, + }, + { + tab: "CSS", + template: toastCssTemplate, + language: "css", + copy: true, + codesandbox: sandboxTs, + }, + { + tab: "Utils.tsx", + template: toastUtilsTemplate, + language: "tsx", + copy: true, + codesandbox: sandboxTs, + }, + { + tab: "Utils.jsx", + template: toastUtilsTemplateJs, + language: "jsx", + copy: true, + codesandbox: sandboxJs, + }, + ], + }, +} as Meta; + +export const Default = () => ; diff --git a/src/toast/stories/Demo.tsx b/src/toast/stories/Demo.tsx deleted file mode 100644 index 72049125b..000000000 --- a/src/toast/stories/Demo.tsx +++ /dev/null @@ -1,169 +0,0 @@ -import React from "react"; -import { useToast } from "../"; - -const randomType = (): string => { - return ["error", "warning", "success"].splice(Math.random() * 3, 1)[0]; -}; - -const SomeDeepNestedComp = () => { - const { show } = useToast(); - - return ( -
- - - - -
- ); -}; - -const PlacementDemo = () => { - const { show } = useToast(); - - return ( -
- - - - - - -
- ); -}; - -const Demo = () => { - return ( - <> - -
- - - ); -}; - -// Animation util -export const getTransform = (placement: string, pixels: number) => { - const pos = { from: "", enter: "", leave: "" }; - pos.enter = `translate(0, 0)`; - - if (placement === "bottom-center") { - pos.from = `translate(0, ${pixels}px)`; - pos.leave = `translate(0, ${pixels}px)`; - return pos; - } - if (placement === "top-center") { - pos.from = `translate(0, ${-pixels}px)`; - pos.leave = `translate(0, ${-pixels}px)`; - return pos; - } - if (["bottom-left", "top-left"].includes(placement)) { - pos.from = `translate(${-pixels}px, 0)`; - pos.leave = `translate(${-pixels}px, 0)`; - return pos; - } - if (["bottom-right", "top-right"].includes(placement)) { - pos.from = `translate(${pixels}px, 0)`; - pos.leave = `translate(${pixels}px, 0)`; - return pos; - } - - return pos; -}; - -export default Demo; diff --git a/src/toast/stories/ReactSpringToast.stories.tsx b/src/toast/stories/ReactSpringToast.stories.tsx new file mode 100644 index 000000000..ac38db670 --- /dev/null +++ b/src/toast/stories/ReactSpringToast.stories.tsx @@ -0,0 +1,68 @@ +import "./Toast.css"; +import React from "react"; +import { Meta } from "@storybook/react"; + +import { + toastCssTemplate, + toastUtilsTemplate, + toastUtilsTemplateJs, + toastReactSpringTemplate, + toastReactSpringTemplateJs, +} from "./templates"; +import { App as ReactSpringToast } from "./ToastCSSAnimated.component"; +import { CreateToastSandbox } from "../../../scripts/create-preview-tabs"; + +const sandboxJs = CreateToastSandbox({ + type: "jsx", + deps: ["renderless-components@alpha", "react-spring"], +}); +const sandboxTs = CreateToastSandbox({ + type: "tsx", + deps: ["renderless-components@alpha", "react-spring"], +}); + +export default { + component: ReactSpringToast, + title: "Toast/ReactSpringToast", + parameters: { + preview: [ + { + tab: "ReactJS", + template: toastReactSpringTemplateJs, + language: "jsx", + copy: true, + codesandbox: sandboxJs, + }, + { + tab: "React", + template: toastReactSpringTemplate, + language: "tsx", + copy: true, + codesandbox: sandboxTs, + }, + { + tab: "CSS", + template: toastCssTemplate, + language: "css", + copy: true, + codesandbox: sandboxTs, + }, + { + tab: "Utils.tsx", + template: toastUtilsTemplate, + language: "tsx", + copy: true, + codesandbox: sandboxTs, + }, + { + tab: "Utils.jsx", + template: toastUtilsTemplateJs, + language: "jsx", + copy: true, + codesandbox: sandboxJs, + }, + ], + }, +} as Meta; + +export const Default = () => ; diff --git a/src/toast/stories/BasicToast.stories.tsx b/src/toast/stories/Toast.component.tsx similarity index 79% rename from src/toast/stories/BasicToast.stories.tsx rename to src/toast/stories/Toast.component.tsx index 17ca64246..1c75af04d 100644 --- a/src/toast/stories/BasicToast.stories.tsx +++ b/src/toast/stories/Toast.component.tsx @@ -1,15 +1,9 @@ -import "./style.css"; import React from "react"; -import { Meta } from "@storybook/react"; +import { ToastProvider } from "renderless-components"; -import Demo from "./Demo"; -import { ToastProvider } from "../index"; +import { Variants, Placements } from "./ToastUtils.component"; -export default { - title: "Toast/Base", -} as Meta; - -export const Default: React.FC = () => { +export const App: React.FC = () => { return ( { }, }} > - + +
+
); }; + +export default App; diff --git a/src/toast/stories/style.css b/src/toast/stories/Toast.css similarity index 100% rename from src/toast/stories/style.css rename to src/toast/stories/Toast.css diff --git a/src/toast/stories/Toast.stories.tsx b/src/toast/stories/Toast.stories.tsx new file mode 100644 index 000000000..73768d346 --- /dev/null +++ b/src/toast/stories/Toast.stories.tsx @@ -0,0 +1,68 @@ +import "./Toast.css"; +import React from "react"; +import { Meta } from "@storybook/react"; + +import { + toastCssTemplate, + toastTemplate, + toastTemplateJs, + toastUtilsTemplate, + toastUtilsTemplateJs, +} from "./templates"; +import { App as Toast } from "./Toast.component"; +import { CreateToastSandbox } from "../../../scripts/create-preview-tabs"; + +const sandboxJs = CreateToastSandbox({ + type: "jsx", + deps: ["renderless-components@alpha"], +}); +const sandboxTs = CreateToastSandbox({ + type: "tsx", + deps: ["renderless-components@alpha"], +}); + +export default { + component: Toast, + title: "Toast/BasicToast", + parameters: { + preview: [ + { + tab: "ReactJS", + template: toastTemplateJs, + language: "jsx", + copy: true, + codesandbox: sandboxJs, + }, + { + tab: "React", + template: toastTemplate, + language: "tsx", + copy: true, + codesandbox: sandboxTs, + }, + { + tab: "CSS", + template: toastCssTemplate, + language: "css", + copy: true, + codesandbox: sandboxTs, + }, + { + tab: "Utils.tsx", + template: toastUtilsTemplate, + language: "tsx", + copy: true, + codesandbox: sandboxTs, + }, + { + tab: "Utils.jsx", + template: toastUtilsTemplateJs, + language: "jsx", + copy: true, + codesandbox: sandboxJs, + }, + ], + }, +} as Meta; + +export const Default = () => ; diff --git a/src/toast/stories/ToastCSSAnimated.component.tsx b/src/toast/stories/ToastCSSAnimated.component.tsx new file mode 100644 index 000000000..18bd6fc15 --- /dev/null +++ b/src/toast/stories/ToastCSSAnimated.component.tsx @@ -0,0 +1,56 @@ +import React from "react"; +import { CSSTransition } from "react-transition-group"; +import { ToastProvider, TToastWrapper } from "renderless-components"; + +import { Variants, Placements } from "./ToastUtils.component"; + +const CSSTransitionAnimationWrapper: TToastWrapper = ({ + isVisible, + children, +}) => { + return ( + + {children} + + ); +}; + +export const App: React.FC = () => { + return ( + { + return ( +
+ {content} +
+ ); + }, + success: ({ remove, content, id }) => { + return ( +
+ {content} +
+ ); + }, + warning: ({ remove, content, id }) => { + return ( +
+ {content} +
+ ); + }, + }} + > + +
+ +
+ ); +}; + +export default App; diff --git a/src/toast/stories/AnimatedToast.stories.tsx b/src/toast/stories/ToastReactSpring.component.tsx similarity index 50% rename from src/toast/stories/AnimatedToast.stories.tsx rename to src/toast/stories/ToastReactSpring.component.tsx index 7b041b184..36976e74b 100644 --- a/src/toast/stories/AnimatedToast.stories.tsx +++ b/src/toast/stories/ToastReactSpring.component.tsx @@ -1,62 +1,7 @@ -import "./style.css"; import React from "react"; -import { Meta } from "@storybook/react"; -import { CSSTransition } from "react-transition-group"; -import { useTransition, animated } from "react-spring"; - -import Demo, { getTransform } from "./Demo"; -import { ToastProvider, TToastWrapper } from "../index"; - -export default { - title: "Toast/Animated", -} as Meta; - -const CSSTransitionAnimationWrapper: TToastWrapper = ({ - isVisible, - children, -}) => { - return ( - - {children} - - ); -}; - -export const CSSTransitionAnimation: React.FC = () => { - return ( - { - return ( -
- {content} -
- ); - }, - success: ({ remove, content, id }) => { - return ( -
- {content} -
- ); - }, - warning: ({ remove, content, id }) => { - return ( -
- {content} -
- ); - }, - }} - > - -
- ); -}; +import { animated, useTransition } from "react-spring"; +import { ToastProvider, TToastWrapper } from "renderless-components"; +import { Variants, Placements } from "./ToastUtils.component"; const SpringAnimationWrapper: TToastWrapper = ({ placement, @@ -89,7 +34,7 @@ const SpringAnimationWrapper: TToastWrapper = ({ ); }; -export const ReactSpringAnimation: React.FC = () => { +export const App: React.FC = () => { return ( { }, }} > - + +
+
); }; + +// Animation util +export const getTransform = (placement: string, pixels: number) => { + const pos = { from: "", enter: "", leave: "" }; + pos.enter = `translate(0, 0)`; + + if (placement === "bottom-center") { + pos.from = `translate(0, ${pixels}px)`; + pos.leave = `translate(0, ${pixels}px)`; + return pos; + } + if (placement === "top-center") { + pos.from = `translate(0, ${-pixels}px)`; + pos.leave = `translate(0, ${-pixels}px)`; + return pos; + } + if (["bottom-left", "top-left"].includes(placement)) { + pos.from = `translate(${-pixels}px, 0)`; + pos.leave = `translate(${-pixels}px, 0)`; + return pos; + } + if (["bottom-right", "top-right"].includes(placement)) { + pos.from = `translate(${pixels}px, 0)`; + pos.leave = `translate(${pixels}px, 0)`; + return pos; + } + + return pos; +}; + +export default App; diff --git a/src/toast/stories/ToastUtils.component.tsx b/src/toast/stories/ToastUtils.component.tsx new file mode 100644 index 000000000..2d760ca39 --- /dev/null +++ b/src/toast/stories/ToastUtils.component.tsx @@ -0,0 +1,85 @@ +import React from "react"; +import { useToast, Placements as IPlacements } from "renderless-components"; + +const randomType = (): string => { + return ["error", "warning", "success"].splice(Math.random() * 3, 1)[0]; +}; + +export const Variants: React.FC = () => { + const { show } = useToast(); + + const variants = ["error", "success", "warning"]; + + return ( +
+ {variants.map(variant => { + return ( + + ); + })} + + +
+ ); +}; + +export const Placements: React.FC = () => { + const { show } = useToast(); + + const placements = [ + "top-left", + "top-right", + "top-center", + "bottom-left", + "bottom-right", + "bottom-center", + ]; + + return ( +
+ {placements.map(placement => { + return ( + + ); + })} +
+ ); +};