Update Storybook to v7

pull/2573/head
Jérémy Rialland 2023-04-17 15:50:04 +02:00 committed by Jérémy Rialland
parent ae7cded96e
commit c1d0ddeffb
32 changed files with 2995 additions and 6144 deletions

View File

@ -1,76 +0,0 @@
// TODO: Move to ESModule
const { loadConfigFromFile, mergeConfig } = require('vite')
const reactPlugin = require('@vitejs/plugin-react-swc')
const path = require('path')
const VitePWA = require('vite-plugin-pwa').VitePWA
const yaml = require('@rollup/plugin-yaml')
module.exports = {
stories: [
'../source/**/*.stories.mdx',
'../source/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-a11y',
],
framework: '@storybook/react',
core: {
builder: '@storybook/builder-vite',
},
features: {
// Auto title not supported when not using storyStoreV7
// See https://github.com/eirslett/storybook-builder-vite/issues/201
storyStoreV7: true,
},
typescript: (config) => ({
...config,
reactDocgenTypescriptOptions: {
...config.reactDocgenTypescriptOptions,
propFilter: (prop) => {
// Remove from controls aria-xxx props and props from react types
return (
!/aria-/.test(prop.name) &&
!/node_modules\/@types\/react/.test(prop.parent?.fileName)
)
},
},
}),
async viteFinal(config, { configType }) {
const { config: userConfig } = await loadConfigFromFile(
path.resolve(__dirname, '../vite.config.ts')
) // Keep storybook plugins in storybookPlugins
const storybookPlugins = config.plugins
config.plugins = []
const conf = mergeConfig(config, {
...userConfig,
base: configType === 'PRODUCTION' ? '/dev/storybook/' : userConfig.base,
plugins: [
// Replace @vitejs/plugin-react from storybook by ours
...storybookPlugins.filter(
(plugin) =>
!(Array.isArray(plugin) && plugin[0].name === 'vite:react-babel')
),
reactPlugin({
plugins: [['@swc/plugin-styled-components', { pure: true }]],
}),
yaml(),
VitePWA({ disable: true }),
],
})
return conf
},
managerHead: (head, { configType }) => {
if (configType === 'PRODUCTION') {
return `
${head}
<base href="/dev/storybook/">
`
}
},
}

35
site/.storybook/main.ts Normal file
View File

@ -0,0 +1,35 @@
import type { StorybookConfig } from '@storybook/react-vite'
const config: StorybookConfig = {
stories: [
'../source/**/*.stories.mdx',
'../source/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
'@storybook/addon-a11y',
],
framework: {
name: '@storybook/react-vite',
options: {},
},
typescript: {
reactDocgenTypescriptOptions: {
propFilter: (prop) => {
// Remove from controls aria-xxx props and props from react types
return (
!/aria-/.test(prop.name) &&
!(
prop.parent?.fileName &&
/node_modules\/@types\/react/.test(prop.parent.fileName)
)
)
},
},
},
}
export default config

View File

@ -1,28 +0,0 @@
import React from 'react'
import { DarkModeProvider } from '@/components/utils/DarkModeContext'
import { GlobalStyle } from '@/design-system/index'
import DesignSystemThemeProvider from '@/design-system/root'
export const decorators = [
(Story) => (
<DesignSystemThemeProvider>
<DarkModeProvider value={false}>
<GlobalStyle />
<Story />
</DarkModeProvider>
</DesignSystemThemeProvider>
),
]
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
expanded: true,
sort: 'requiredFirst',
},
}

View File

@ -0,0 +1,30 @@
import { Preview } from '@storybook/react'
import React from 'react'
import DesignSystemThemeProvider from '../source/design-system/root'
import theme from '../source/design-system/theme'
const preview: Preview = {
decorators: [
(Story, context) => (
<DesignSystemThemeProvider
forceDarkMode={
context?.globals?.backgrounds?.value ===
theme?.colors?.extended?.dark[800]
}
>
<Story />
</DesignSystemThemeProvider>
),
],
parameters: {
backgrounds: {
values: [
{ name: 'light', value: '#ffffff' },
{ name: 'dark', value: theme.colors.extended.dark[800] },
],
},
},
}
export default preview

View File

@ -45,8 +45,8 @@
"i18n:rules:translate": "node scripts/i18n/translate-rules.js",
"i18n:ui:check": "i18next -c scripts/i18n/parser.config.js && node scripts/i18n/check-missing-UI-translation.js",
"i18n:ui:translate": "rm -rf source/locales/static-analysis-fr.json && i18next -c scripts/i18n/parser.config.js && node scripts/i18n/translate-ui.js",
"storybook": "NODE_OPTIONS=--openssl-legacy-provider start-storybook -p 6006",
"build:storybook": "NODE_OPTIONS=--openssl-legacy-provider build-storybook"
"start:storybook": "storybook dev -p 6006",
"build:storybook": "storybook build"
},
"dependencies": {
"@atomik-color/component": "^1.0.17",
@ -115,14 +115,15 @@
"@rollup/plugin-replace": "^5.0.2",
"@rollup/plugin-yaml": "^4.0.1",
"@rushstack/package-deps-hash": "^3.2.64",
"@storybook/addon-a11y": "^6.5.14",
"@storybook/addon-actions": "^6.5.13",
"@storybook/addon-essentials": "^6.5.13",
"@storybook/addon-interactions": "^6.5.13",
"@storybook/addon-links": "^6.5.13",
"@storybook/builder-vite": "^0.4.2",
"@storybook/react": "^6.5.13",
"@storybook/testing-library": "^0.0.13",
"@storybook/addon-a11y": "^7.0.5",
"@storybook/addon-actions": "^7.0.5",
"@storybook/addon-essentials": "^7.0.5",
"@storybook/addon-interactions": "^7.0.5",
"@storybook/addon-links": "^7.0.5",
"@storybook/blocks": "^7.0.5",
"@storybook/react": "^7.0.5",
"@storybook/react-vite": "^7.0.5",
"@storybook/testing-library": "^0.1.0",
"@swc/plugin-styled-components": "^1.5.43",
"@types/history": "^5.0.0",
"@types/react": "^18.0.25",
@ -144,6 +145,7 @@
"rimraf": "^3.0.2",
"rollup-plugin-toml": "^1.0.0",
"serve-static": "^1.15.0",
"storybook": "^7.0.5",
"ts-morph": "^17.0.1",
"ts-node": "^10.9.1",
"typescript": "^4.9.5",

View File

@ -5,6 +5,8 @@ import { useDarkMode } from '@/hooks/useDarkMode'
import { useIsEmbedded } from '@/hooks/useIsEmbedded'
import { getItem, setItem } from '@/storage/safeLocalStorage'
// TODO: Theme and dark mode should be in design-system (https://github.com/betagouv/mon-entreprise/issues/2563)
type DarkModeContextType = [boolean, (darkMode: boolean) => void]
const persistDarkMode = (darkMode: boolean) => {

View File

@ -1,48 +1,48 @@
import { Item } from '@react-stately/collections'
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Meta, StoryObj } from '@storybook/react'
import { ComponentProps } from 'react'
import { Accordion } from '@/design-system'
import { Accordion, Item } from '@/design-system'
import { Body } from '@/design-system/typography/paragraphs'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
const meta: Meta<typeof Accordion> = {
component: Accordion,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
} as ComponentMeta<typeof Accordion>
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof Accordion> = (args) => (
<Accordion {...args}>
<Item key="lorem-ipsum" title="Lorem ipsum" hasChildItems={false}>
<Body>
Nam ipsum doloribus non. Deserunt consequatur quam consectetur odio.
Dolor eos est et omnis quas nulla repellat. Velit voluptate sequi et
voluptatibus sed dolorem dolorum.
</Body>
<Body>
Totam et reprehenderit aliquam hic dolorum ipsum. Iste et neque eos
voluptas deserunt harum. Mollitia numquam incidunt nihil laboriosam.
Error autem possimus quaerat veniam ut explicabo ut. Error esse est
reprehenderit quae dolor occaecati quas laboriosam.
</Body>
</Item>
<Item
key="eligendi-et-voluptatem"
title="Eligendi et voluptatem"
hasChildItems={false}
>
<Body>
Qui tempora tenetur eum voluptatibus sit et assumenda fuga. Temporibus
hic ut in maxime omnis esse et nam. Aliquam veritatis perferendis quia
enim dolorem molestiae. Impedit eaque optio iste. Eligendi et voluptatem
voluptate corporis perferendis.
</Body>
</Item>
</Accordion>
)
export const Basic = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Basic.args = {
defaultExpandedKeys: ['lorem-ipsum'],
}
export default meta
type Story = StoryObj<typeof Accordion>
export const Basic: Story = {
render: (args: ComponentProps<typeof Accordion>) => (
<Accordion {...args}>
<Item key="lorem-ipsum" title="Lorem ipsum" hasChildItems={false}>
<Body>
Nam ipsum doloribus non. Deserunt consequatur quam consectetur odio.
Dolor eos est et omnis quas nulla repellat. Velit voluptate sequi et
voluptatibus sed dolorem dolorum.
</Body>
<Body>
Totam et reprehenderit aliquam hic dolorum ipsum. Iste et neque eos
voluptas deserunt harum. Mollitia numquam incidunt nihil laboriosam.
Error autem possimus quaerat veniam ut explicabo ut. Error esse est
reprehenderit quae dolor occaecati quas laboriosam.
</Body>
</Item>
<Item
key="eligendi-et-voluptatem"
title="Eligendi et voluptatem"
hasChildItems={false}
>
<Body>
Qui tempora tenetur eum voluptatibus sit et assumenda fuga. Temporibus
hic ut in maxime omnis esse et nam. Aliquam veritatis perferendis quia
enim dolorem molestiae. Impedit eaque optio iste. Eligendi et
voluptatem voluptate corporis perferendis.
</Body>
</Item>
</Accordion>
),
args: {
defaultExpandedKeys: ['lorem-ipsum'],
},
}

View File

@ -0,0 +1,30 @@
import { Meta, StoryObj } from '@storybook/react'
import { Button } from '@/design-system/buttons'
const meta: Meta<typeof Button> = {
component: Button,
argTypes: {
children: { type: 'string' },
},
}
export default meta
type Story = StoryObj<typeof Button>
export const Primary: Story = {
args: {
size: 'XL',
color: 'primary',
children: 'Primary XL button',
},
}
export const Secondary: Story = {
args: {
size: 'XS',
color: 'secondary',
children: 'Secondary XS button',
},
}

View File

@ -0,0 +1,13 @@
import { Meta, StoryObj } from '@storybook/react'
import { CloseButton as CloseButtonComponent } from '@/design-system/buttons'
const meta: Meta<typeof CloseButtonComponent> = {
component: CloseButtonComponent,
}
export default meta
type Story = StoryObj<typeof CloseButtonComponent>
export const CloseButton: Story = {}

View File

@ -0,0 +1,33 @@
import { OverlayProvider } from '@react-aria/overlays'
import { Meta, StoryObj } from '@storybook/react'
import { BrowserRouter } from 'react-router-dom'
import { HelpButtonWithPopover as HelpButtonWithPopoverComponent } from '@/design-system/buttons'
const meta: Meta<typeof HelpButtonWithPopoverComponent> = {
component: HelpButtonWithPopoverComponent,
}
export default meta
type Story = StoryObj<typeof HelpButtonWithPopoverComponent>
export const HelpButtonWithPopover: Story = {
render: (args) => {
// Hack to prevent useIFrameOffset() to return undefined in Popover.tsx
window.parent = window
return (
<BrowserRouter>
<OverlayProvider>
<HelpButtonWithPopoverComponent {...args} />
</OverlayProvider>
</BrowserRouter>
)
},
args: {
title: 'title',
type: 'info',
children: 'content',
},
}

View File

@ -1,32 +0,0 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Button } from '@/design-system/buttons'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
component: Button,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
children: { type: 'string' },
},
} as ComponentMeta<typeof Button>
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />
export const Primary = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Primary.args = {
size: 'XL',
color: 'primary',
children: 'Primary XL button',
}
export const Secondary = Template.bind({})
Secondary.args = {
size: 'XS',
color: 'secondary',
children: 'Secondary XS button',
}
export { CloseButton, HelpButtonWithPopover } from '@/design-system/buttons'

View File

@ -1,24 +1,26 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Meta, StoryObj } from '@storybook/react'
import { CheckList } from '@/design-system'
import { CheckList as CheckListComponent } from '@/design-system'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
component: CheckList,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
const meta: Meta<typeof CheckListComponent> = {
component: CheckListComponent,
argTypes: {
items: [{ isChecked: 'boolean', label: 'string' }],
},
} as ComponentMeta<typeof CheckList>
}
export const CheckListWithData: ComponentStory<typeof CheckList> = () => (
<CheckList
items={[
export default meta
type Story = StoryObj<typeof CheckListComponent>
export const CheckList: Story = {
args: {
items: [
{ isChecked: false, label: "Tient compte de l'ACRE" },
{
isChecked: true,
label: "Versement libératoire de l'impôt sur le revenu",
},
]}
/>
)
],
},
}

View File

@ -1,61 +1,62 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Meta, StoryObj } from '@storybook/react'
import { Chip } from '@/design-system'
import { Emoji } from '../emoji'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
const meta: Meta<typeof Chip> = {
component: Chip,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
children: { type: 'string' },
},
} as ComponentMeta<typeof Chip>
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof Chip> = (args) => <Chip {...args} />
export const Notification = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Notification.args = {
children: '4',
type: 'info',
}
export const DifferentChips: ComponentStory<typeof Chip> = (args) => (
<>
<Chip {...args} type="error">
Panique !
</Chip>
<Chip {...args} type="info">
Attention
</Chip>
<Chip {...args} type="success">
Ouiiiiiii
</Chip>
<Chip {...args} type="primary">
4 messages non lus
</Chip>
<Chip {...args} type="secondary">
SASU
</Chip>
</>
)
export default meta
DifferentChips.args = {
icon: true,
type Story = StoryObj<typeof Chip>
export const Notification: Story = {
args: {
children: '4',
type: 'info',
},
}
export const ChipWithCustomIcon: ComponentStory<typeof Chip> = (args) => (
<>
<Chip {...args} icon={<Emoji emoji="🚧" />} type="info">
Bêta
</Chip>
<Chip {...args} type="secondary" icon={<Emoji emoji="😃" />}>
Everything is awesome
</Chip>
</>
)
export const DifferentChips: Story = {
render: (args) => (
<>
<Chip {...args} type="error">
Panique !
</Chip>
<Chip {...args} type="info">
Attention
</Chip>
<Chip {...args} type="success">
Ouiiiiiii
</Chip>
<Chip {...args} type="primary">
4 messages non lus
</Chip>
<Chip {...args} type="secondary">
SASU
</Chip>
</>
),
args: {
icon: true,
},
}
ChipWithCustomIcon.args = {}
export const ChipWithCustomIcon: Story = {
render: (args) => (
<>
<Chip {...args} icon={<Emoji emoji="🚧" />} type="info">
Bêta
</Chip>
<Chip {...args} type="secondary" icon={<Emoji emoji="😃" />}>
Everything is awesome
</Chip>
</>
),
args: {},
}

View File

@ -1,14 +1,12 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Meta, StoryObj } from '@storybook/react'
import { Drawer } from '@/design-system/drawer'
import { Button } from '../buttons'
import { DrawerButtonProps } from './Drawer'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
const meta: Meta<typeof Drawer> = {
component: Drawer,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
children: {
type: 'string',
@ -29,23 +27,24 @@ export default {
type: 'string',
},
},
} as ComponentMeta<typeof Drawer>
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof Drawer> = (args) => <Drawer {...args} />
export const Basic = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Basic.args = {
children: <div>Coucou, je suis ouvert !</div>,
trigger: (buttonProps: DrawerButtonProps) => (
<Button color="primary" light {...buttonProps}>
Ouvrir le tiroir
</Button>
),
isDismissable: true,
// eslint-disable-next-line no-console
onConfirm: () => console.log('onConfirm appelé !'),
confirmLabel: 'Sauvegarder',
cancelLabel: 'Annuler',
}
export default meta
type Story = StoryObj<typeof Drawer>
export const Basic: Story = {
args: {
children: <div>Coucou, je suis ouvert !</div>,
trigger: (buttonProps: DrawerButtonProps) => (
<Button color="primary" light {...buttonProps}>
Ouvrir le tiroir
</Button>
),
isDismissable: true,
// eslint-disable-next-line no-console
onConfirm: () => console.log('onConfirm appelé !'),
confirmLabel: 'Sauvegarder',
cancelLabel: 'Annuler',
},
}

View File

@ -1,20 +1,20 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Meta, StoryObj } from '@storybook/react'
import { Emoji as EmojiComponent } from '.'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
const meta: Meta<typeof EmojiComponent> = {
component: EmojiComponent,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
emoji: { type: 'string' },
},
} as ComponentMeta<typeof EmojiComponent>
export const Emoji: ComponentStory<typeof EmojiComponent> = (args) => (
<EmojiComponent {...args} />
)
Emoji.args = {
emoji: '❤️🧡💛💚💙💜',
}
export default meta
type Story = StoryObj<typeof EmojiComponent>
export const Emoji: Story = {
args: {
emoji: '❤️🧡💛💚💙💜',
},
}

View File

@ -1,41 +1,41 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Meta, StoryObj } from '@storybook/react'
import { RadioCard, RadioCardGroup } from '.'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
const meta: Meta<typeof RadioCardGroup> = {
component: RadioCardGroup,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
label: {
type: 'string',
},
},
} as ComponentMeta<typeof RadioCardGroup>
}
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof RadioCardGroup> = (args) => (
<RadioCardGroup {...args}>
<RadioCard
value="valueA"
label={'Title A'}
description={'ceci est une description'}
/>
<RadioCard
value="valueB"
label={'Title B'}
description={'ceci est une description'}
/>
<RadioCard value="valueC" label={'Title C'} />
<RadioCard
hideRadio
value="valueD"
label={'Title D'}
description="hidden radio"
/>
</RadioCardGroup>
)
export default meta
export const Basic = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Basic.args = {}
type Story = StoryObj<typeof RadioCardGroup>
export const Basic: Story = {
render: (args) => (
<RadioCardGroup {...args}>
<RadioCard
value="valueA"
label={'Title A'}
description={'ceci est une description'}
/>
<RadioCard
value="valueB"
label={'Title B'}
description={'ceci est une description'}
/>
<RadioCard value="valueC" label={'Title C'} />
<RadioCard
hideRadio
value="valueD"
label={'Title D'}
description="hidden radio"
/>
</RadioCardGroup>
),
args: {},
}

View File

@ -1,24 +1,22 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Meta, StoryObj } from '@storybook/react'
import { Radio, RadioGroup } from '.'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
const meta: Meta<typeof RadioGroup> = {
component: RadioGroup,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
// argTypes: {
// },
} as ComponentMeta<typeof RadioGroup>
}
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof RadioGroup> = (args) => (
<RadioGroup {...args}>
<Radio value="valueA">Radio A</Radio>
<Radio value="valueB">Radio B</Radio>
<Radio value="valueC">Radio C</Radio>
</RadioGroup>
)
export default meta
export const Basic = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Basic.args = {}
type Story = StoryObj<typeof RadioGroup>
export const Basic: Story = {
render: (args) => (
<RadioGroup {...args}>
<Radio value="valueA">Radio A</Radio>
<Radio value="valueB">Radio B</Radio>
<Radio value="valueC">Radio C</Radio>
</RadioGroup>
),
args: {},
}

View File

@ -1,24 +1,22 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Meta, StoryObj } from '@storybook/react'
import { Radio, ToggleGroup } from '.'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
const meta: Meta<typeof ToggleGroup> = {
component: ToggleGroup,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
// argTypes: {
// },
} as ComponentMeta<typeof ToggleGroup>
}
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof ToggleGroup> = (args) => (
<ToggleGroup {...args}>
<Radio value="valueA">Radio A</Radio>
<Radio value="valueB">Radio B</Radio>
<Radio value="valueC">Radio C</Radio>
</ToggleGroup>
)
export default meta
export const Basic = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Basic.args = {}
type Story = StoryObj<typeof ToggleGroup>
export const Basic: Story = {
render: (args) => (
<ToggleGroup {...args}>
<Radio value="valueA">Radio A</Radio>
<Radio value="valueB">Radio B</Radio>
<Radio value="valueC">Radio C</Radio>
</ToggleGroup>
),
args: {},
}

View File

@ -1,22 +1,23 @@
import { ComponentMeta } from '@storybook/react'
import { Meta } from '@storybook/react'
import { SvgIcon } from '.'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
const meta: Meta<typeof SvgIcon> = {
component: SvgIcon,
} as ComponentMeta<typeof SvgIcon>
}
export default meta
export {
CarretDownIcon,
ChevronIcon,
CircleIcon,
EditIcon,
ErrorIcon,
HexagonIcon,
InfoIcon,
ReturnIcon,
SearchIcon,
SuccessIcon,
EditIcon,
HexagonIcon,
TriangleIcon,
CircleIcon,
} from '@/design-system/icons'

View File

@ -1,4 +1,4 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Meta, StoryObj } from '@storybook/react'
import styled from 'styled-components'
import { Message } from '@/design-system'
@ -7,55 +7,65 @@ import { Emoji } from '../emoji'
import { Strong } from '../typography'
import { Body } from '../typography/paragraphs'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
const meta: Meta<typeof Message> = {
component: Message,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
children: { type: 'string' },
},
} as ComponentMeta<typeof Message>
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof Message> = (args) => <Message {...args} />
export const AccompanyingMessage = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
AccompanyingMessage.args = {
children:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam',
type: 'primary',
icon: true,
}
const AlertTemplate: ComponentStory<typeof Message> = (args) => (
<>
<Message {...args} type="success">
Votre message a bien été envoyé
</Message>
<Message {...args} type="info">
Certaines informations sont incorrectes
</Message>
<Message {...args} type="error">
Échec de lenvoi du message
</Message>
</>
)
export default meta
export const Alert = AlertTemplate.bind({})
Alert.args = {
icon: true,
type Story = StoryObj<typeof Message>
export const AccompanyingMessage: Story = {
args: {
children: (
<Body>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam
</Body>
),
type: 'primary',
icon: true,
},
}
export const MessageWithCustomIcon = () => (
<Message type="info" icon={<Emoji emoji="🚧" />} border={false} mini>
<Body>
<StyledStrong>Cet outil est en version bêta</StyledStrong> : nous
travaillons à <Strong>valider les informations et les calculs</Strong>,
mais des <Strong>erreurs peuvent être présentes.</Strong>
</Body>
</Message>
)
export const Alert: Story = {
render: (args) => (
<>
<Message {...args} type="success">
<Body>Votre message a bien été envoyé</Body>
</Message>
<Message {...args} type="info">
<Body>Certaines informations sont incorrectes</Body>
</Message>
<Message {...args} type="error">
<Body>Échec de lenvoi du message</Body>
</Message>
</>
),
args: { icon: true },
}
export const MessageWithCustomIcon: Story = {
render: (args) => (
<Message {...args}>
<Body>
<StyledStrong>Cet outil est en version bêta</StyledStrong> : nous
travaillons à <Strong>valider les informations et les calculs</Strong>,
mais des <Strong>erreurs peuvent être présentes.</Strong>
</Body>
</Message>
),
args: {
type: 'info',
icon: <Emoji emoji="🚧" />,
border: false,
mini: true,
},
}
const StyledStrong = styled(Strong)`
color: ${({ theme }) => theme.colors.extended.info[600]};

View File

@ -9,13 +9,7 @@ import {
} from '@react-aria/overlays'
import { AriaDialogProps } from '@react-types/dialog'
import FocusTrap from 'focus-trap-react'
import React, {
Attributes,
RefObject,
useEffect,
useRef,
useState,
} from 'react'
import React, { RefObject, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled, { css, keyframes } from 'styled-components'

View File

@ -6,7 +6,6 @@ import { Button } from '@/design-system/buttons'
import { Grid } from '../layout'
import { H3 } from '../typography/heading'
import { Body } from '../typography/paragraphs'
import PopoverWithTrigger, {
PopoverWithTriggerProps,
} from './PopoverWithTrigger'

View File

@ -1,14 +1,7 @@
import { useOverlayTrigger } from '@react-aria/overlays'
import { useOverlayTriggerState } from '@react-stately/overlays'
import { AriaButtonProps } from '@react-types/button'
import React, {
Attributes,
ReactElement,
Ref,
RefObject,
useEffect,
useRef,
} from 'react'
import React, { ReactElement, Ref, RefObject, useEffect, useRef } from 'react'
import { useLocation } from 'react-router-dom'
import { ForceThemeProvider } from '@/components/utils/DarkModeContext'

View File

@ -11,27 +11,25 @@ import { useDarkMode } from '@/hooks/useDarkMode'
type SystemRootProps = {
children: ReactNode
forceDarkMode?: boolean
}
const SystemRoot = ({ children }: SystemRootProps) => {
const SystemRoot = ({ children, forceDarkMode }: SystemRootProps) => {
const userAgent = typeof navigator !== 'undefined' && navigator.userAgent
const [darkMode] = useDarkMode()
const [contextDarkMode] = useDarkMode()
const darkMode =
typeof forceDarkMode === 'boolean' ? forceDarkMode : contextDarkMode
return (
<StyleSheetManager disableCSSOMInjection={isbot(userAgent)}>
<ThemeProvider theme={{ ...urssafTheme, darkMode }}>
<Background>{children}</Background>
<BackgroundStyle $darkMode={darkMode}>{children}</BackgroundStyle>
</ThemeProvider>
</StyleSheetManager>
)
}
const Background = ({ children }: { children: ReactNode }) => {
const [darkMode] = useDarkMode()
return <BackgroundStyle $darkMode={darkMode}>{children}</BackgroundStyle>
}
type BackgroundProps = {
$darkMode: boolean
}

View File

@ -1,34 +1,36 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Meta, StoryObj } from '@storybook/react'
import { MemoryRouter } from 'react-router-dom'
import { Step, Stepper } from '@/design-system'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
const meta: Meta<typeof Stepper> = {
component: Stepper,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
} as ComponentMeta<typeof Step>
const Template: ComponentStory<typeof Stepper> = (args) => (
<MemoryRouter initialEntries={['/step-2']}>
<Stepper {...args}>
<Step to={'/'} progress={1}>
Première étape
</Step>
<Step to={'/step-2'} progress={0.2}>
Deuxième étape
</Step>
<Step to={'/step-3'} progress={0}>
Troisième étape
</Step>
<Step to={'/step-4'} progress={0} isDisabled>
Dernière étape
</Step>
</Stepper>
</MemoryRouter>
)
export const Basic = Template.bind({})
Basic.args = {
'aria-label': 'Étapes du formulaire en cours',
}
export default meta
type Story = StoryObj<typeof Stepper>
export const Basic: Story = {
render: (args) => (
<MemoryRouter initialEntries={['/step-2']}>
<Stepper {...args}>
<Step to={'/'} progress={1}>
Première étape
</Step>
<Step to={'/step-2'} progress={0.2}>
Deuxième étape
</Step>
<Step to={'/step-3'} progress={0}>
Troisième étape
</Step>
<Step to={'/step-4'} progress={0} isDisabled>
Dernière étape
</Step>
</Stepper>
</MemoryRouter>
),
args: {
'aria-label': 'Étapes du formulaire en cours',
},
}

View File

@ -1,33 +1,34 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Meta, StoryObj } from '@storybook/react'
import { Switch } from '@/design-system/switch'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
const meta: Meta<typeof Switch> = {
component: Switch,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
children: {
type: 'string',
},
},
} as ComponentMeta<typeof Switch>
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof Switch> = (args) => <Switch {...args} />
export const Basic = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Basic.args = {
children: 'Label',
}
export const Selected = Template.bind({})
Selected.args = {
isSelected: true,
export default meta
type Story = StoryObj<typeof Switch>
export const Basic: Story = {
args: {
children: 'Label',
},
}
export const Disabled = Template.bind({})
Disabled.args = {
isDisabled: true,
export const Selected: Story = {
args: {
isSelected: true,
},
}
export const Disabled: Story = {
args: {
isDisabled: true,
},
}

View File

@ -1,4 +1,4 @@
import React, { ReactNode } from 'react'
import React, { ReactElement, ReactNode } from 'react'
import { Tooltip as RTooltip } from 'react-tooltip'
import 'react-tooltip/dist/react-tooltip.css'
@ -11,7 +11,7 @@ export const Tooltip = ({
className,
id,
}: {
children: ReactNode
children: ReactElement
tooltip: ReactNode
className?: string
// A11y : préciser un aria-describedby sur l'élément visé par le tooltip
@ -20,11 +20,15 @@ export const Tooltip = ({
return (
<StyledSpan>
{React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
if (React.isValidElement(child) && child.type !== React.Fragment) {
return React.cloneElement(child, { id } as {
id: string
})
}
throw new Error(
'Tooltip children must be a valid React element and not a React fragment.'
)
})}
<StyledRTooltip
anchorId={id}
@ -41,6 +45,7 @@ const StyledRTooltip = styled(RTooltip)`
max-width: 20rem;
font-size: 0.75rem;
`
const StyledSpan = styled.span`
display: flex;
align-items: center;

View File

@ -1,15 +1,11 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { ErrorBoundary } from '@sentry/react'
import { Meta, StoryObj } from '@storybook/react'
import { Tooltip } from '@/design-system/tooltip'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
const meta: Meta<typeof Tooltip> = {
component: Tooltip,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
children: {
type: 'string',
},
tooltip: {
type: 'string',
},
@ -17,15 +13,29 @@ export default {
type: 'string',
},
},
} as ComponentMeta<typeof Tooltip>
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof Tooltip> = (args) => <Tooltip {...args} />
export const Basic = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Basic.args = {
children: 'Passez la souris sur moi',
tooltip: 'Coucou !',
id: 'test-tooltip',
}
export default meta
type Story = StoryObj<typeof Tooltip>
export const Basic: Story = {
args: {
children: <span>Passez la souris sur moi</span>,
tooltip: 'Coucou !',
id: 'test-tooltip',
},
}
export const Invalid: Story = {
render: (args) => (
<ErrorBoundary fallback={({ error }) => <span>{error.message}</span>}>
<Tooltip {...args} />
</ErrorBoundary>
),
args: {
children: <>Les Fragment sont interdit</>,
tooltip: 'Coucou !',
id: 'test-tooltip',
},
}

View File

@ -0,0 +1,21 @@
import { Meta, StoryObj } from '@storybook/react'
import { Li, Ol } from '@/design-system/typography/list'
const meta: Meta<typeof Ol> = {
component: Ol,
}
export default meta
type Story = StoryObj<typeof Ol>
export const Numbered: Story = {
render: (args) => (
<Ol {...args}>
<Li>Élément 1</Li>
<Li>Élément 2</Li>
<Li>Élément 3</Li>
</Ol>
),
}

View File

@ -0,0 +1,34 @@
import { Meta, StoryObj } from '@storybook/react'
import { Li, Ul } from '@/design-system/typography/list'
const meta: Meta<typeof Ul> = {
component: Ul,
}
export default meta
type StoryUl = StoryObj<typeof Ul>
export const Basic: StoryUl = {
render: (args) => (
<Ul {...args}>
<Li>Élément 1</Li>
<Li>Élément 2</Li>
<Li>Élément 3</Li>
</Ul>
),
}
export const Xl: StoryUl = {
render: (args) => (
<Ul {...args}>
<Li>Élément 1</Li>
<Li>Élément 2</Li>
<Li>Élément 3</Li>
</Ul>
),
args: {
size: 'XL',
},
}

View File

@ -1,40 +0,0 @@
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { Li, Ol, Ul } from '@/design-system/typography/list'
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
component: Ul,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
} as ComponentMeta<typeof Ul>
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof Ul> = (args) => (
<Ul {...args}>
<Li>Élément 1</Li>
<Li>Élément 2</Li>
<Li>Élément 3</Li>
</Ul>
)
export const Basic = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Basic.args = {}
export const XL = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
XL.args = {
size: 'XL',
}
const OlTemplate: ComponentStory<typeof Ol> = (args) => (
<Ol {...args}>
<Li>Élément 1</Li>
<Li>Élément 2</Li>
<Li>Élément 3</Li>
</Ol>
)
export const Numbered = OlTemplate.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Numbered.args = {}

8044
yarn.lock

File diff suppressed because it is too large Load Diff