diff --git a/.storybook/preview.ts b/.storybook/preview.tsx similarity index 70% rename from .storybook/preview.ts rename to .storybook/preview.tsx index 9d75b4b27..61ab250f9 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.tsx @@ -1,5 +1,6 @@ import type { Preview } from '@storybook/react' import '../src/assets/styles/index.scss' +import DocumentationTemplate from '../src/stories/ui/DocumentationTemplate.mdx' const preview: Preview = { parameters: { @@ -9,6 +10,9 @@ const preview: Preview = { color: /(background|color)$/i, date: /Date$/ } + }, + docs: { + page: DocumentationTemplate } } } diff --git a/src/stories/Introduction.mdx b/src/stories/Introduction.mdx deleted file mode 100644 index a314fa7f4..000000000 --- a/src/stories/Introduction.mdx +++ /dev/null @@ -1,211 +0,0 @@ -import { Meta } from '@storybook/blocks'; -import Code from './assets/code-brackets.svg'; -import Colors from './assets/colors.svg'; -import Comments from './assets/comments.svg'; -import Direction from './assets/direction.svg'; -import Flow from './assets/flow.svg'; -import Plugin from './assets/plugin.svg'; -import Repo from './assets/repo.svg'; -import StackAlt from './assets/stackalt.svg'; - - - - - -# Welcome to Storybook - -Storybook helps you build UI components in isolation from your app's business logic, data, and context. -That makes it easy to develop hard-to-reach states. Save these UI states as **stories** to revisit during development, testing, or QA. - -Browse example stories now by navigating to them in the sidebar. -View their code in the `stories` directory to learn how they work. -We recommend building UIs with a [**component-driven**](https://componentdriven.org) process starting with atomic components and ending with pages. - -
Configure
- -
- - plugin - - Presets for popular tools - Easy setup for TypeScript, SCSS and more. - - - - Build - - Build configuration - How to customize webpack and Babel - - - - colors - - Styling - How to load and configure CSS libraries - - - - flow - - Data - Providers and mocking for data libraries - - -
- -
Learn
- -
- - repo - - Storybook documentation - Configure, customize, and extend - - - - direction - - In-depth guides - Best practices from leading teams - - - - code - - GitHub project - View the source and add issues - - - - comments - - Discord chat - Chat with maintainers and the community - - -
- -
- TipEdit the Markdown in{' '} - stories/Introduction.stories.mdx -
diff --git a/src/stories/ui/CanvasFixedHeight.tsx b/src/stories/ui/CanvasFixedHeight.tsx new file mode 100644 index 000000000..dc32cf84a --- /dev/null +++ b/src/stories/ui/CanvasFixedHeight.tsx @@ -0,0 +1,10 @@ +import { ReactNode } from 'react' + +interface CanvasFixedHeight { + height: number + children: ReactNode +} + +export function CanvasFixedHeight({ height, children }: CanvasFixedHeight) { + return
{children}
+} diff --git a/src/stories/ui/DocumentationTemplate.mdx b/src/stories/ui/DocumentationTemplate.mdx new file mode 100644 index 000000000..54a15bac7 --- /dev/null +++ b/src/stories/ui/DocumentationTemplate.mdx @@ -0,0 +1,16 @@ +import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks'; + + + + + +<Primary /> + +<Description /> + +## Props + +The component accepts the following inputs (props): +<Controls /> + +<Stories title="Variants" /> diff --git a/src/stories/ui/button/Button.mdx b/src/stories/ui/button/Button.mdx deleted file mode 100644 index 8c3665245..000000000 --- a/src/stories/ui/button/Button.mdx +++ /dev/null @@ -1,103 +0,0 @@ -import { Canvas, Meta, Controls } from '@storybook/blocks'; - -import * as ButtonStories from './Button.stories'; - -<Meta of={ButtonStories} /> - -# Button - -A button is a graphical control element that is used to trigger an action or event when the user clicks or taps on it. - -Buttons can be used to perform a wide variety of actions, such as submitting a form, navigating to a new page, opening -a dialog box, or initiating a process. - -<Canvas of={ButtonStories.Default} /> - -## Props - -<Controls /> - -## Usage - -### General - -Button width is set by its content. Avoid changing its width. - -## Variants - -### All variants at a glance - -<Canvas of={ButtonStories.Variants} /> - -### Primary button - -The primary button should be used for the main or most important action in the user interface. Its purpose is to -encourage users to take a specific action, such as submitting a form or initiating a new task. - -Use only one primary button. Any remaining calls to action should be represented as variants with lower emphasis. - -<Canvas of={ButtonStories.Primary} /> - -### Secondary button - -The secondary button should be used to provide additional options or actions to the user that are not as critical or -urgent as the primary action. E.g.: "Cancel" or "Skip". - -Do not use the secondary button without being accompanied by a primary button. It should be the negative or alternative -action to the primary. - -<Canvas of={ButtonStories.Secondary} /> - -### Link - -The link button should be used as a secondary or tertiary button, or as a subtle call-to-action. Its purpose is to -draw attention to the button without being overly distracting, while also providing a clear call-to-action. It looks -like a link because the usage is very similar. E.g.: "Read More" or "Learn More". - -<Canvas of={ButtonStories.Link} /> - -## Variants - -## Usage examples - -Note that unless specified, examples with multiple buttons have `withSpacing` set to true. - -### Basic (enabled, no icon) - -<Canvas of={ButtonStories.Variants} /> - -### Disabled - -<Canvas of={ButtonStories.Disabled} /> - -### No spacing - -<Canvas of={ButtonStories.NoSpacing} /> - -### With icon - -<Canvas of={ButtonStories.WithIcon} /> - -### Secondary button to cancel - -<Canvas of={ButtonStories.SecondaryAsAltOption} /> - -### Link button to learn more - -<Canvas of={ButtonStories.LinkButtonUsage} /> - -## SASS variables - -``` -$dv-primary-text-color -$dv-primary-text-shadow-color -$dv-primary-background-color -$dv-primary-background-color-disabled -$dv-primary-border-color - -$dv-secondary-text-color -$dv-secondary-text-shadow-color -$dv-secondary-background-color -$dv-secondary-background-color-disabled -$dv-secondary-border-color -``` \ No newline at end of file diff --git a/src/stories/ui/button/Button.stories.tsx b/src/stories/ui/button/Button.stories.tsx index 31200a409..631f78cd0 100644 --- a/src/stories/ui/button/Button.stories.tsx +++ b/src/stories/ui/button/Button.stories.tsx @@ -2,9 +2,47 @@ import type { Meta, StoryObj } from '@storybook/react' import { Button } from '../../../sections/ui/button/Button' import { Icon } from '../../../sections/ui/icon.enum' +/** + * ## Description + * A button is a graphical control element that is used to trigger an action or event when the user clicks or taps on it. + * + * Buttons can be used to perform a wide variety of actions, such as submitting a form, navigating to a new page, opening + * a dialog box, or initiating a process. + * + * ## Usage guidelines + * + * ### Dos + * - Button labels: + * - Concise + * - Should include a verb + * - Always include a noun if there is any room for interpretation about what the verb operates on + * - For action buttons on a page, we include an icon and text label. + * + * ### Don'ts + * + * - Button width is set by its content. Avoid changing its width. + * - Do not use a button for a text link or navigation item like breadcrumbs. + * + * ## SASS variables + * + * ``` + * $dv-primary-text-color + * $dv-primary-text-shadow-color + * $dv-primary-background-color + * $dv-primary-background-color-disabled + * $dv-primary-border-color + * + * $dv-secondary-text-color + * $dv-secondary-text-shadow-color + * $dv-secondary-background-color + * $dv-secondary-background-color-disabled + * $dv-secondary-border-color + * ``` + */ const meta: Meta<typeof Button> = { title: 'UI/Button', - component: Button + component: Button, + tags: ['autodocs'] } export default meta @@ -14,19 +52,40 @@ export const Default: Story = { render: () => <Button>Button</Button> } -export const Primary: Story = { +/** + * The primary button should be used for the main or most important action in the user interface. Its purpose is to + * encourage users to take a specific action, such as submitting a form or initiating a new task. + * + * Use only one primary button. Any remaining calls to action should be represented as variants with lower emphasis. + */ +export const PrimaryButton: Story = { render: () => <Button>Primary</Button> } -export const Secondary: Story = { +/** + * The secondary button should be used to provide additional options or actions to the user that are not as critical or + * urgent as the primary action. E.g.: "Cancel" or "Skip". + * + * Do not use the secondary button without being accompanied by a primary button. It should be the negative or alternative + * action to the primary. + */ +export const SecondaryButton: Story = { render: () => <Button variant="secondary">Secondary</Button> } -export const Link: Story = { +/** + * The link button should be used as a secondary or tertiary button, or as a subtle call-to-action. Its purpose is to + * draw attention to the button without being overly distracting, while also providing a clear call-to-action. It looks + * like a link because the usage is very similar. E.g.: "Read More" or "Learn More". + */ +export const LinkButton: Story = { render: () => <Button variant="link">Link</Button> } -export const Variants: Story = { +/** + * Note that unless specified, examples with multiple buttons have `withSpacing` set to true. + */ +export const AllVariantsAtAGlance: Story = { render: () => ( <> <Button withSpacing>Primary</Button> @@ -70,7 +129,17 @@ export const WithIcon: Story = { render: () => <Button icon={Icon.COLLECTION}>Primary</Button> } -export const SecondaryAsAltOption: Story = { +export const UseCasePrimaryButtonAsCallToAction: Story = { + name: 'Example use case: Primary button as call-to-action', + render: () => ( + <> + <Button>Publish</Button> + </> + ) +} + +export const UseCaseSecondaryButtonToCancel: Story = { + name: 'Example use case: Secondary button to cancel', render: () => ( <> <Button withSpacing>Continue</Button> @@ -81,7 +150,8 @@ export const SecondaryAsAltOption: Story = { ) } -export const LinkButtonUsage: Story = { +export const UseCaseLinkButtonToLearnMore: Story = { + name: 'Example use case: Link button to learn more', render: () => ( <> <Button withSpacing>Save</Button> diff --git a/src/stories/ui/dropdown-button/DropdownButton.mdx b/src/stories/ui/dropdown-button/DropdownButton.mdx deleted file mode 100644 index 199dc45cb..000000000 --- a/src/stories/ui/dropdown-button/DropdownButton.mdx +++ /dev/null @@ -1,45 +0,0 @@ -import { Canvas, Meta, Controls } from '@storybook/blocks'; - -import * as DropdownButtonStories from './DropdownButton.stories'; - -<Meta of={DropdownButtonStories} /> - -# Dropdown Button - -A dropdown button is a graphical user interface element that displays a list of options when it is clicked. - -Dropdown buttons can be used to present a compact and organized set of choices to the user. They are -often used in forms, search bars, navigation menus, and other user interfaces where space is limited or where the number -of options is too large to display at once. - -<Canvas of={DropdownButtonStories.Default} /> - -## Props - -<Controls /> - -## Variants - -### All variants at a glance - -<Canvas of={DropdownButtonStories.Variants} /> - -### With Icon - -<Canvas of={DropdownButtonStories.WithIcon} /> - -## SASS variables - -``` -$dv-primary-text-color -$dv-primary-text-shadow-color -$dv-primary-background-color -$dv-primary-background-color-disabled -$dv-primary-border-color - -$dv-secondary-text-color -$dv-secondary-text-shadow-color -$dv-secondary-background-color -$dv-secondary-border-color -$dv-secondary-background-color-disabled -``` \ No newline at end of file diff --git a/src/stories/ui/dropdown-button/DropdownButton.stories.tsx b/src/stories/ui/dropdown-button/DropdownButton.stories.tsx index 96fd3daa8..b3fe43492 100644 --- a/src/stories/ui/dropdown-button/DropdownButton.stories.tsx +++ b/src/stories/ui/dropdown-button/DropdownButton.stories.tsx @@ -2,35 +2,67 @@ import type { Meta, StoryObj } from '@storybook/react' import { DropdownButton } from '../../../sections/ui/dropdown-button/DropdownButton' import { DropdownButtonItem } from '../../../sections/ui/dropdown-button/dropdown-button-item/DropdownButtonItem' import { Icon } from '../../../sections/ui/icon.enum' -import { ReactNode } from 'react' +import { CanvasFixedHeight } from '../CanvasFixedHeight' + +/** + * ## Description + * A dropdown button is a graphical user interface element that displays a list of options when it is clicked. + * + * Dropdown buttons can be used to present a compact and organized set of choices to the user. They are + * often used in forms, search bars, navigation menus, and other user interfaces where space is limited or where the number + * of options is too large to display at once. + * + * ## Usage guidelines + * Use dropdowns for a list of related options and try to keep the list short. + * + * ### Dos + * - Use the dropdown as a navigation tool to goto a href related to the dropdown title + * + * ### Don'ts + * + * - Use the dropdown as a select input + * + * ## SASS variables + * + * ``` + * $dv-primary-text-color + * $dv-primary-text-shadow-color + * $dv-primary-background-color + * $dv-primary-background-color-disabled + * $dv-primary-border-color + * + * $dv-secondary-text-color + * $dv-secondary-text-shadow-color + * $dv-secondary-background-color + * $dv-secondary-border-color + * $dv-secondary-background-color-disabled + * ``` + */ const meta: Meta<typeof DropdownButton> = { title: 'UI/Dropdown Button', - component: DropdownButton + component: DropdownButton, + tags: ['autodocs'] } export default meta type Story = StoryObj<typeof DropdownButton> -const Canvas150Height = ({ children }: { children: ReactNode }) => { - return <div style={{ height: 150 }}>{children}</div> -} - export const Default: Story = { render: () => ( - <Canvas150Height> + <CanvasFixedHeight height={150}> <DropdownButton withSpacing title="Dropdown Button" id="dropdown-1"> <DropdownButtonItem href="/item-1">Item 1</DropdownButtonItem> <DropdownButtonItem href="/item-2">Item 2</DropdownButtonItem> <DropdownButtonItem href="/item-3">Item 3</DropdownButtonItem> </DropdownButton> - </Canvas150Height> + </CanvasFixedHeight> ) } -export const Variants: Story = { +export const AllVariantsAtAGlance: Story = { render: () => ( - <Canvas150Height> + <CanvasFixedHeight height={150}> <DropdownButton withSpacing title="Primary" id="dropdown-1" variant="primary"> <DropdownButtonItem href="/item-1">Item 1</DropdownButtonItem> <DropdownButtonItem href="/item-2">Item 2</DropdownButtonItem> @@ -41,13 +73,46 @@ export const Variants: Story = { <DropdownButtonItem href="/item-2">Item 2</DropdownButtonItem> <DropdownButtonItem href="/item-3">Item 3</DropdownButtonItem> </DropdownButton> - </Canvas150Height> + </CanvasFixedHeight> + ) +} + +/** + * The primary dropdown should be used for the main or most important actions in the user interface. + * + * Use only one primary dropdown. Any remaining calls to action should be represented as variants with lower emphasis. + */ +export const PrimaryDropdown: Story = { + render: () => ( + <CanvasFixedHeight height={150}> + <DropdownButton title="Primary" id="dropdown-primary" variant="primary"> + <DropdownButtonItem href="/item-1">Item 1</DropdownButtonItem> + <DropdownButtonItem href="/item-2">Item 2</DropdownButtonItem> + <DropdownButtonItem href="/item-3">Item 3</DropdownButtonItem> + </DropdownButton> + </CanvasFixedHeight> + ) +} + +/** + * The secondary dropdown should be used to provide additional options or actions to the user that are not as critical or + * urgent as the primary actions. + */ +export const SecondaryDropdown: Story = { + render: () => ( + <CanvasFixedHeight height={150}> + <DropdownButton title="Secondary" id="dropdown-secondary" variant="secondary"> + <DropdownButtonItem href="/item-1">Item 1</DropdownButtonItem> + <DropdownButtonItem href="/item-2">Item 2</DropdownButtonItem> + <DropdownButtonItem href="/item-3">Item 3</DropdownButtonItem> + </DropdownButton> + </CanvasFixedHeight> ) } export const WithIcon: Story = { render: () => ( - <Canvas150Height> + <CanvasFixedHeight height={150}> <DropdownButton withSpacing title="Dropdown Button" @@ -58,6 +123,21 @@ export const WithIcon: Story = { <DropdownButtonItem href="/item-2">Item 2</DropdownButtonItem> <DropdownButtonItem href="/item-3">Item 3</DropdownButtonItem> </DropdownButton> - </Canvas150Height> + </CanvasFixedHeight> + ) +} + +/** + * This is an example use case for a navigation dropdown button. + */ +export const UseCaseNavigation: Story = { + name: 'Example use case: Navigation', + render: () => ( + <CanvasFixedHeight height={150}> + <DropdownButton withSpacing title="Edit" id="dropdown-navigation" variant="primary"> + <DropdownButtonItem href="/users/edit">Users</DropdownButtonItem> + <DropdownButtonItem href="/products/edit">Products</DropdownButtonItem> + </DropdownButton> + </CanvasFixedHeight> ) } diff --git a/src/stories/ui/grid/Grid.stories.tsx b/src/stories/ui/grid/Grid.stories.tsx index a92a8dd72..6c575829f 100644 --- a/src/stories/ui/grid/Grid.stories.tsx +++ b/src/stories/ui/grid/Grid.stories.tsx @@ -4,10 +4,22 @@ import { WithI18next } from '../../WithI18next' import { Col } from '../../../sections/ui/grid/col/Col' import { Row } from '../../../sections/ui/grid/row/Row' +/** + * ## Description + * Grid system for the layout of the page + * It is based on a 12-column system, using Bootstrap's grid system underneath. + * + * ## Usage guidelines + * + * Bootstrap provides a responsive, fluid, 12-column grid system that we use to organize our page layouts. + * + * We use the fixed-width Container component which provides responsive widths based on media queries for the page + * layout, with a series of rows and columns for the content. + * + * The grid layout uses Col component for horizontal groups of columns, inside a Row containing component. Content + * should be placed within columns, and only columns may be immediate children of rows. + */ const meta: Meta<typeof Container> = { - /* Grid system for the layout of the page - * It is based on a 12-column system, using Bootstrap's grid system underneath. - */ tags: ['autodocs'], title: 'UI/Grid', component: Container, diff --git a/src/stories/ui/navbar/Navbar.stories.tsx b/src/stories/ui/navbar/Navbar.stories.tsx index 51b499a76..7860c6456 100644 --- a/src/stories/ui/navbar/Navbar.stories.tsx +++ b/src/stories/ui/navbar/Navbar.stories.tsx @@ -2,38 +2,79 @@ import type { Meta, StoryObj } from '@storybook/react' import { WithI18next } from '../../WithI18next' import { Navbar } from '../../../sections/ui/navbar/Navbar' import logo from '../../../sections/ui/logo.svg' +import { CanvasFixedHeight } from '../CanvasFixedHeight' +/** + * ## Description + * The navbar component is a user interface element that typically appears at the top of a website or application. Its main + * purpose is to provide users with easy access to the main sections and features of the website or application. + * + * ## Usage guidelines + * + * The text used in the component should be concise and meaningful, and the component should be organized in a logical way + * to make it easy for users to find what they are looking for. + * + * ## SASS variables + * + * ``` + * + * $dv-brand-color + * + * ``` + * + */ const meta: Meta<typeof Navbar> = { title: 'UI/Navbar', component: Navbar, - decorators: [WithI18next] + decorators: [WithI18next], + tags: ['autodocs'] } export default meta type Story = StoryObj<typeof Navbar> -export const Example: Story = { +export const Default: Story = { render: () => ( - <Navbar - brand={{ logo: { src: logo, altText: 'logo' }, title: 'Brand Title', path: '#' }} - links={[ - { title: 'Link 1 ', value: '#' }, - { title: 'Link 2', value: '#' }, - { - title: 'Dropdown 1', - value: [ - { title: 'Link 3 ', value: '#' }, - { title: 'Link 4', value: '#' } - ] - }, - { - title: 'Dropdown 2', - value: [ - { title: 'Link 5 ', value: '#' }, - { title: 'Link 6', value: '#' } - ] - } - ]} - /> + <CanvasFixedHeight height={150}> + <Navbar + brand={{ logo: { src: logo, altText: 'logo' }, title: 'Brand Title', path: '#' }} + links={[ + { title: 'Link 1 ', value: '#' }, + { title: 'Link 2', value: '#' }, + { + title: 'Dropdown 1', + value: [ + { title: 'Link 3 ', value: '#' }, + { title: 'Link 4', value: '#' } + ] + }, + { + title: 'Dropdown 2', + value: [ + { title: 'Link 5 ', value: '#' }, + { title: 'Link 6', value: '#' } + ] + } + ]} + /> + </CanvasFixedHeight> + ) +} + +/** + * This an example use case for a menu using the navbar component + */ +export const UseCaseMenu: Story = { + name: 'Example use case: Menu', + render: () => ( + <CanvasFixedHeight height={150}> + <Navbar + brand={{ logo: { src: logo, altText: 'logo' }, title: 'Dataverse', path: '#' }} + links={[ + { title: 'Sign Up', value: '#' }, + { title: 'Log In', value: '#' } + ]} + /> + </CanvasFixedHeight> ) }