From 86acc0b61c0745266db9c8c7adedb65ca96d4146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kry=C5=A1p=C3=ADn?= Date: Thu, 17 Aug 2023 17:24:38 +0200 Subject: [PATCH] Docs(web-react): Introduce new Stories for Button, Modal and Pill --- .storybook/main.ts | 1 + .storybook/preview.ts | 3 + package.json | 1 + packages/web-react/.eslintrc.js | 11 ++- .../src/components/Button/Button.stories.ts | 27 ------- .../src/components/Button/Button.stories.tsx | 35 +++++++++ .../components/Button/ButtonLink.stories.tsx | 36 ++++----- .../src/components/Button/demo/argTypes.ts | 42 ---------- .../src/components/Button/stories/args.tsx | 56 ++++++++++++++ .../src/components/Modal/Modal.stories.tsx | 76 +++++++++++++++++-- .../components/Modal/ModalBody.stories.tsx | 64 ++++++++++++++++ .../components/Modal/ModalDialog.stories.tsx | 71 +++++++++++++++++ .../components/Modal/ModalFooter.stories.tsx | 67 ++++++++++++++++ .../components/Modal/ModalHeader.stories.tsx | 67 ++++++++++++++++ .../src/components/Pill/Pill.stories.ts | 18 ----- .../src/components/Pill/Pill.stories.tsx | 47 ++++++++++++ .../src/components/Pill/demo/argTypes.ts | 11 --- packages/web-react/src/global.d.ts | 5 ++ 18 files changed, 514 insertions(+), 124 deletions(-) delete mode 100644 packages/web-react/src/components/Button/Button.stories.ts create mode 100644 packages/web-react/src/components/Button/Button.stories.tsx delete mode 100644 packages/web-react/src/components/Button/demo/argTypes.ts create mode 100644 packages/web-react/src/components/Button/stories/args.tsx create mode 100644 packages/web-react/src/components/Modal/ModalBody.stories.tsx create mode 100644 packages/web-react/src/components/Modal/ModalDialog.stories.tsx create mode 100644 packages/web-react/src/components/Modal/ModalFooter.stories.tsx create mode 100644 packages/web-react/src/components/Modal/ModalHeader.stories.tsx delete mode 100644 packages/web-react/src/components/Pill/Pill.stories.ts create mode 100644 packages/web-react/src/components/Pill/Pill.stories.tsx delete mode 100644 packages/web-react/src/components/Pill/demo/argTypes.ts diff --git a/.storybook/main.ts b/.storybook/main.ts index d31f7e3a3a..811a74d66b 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -44,6 +44,7 @@ const config: StorybookViteConfig = { docs: { autodocs: true, + defaultName: 'Overview', }, }; diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 2ab4ec6fb0..557fe105f3 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -9,6 +9,9 @@ export const parameters = { color: /(background|color)$/i, date: /Date$/, }, + expanded: true, + sort: 'alpha', + hideNoControlsWarning: true, }, docs: { theme: SpiritTheme, diff --git a/package.json b/package.json index 19947dc23b..d42346d4e0 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "@storybook/addon-links": "7.3.2", "@storybook/addon-mdx-gfm": "7.3.2", "@storybook/addons": "7.3.2", + "@storybook/blocks": "7.3.2", "@storybook/client-api": "7.3.2", "@storybook/html": "7.3.2", "@storybook/react": "7.3.2", diff --git a/packages/web-react/.eslintrc.js b/packages/web-react/.eslintrc.js index 7045509861..6c75c782de 100644 --- a/packages/web-react/.eslintrc.js +++ b/packages/web-react/.eslintrc.js @@ -25,7 +25,7 @@ module.exports = { settings: { 'import/resolver': { node: { - extensions: ['.js', '.jsx', '.ts', '.tsx'], + extensions: ['.js', '.jsx', '.ts', '.tsx', '.md', 'raw', '.md?raw'], }, }, }, @@ -63,6 +63,15 @@ module.exports = { 'no-param-reassign': ['warn', { props: false }], // support monorepos 'import/no-extraneous-dependencies': ['error', { packageDir: ['./', '../../'] }], + 'import/no-unresolved': [ + 2, + { + ignore: [ + // Ignore vite's ?raw imports + '.*?raw', + ], + }, + ], // disable double quotes quotes: ['warn', 'single'], }, diff --git a/packages/web-react/src/components/Button/Button.stories.ts b/packages/web-react/src/components/Button/Button.stories.ts deleted file mode 100644 index 9b452a5902..0000000000 --- a/packages/web-react/src/components/Button/Button.stories.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ComponentMeta } from '@storybook/react'; -import argTypes from './demo/argTypes'; -import Button from './Button'; - -export default { - title: 'Components/Button', - component: Button, - parameters: { - docs: { - description: { - component: 'Buttons allow users to take actions.', - }, - }, - }, - argTypes: { - ...argTypes, - type: { - control: { - type: 'select', - options: ['button', 'submit', 'reset'], - }, - defaultValue: 'button', - }, - }, -} as ComponentMeta; - -export { default as Button } from './demo/Button'; diff --git a/packages/web-react/src/components/Button/Button.stories.tsx b/packages/web-react/src/components/Button/Button.stories.tsx new file mode 100644 index 0000000000..1529b3f3d6 --- /dev/null +++ b/packages/web-react/src/components/Button/Button.stories.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { Markdown } from '@storybook/blocks'; +import type { Meta, StoryObj } from '@storybook/react'; + +import { Button } from './Button'; +import { args, argTypes } from './stories/args'; +import ReadMe from './README.md?raw'; + +const meta: Meta = { + title: 'Components/Button', + component: Button, + parameters: { + docs: { + page: () => {ReadMe}, + }, + }, + argTypes: { + ...argTypes, + type: { + control: 'select', + options: ['button', 'submit', 'reset'], + }, + }, + args: { + ...args, + type: 'button', + }, +}; + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + name: 'Button', +}; diff --git a/packages/web-react/src/components/Button/ButtonLink.stories.tsx b/packages/web-react/src/components/Button/ButtonLink.stories.tsx index 866d24e9eb..78a14a2523 100644 --- a/packages/web-react/src/components/Button/ButtonLink.stories.tsx +++ b/packages/web-react/src/components/Button/ButtonLink.stories.tsx @@ -1,26 +1,26 @@ -import { ComponentMeta } from '@storybook/react'; -import argTypes from './demo/argTypes'; -import ButtonLink from './ButtonLink'; +import React from 'react'; +import { Markdown } from '@storybook/blocks'; +import type { Meta, StoryObj } from '@storybook/react'; -export default { +import { ButtonLink } from './ButtonLink'; +import { args, argTypes } from './stories/args'; +import ReadMe from './README.md?raw'; + +const meta: Meta = { title: 'Components/ButtonLink', component: ButtonLink, parameters: { docs: { - description: { - component: 'ButtonLinks allow users to take actions.', - }, - }, - }, - argTypes: { - ...argTypes, - href: { - control: { - type: 'text', - }, - defaultValue: '#', + page: () => {ReadMe}, }, }, -} as ComponentMeta; + argTypes, + args, +}; + +export default meta; +type Story = StoryObj; -export { default as ButtonLink } from './demo/ButtonLink'; +export const Playground: Story = { + name: 'ButtonLink', +}; diff --git a/packages/web-react/src/components/Button/demo/argTypes.ts b/packages/web-react/src/components/Button/demo/argTypes.ts deleted file mode 100644 index 2a1d28c6c0..0000000000 --- a/packages/web-react/src/components/Button/demo/argTypes.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { ActionColors, EmotionColors, Sizes } from '../../../constants'; - -export default { - color: { - control: { - type: 'select', - options: [...Object.values(ActionColors), ...Object.values(EmotionColors)], - }, - defaultValue: ActionColors.PRIMARY, - }, - isBlock: { - control: { - type: 'boolean', - }, - defaultValue: false, - }, - isDisabled: { - control: { - type: 'boolean', - }, - defaultValue: false, - }, - isLoading: { - control: { - type: 'boolean', - }, - defaultValue: false, - }, - isSquare: { - control: { - type: 'boolean', - }, - defaultValue: false, - }, - size: { - control: { - type: 'select', - options: [...Object.values(Sizes)], - }, - defaultValue: Sizes.MEDIUM, - }, -}; diff --git a/packages/web-react/src/components/Button/stories/args.tsx b/packages/web-react/src/components/Button/stories/args.tsx new file mode 100644 index 0000000000..37f9f37fbe --- /dev/null +++ b/packages/web-react/src/components/Button/stories/args.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { ActionColors, EmotionColors, Sizes } from '../../../constants'; +import { Icon } from '../../Icon'; + +export const argTypes = { + children: { + control: 'text', + description: + 'This is the place for the content of the button. In the real code you can pass in any JSX. ' + + 'In this demo you can set any text you want, or use one of the predefined texts: `` ' + + '(to see how it looks with an Icon) or ` Text` (to see how it looks with an Icon ' + + 'and text). Please note the predefined texts in this demo are not customizable and have ' + + 'to be written exactly as shown.', + mapping: { + '': , + ' Text': ( + <> + Text + + ), + }, + }, + color: { + control: 'select', + options: [...Object.values(ActionColors), ...Object.values(EmotionColors)], + table: { + defaultValue: { summary: ActionColors.PRIMARY }, + }, + }, + isBlock: { + control: 'boolean', + }, + isDisabled: { + control: 'boolean', + }, + isLoading: { + control: 'boolean', + }, + isSquare: { + control: 'boolean', + }, + size: { + control: 'select', + options: [...Object.values(Sizes)], + }, +}; + +export const args = { + children: 'Click me', + color: ActionColors.PRIMARY, + isBlock: false, + isDisabled: false, + isLoading: false, + isSquare: false, + size: Sizes.MEDIUM, +}; diff --git a/packages/web-react/src/components/Modal/Modal.stories.tsx b/packages/web-react/src/components/Modal/Modal.stories.tsx index 8a8a16794f..d93990b0f8 100644 --- a/packages/web-react/src/components/Modal/Modal.stories.tsx +++ b/packages/web-react/src/components/Modal/Modal.stories.tsx @@ -1,16 +1,78 @@ -import { ComponentMeta } from '@storybook/react'; -import Modal from './Modal'; +import React, { useState } from 'react'; +import { Markdown } from '@storybook/blocks'; +import type { Meta, StoryObj } from '@storybook/react'; -export default { +import { SpiritModalProps } from '../../types'; +import { Button } from '../Button'; +import ReadMe from './README.md?raw'; +import { Modal, ModalHeader, ModalDialog, ModalBody, ModalFooter } from '.'; + +const meta: Meta = { title: 'Components/Modal', component: Modal, parameters: { docs: { - description: { - component: 'Add dialogs to your site for lightboxes, user notifications, or completely custom content.', + page: () => {ReadMe}, + }, + }, + argTypes: { + id: { + control: 'text', + }, + isOpen: { + control: 'boolean', + table: { + defaultValue: { summary: false }, }, }, + onClose: { + control: 'function', + }, + }, + args: { + id: 'modal', + isOpen: false, }, -} as ComponentMeta; +}; + +export default meta; +type Story = StoryObj; + +const ModalWithHooks = (args: SpiritModalProps) => { + const [isModalOpen, setModalOpen] = useState(false); + + const toggleModal = () => setModalOpen(!isModalOpen); + + const handleClose = () => { + setModalOpen(false); + }; + + const { isOpen } = args; + + return ( + <> + + + + Modal Header + Body + + + + + + + + ); +}; -export { default as Modal } from './demo/Modal'; +export const Playground: Story = { + name: 'Modal', + render: (args) => , +}; diff --git a/packages/web-react/src/components/Modal/ModalBody.stories.tsx b/packages/web-react/src/components/Modal/ModalBody.stories.tsx new file mode 100644 index 0000000000..368e3fc9ee --- /dev/null +++ b/packages/web-react/src/components/Modal/ModalBody.stories.tsx @@ -0,0 +1,64 @@ +import React, { useState } from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + +import { ModalBodyProps } from '../../types'; +import { Button } from '../Button'; +import { Modal, ModalHeader, ModalDialog, ModalBody, ModalFooter } from '.'; + +const meta: Meta = { + title: 'Components/Modal', + component: ModalBody, + argTypes: { + children: { + control: 'text', + }, + }, + args: { + children: 'Body', + }, +}; + +export default meta; +type Story = StoryObj; + +const ModalWithHooks = (args: ModalBodyProps) => { + const [isOpen, setOpen] = useState(true); + + const toggleModal = () => setOpen(!isOpen); + + const handleClose = () => { + setOpen(false); + }; + + const { children } = args; + + return ( + <> + + + + Modal Header + {children} + + + + + + + + ); +}; + +/** + * + */ +export const ModalBodyPlayground: Story = { + name: 'ModalBody', + render: (args) => , +}; diff --git a/packages/web-react/src/components/Modal/ModalDialog.stories.tsx b/packages/web-react/src/components/Modal/ModalDialog.stories.tsx new file mode 100644 index 0000000000..deafd9c4a8 --- /dev/null +++ b/packages/web-react/src/components/Modal/ModalDialog.stories.tsx @@ -0,0 +1,71 @@ +import React, { useState } from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + +import { ModalDialogProps } from '../../types'; +import { Button } from '../Button'; +import { Modal, ModalHeader, ModalDialog, ModalBody, ModalFooter } from '.'; + +const meta: Meta = { + title: 'Components/Modal', + component: ModalDialog, + argTypes: { + maxHeightFromTabletUp: { + control: 'text', + }, + preferredHeightOnMobile: { + control: 'text', + }, + preferredHeightFromTabletUp: { + control: 'text', + }, + }, + args: { + maxHeightFromTabletUp: '', + preferredHeightOnMobile: '', + preferredHeightFromTabletUp: '', + }, +}; + +export default meta; +type Story = StoryObj; + +const ModalWithHooks = ( + args: React.JSX.IntrinsicAttributes & + Omit, 'ref'> & + React.RefAttributes, +) => { + const [isOpen, setOpen] = useState(true); + + const toggleModal = () => setOpen(!isOpen); + + const handleClose = () => { + setOpen(false); + }; + + return ( + <> + + + + Modal Header + Body + + + + + + + + ); +}; + +export const ModalDialogPlayground: Story = { + name: 'ModalDialog', + render: (args) => , +}; diff --git a/packages/web-react/src/components/Modal/ModalFooter.stories.tsx b/packages/web-react/src/components/Modal/ModalFooter.stories.tsx new file mode 100644 index 0000000000..09ec405211 --- /dev/null +++ b/packages/web-react/src/components/Modal/ModalFooter.stories.tsx @@ -0,0 +1,67 @@ +import React, { useState } from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + +import { AlignmentX } from '../../constants'; +import { ModalFooterProps } from '../../types'; +import { Button } from '../Button'; +import { Modal, ModalHeader, ModalDialog, ModalBody, ModalFooter } from '.'; + +const meta: Meta = { + title: 'Components/Modal', + component: ModalFooter, + argTypes: { + alignmentX: { + control: 'select', + options: [...Object.values(AlignmentX)], + table: { + defaultValue: { summary: AlignmentX.RIGHT }, + }, + }, + children: { + control: 'text', + }, + description: { + control: 'text', + }, + }, + args: { + alignmentX: AlignmentX.RIGHT, + children: 'Footer', + description: 'Footer Description', + }, +}; + +export default meta; +type Story = StoryObj; + +const ModalWithHooks = (args: ModalFooterProps) => { + const [isOpen, setOpen] = useState(true); + + const toggleModal = () => setOpen(!isOpen); + + const handleClose = () => { + setOpen(false); + }; + + const { children } = args; + + return ( + <> + + + + Modal Header + Body + {children} + + + + ); +}; + +export const ModalFooterPlayground: Story = { + name: 'ModalFooter', + render: (args) => , +}; diff --git a/packages/web-react/src/components/Modal/ModalHeader.stories.tsx b/packages/web-react/src/components/Modal/ModalHeader.stories.tsx new file mode 100644 index 0000000000..e7ad8049d5 --- /dev/null +++ b/packages/web-react/src/components/Modal/ModalHeader.stories.tsx @@ -0,0 +1,67 @@ +import React, { useState } from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + +import { ModalHeaderProps } from '../../types'; +import { Button } from '../Button'; +import { Modal, ModalHeader, ModalDialog, ModalBody, ModalFooter } from '.'; + +const meta: Meta = { + title: 'Components/Modal', + component: ModalHeader, + argTypes: { + children: { + control: 'text', + }, + closeLabel: { + control: 'text', + table: { + defaultValue: { summary: 'Close' }, + }, + }, + }, + args: { + children: 'Modal Header', + }, +}; + +export default meta; +type Story = StoryObj; + +const ModalWithHooks = (args: ModalHeaderProps) => { + const [isOpen, setOpen] = useState(true); + + const toggleModal = () => setOpen(!isOpen); + + const handleClose = () => { + setOpen(false); + }; + + const { children } = args; + + return ( + <> + + + + {children} + Body + + + + + + + + ); +}; + +export const ModalHeaderPlayground: Story = { + name: 'ModalHeader', + render: (args) => , +}; diff --git a/packages/web-react/src/components/Pill/Pill.stories.ts b/packages/web-react/src/components/Pill/Pill.stories.ts deleted file mode 100644 index 7445737557..0000000000 --- a/packages/web-react/src/components/Pill/Pill.stories.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ComponentMeta } from '@storybook/react'; -import argTypes from './demo/argTypes'; -import Pill from './Pill'; - -export default { - title: 'Components/Pill', - component: Pill, - parameters: { - docs: { - description: { - component: 'Can be used to show count or label.', - }, - }, - }, - argTypes, -} as ComponentMeta; - -export { default as Pill } from './demo/Pill'; diff --git a/packages/web-react/src/components/Pill/Pill.stories.tsx b/packages/web-react/src/components/Pill/Pill.stories.tsx new file mode 100644 index 0000000000..fae574944d --- /dev/null +++ b/packages/web-react/src/components/Pill/Pill.stories.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { Markdown } from '@storybook/blocks'; +import type { Meta, StoryObj } from '@storybook/react'; + +import { ActionColors, EmotionColors } from '../../constants'; +import { Pill } from './Pill'; +import ReadMe from './README.md?raw'; + +const meta: Meta = { + title: 'Components/Pill', + component: Pill, + parameters: { + docs: { + page: () => {ReadMe}, + }, + }, + argTypes: { + children: { + control: 'text', + }, + color: { + control: 'select', + options: [...Object.values(ActionColors), ...Object.values(EmotionColors), 'selected', 'unselected'], + table: { + defaultValue: { summary: 'selected' }, + }, + }, + elementType: { + control: 'text', + table: { + defaultValue: { summary: 'span' }, + }, + }, + }, + args: { + children: '3', + color: 'selected', + elementType: 'span', + }, +}; + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + name: 'Pill', +}; diff --git a/packages/web-react/src/components/Pill/demo/argTypes.ts b/packages/web-react/src/components/Pill/demo/argTypes.ts deleted file mode 100644 index 74f78ea5d7..0000000000 --- a/packages/web-react/src/components/Pill/demo/argTypes.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ActionColors, EmotionColors } from '../../../constants'; - -export default { - color: { - control: { - type: 'select', - options: [...Object.values(ActionColors), ...Object.values(EmotionColors), 'selected', 'unselected'], - }, - defaultValue: 'selected', - }, -}; diff --git a/packages/web-react/src/global.d.ts b/packages/web-react/src/global.d.ts index a7386253aa..7f00d94984 100644 --- a/packages/web-react/src/global.d.ts +++ b/packages/web-react/src/global.d.ts @@ -1,3 +1,8 @@ +declare module '*.md?raw' { + const content: string; + export default content; +} + interface Window { console: Console; }