@linagora/twake-mui 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [1.6.0](https://github.com/linagora/twake-ui/compare/v1.5.0...v1.6.0) (2026-04-22)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * ESM/CJS mismatch in exports ([bd31d2d](https://github.com/linagora/twake-ui/commit/bd31d2db3b8993da5cafe582cb350441a7d05685))
7
+
8
+
9
+ ### Features
10
+
11
+ * Add all storybook/argos config files ([6a774a9](https://github.com/linagora/twake-ui/commit/6a774a97cedfacaa8387f3b4d5b75503efd7ae65))
12
+ * Add packages for storybook and argos ([729e937](https://github.com/linagora/twake-ui/commit/729e93734f0e09d639871410f0256cbba0939ad9))
13
+ * Add storybook stories ([9a141ca](https://github.com/linagora/twake-ui/commit/9a141ca06d2c5cfd9ec8a8142a5c5a34452cfd90))
14
+
1
15
  # [1.5.0](https://github.com/linagora/twake-ui/compare/v1.4.0...v1.5.0) (2026-04-14)
2
16
 
3
17
 
package/README.md CHANGED
@@ -70,6 +70,43 @@ This package is part of the `twake-ui` monorepo.
70
70
  npm run build
71
71
  ```
72
72
 
73
+ ### Storybook
74
+
75
+ Use Storybook for isolated component development and visual testing:
76
+
77
+ ```bash
78
+ # Start Storybook development server
79
+ npm run doc
80
+
81
+ # Build static Storybook
82
+ npm run build:doc
83
+ ```
84
+
85
+ Stories are located in:
86
+ - `src/components/**/*.stories.tsx` - Component stories (e.g., Avatar)
87
+ - `src/stories/*.stories.tsx` - Override showcase stories (Button, Input, Dialog, etc.)
88
+
89
+ Access Storybook at http://localhost:6006
90
+
91
+ ### Visual Regression Testing
92
+
93
+ We use Argos for visual regression testing. Screenshots are automatically captured from Storybook stories during CI.
94
+
95
+ To run visual tests locally (requires ARGOS_TOKEN):
96
+
97
+ ```bash
98
+ npm run build:doc
99
+ npm run screenshots
100
+ ```
101
+
102
+ To add visual regression coverage to a story:
103
+
104
+ ```typescript
105
+ export const MyStory = {
106
+ tags: ['argos']
107
+ }
108
+ ```
109
+
73
110
  ### Local Development
74
111
 
75
112
  To use this package locally in another project:
@@ -92,6 +129,23 @@ Or use file path in package.json:
92
129
  }
93
130
  ```
94
131
 
132
+ ### About dependencies
133
+
134
+ Because of inter-dependencies between these packages:
135
+ - `storybook`, `@storybook/*`
136
+ - `vite`, `@vitejs/*`
137
+ - `vitest`, `@vitest/*`
138
+ - `@argos-ci/*`, `playwright`
139
+
140
+ you may encounter problem to install packages. So you can:
141
+
142
+ ```bash
143
+ rm -rf node_modules packages/twake-mui/node_modules package-lock.json
144
+ npm install
145
+ ```
146
+
147
+ We can maybe use **pnpm** in the future that support hoisting disabling via `.npmrc`
148
+
95
149
  ## License
96
150
 
97
151
  MIT
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Avatar } from './index';
3
+ declare const meta: Meta<typeof Avatar>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Default: Story;
7
+ export declare const Screenshot: Story;
@@ -0,0 +1,73 @@
1
+ import React from 'react';
2
+ import { supportedColors } from './helpers';
3
+ import { Avatar } from './index';
4
+ const meta = {
5
+ title: 'Avatar',
6
+ component: Avatar,
7
+ parameters: { layout: 'centered' },
8
+ tags: ['autodocs'],
9
+ argTypes: {
10
+ color: {
11
+ control: 'select',
12
+ options: ['none', ...supportedColors]
13
+ },
14
+ size: {
15
+ control: 'select',
16
+ options: ['xs', 's', 'm', 'l', 'xl']
17
+ },
18
+ border: { control: 'boolean' },
19
+ innerBorder: { control: 'boolean' },
20
+ disabled: { control: 'boolean' },
21
+ display: {
22
+ control: 'select',
23
+ options: ['initial', 'inline']
24
+ }
25
+ }
26
+ };
27
+ export default meta;
28
+ export const Default = {
29
+ args: {
30
+ children: 'JD'
31
+ }
32
+ };
33
+ // Visual Regression - Combined view for Argos testing
34
+ export const Screenshot = {
35
+ tags: ['argos'],
36
+ render: () => (React.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: '32px' } },
37
+ React.createElement("section", null,
38
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Sizes"),
39
+ React.createElement("div", { style: { display: 'flex', gap: '16px', alignItems: 'center' } },
40
+ React.createElement(Avatar, { size: "xs" }, "XS"),
41
+ React.createElement(Avatar, { size: "s" }, "S"),
42
+ React.createElement(Avatar, { size: "m" }, "M"),
43
+ React.createElement(Avatar, { size: "l" }, "L"),
44
+ React.createElement(Avatar, { size: "xl" }, "XL"))),
45
+ React.createElement("section", null,
46
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Colors"),
47
+ React.createElement("div", { style: { display: 'flex', gap: '16px', flexWrap: 'wrap' } }, supportedColors.map(color => (React.createElement(Avatar, { key: color, color: color, size: "l" }, color.slice(0, 2).toUpperCase()))))),
48
+ React.createElement("section", null,
49
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Name-based Colors"),
50
+ React.createElement("div", { style: { display: 'flex', gap: '16px' } },
51
+ React.createElement(Avatar, { size: "l" }, "Alice"),
52
+ React.createElement(Avatar, { size: "l" }, "Bob"),
53
+ React.createElement(Avatar, { size: "l" }, "Charlie"),
54
+ React.createElement(Avatar, { size: "l" }, "Diana"))),
55
+ React.createElement("section", null,
56
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "With Image"),
57
+ React.createElement("div", { style: { display: 'flex', gap: '16px' } },
58
+ React.createElement(Avatar, { src: "https://i.pravatar.cc/150?img=11", alt: "User 1", size: "l" }),
59
+ React.createElement(Avatar, { src: "https://i.pravatar.cc/150?img=12", alt: "User 2", size: "l" }),
60
+ React.createElement(Avatar, { src: "https://i.pravatar.cc/150?img=13", alt: "User 3", size: "l" }))),
61
+ React.createElement("section", null,
62
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Border Variants"),
63
+ React.createElement("div", { style: { display: 'flex', gap: '16px' } },
64
+ React.createElement(Avatar, { size: "l" }, "Default"),
65
+ React.createElement(Avatar, { size: "l", border: true }, "Border"),
66
+ React.createElement(Avatar, { size: "l", innerBorder: true }, "Inner"),
67
+ React.createElement(Avatar, { size: "l", border: true, innerBorder: true }, "Both"))),
68
+ React.createElement("section", null,
69
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Disabled State"),
70
+ React.createElement("div", { style: { display: 'flex', gap: '16px' } },
71
+ React.createElement(Avatar, { size: "l", disabled: true }, "D"),
72
+ React.createElement(Avatar, { size: "l", disabled: true, src: "https://i.pravatar.cc/150?img=14", alt: "Disabled" })))))
73
+ };
@@ -0,0 +1,7 @@
1
+ import { Button } from '@mui/material';
2
+ import type { Meta, StoryObj } from '@storybook/react-vite';
3
+ declare const meta: Meta<typeof Button>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Button>;
6
+ export declare const Docs: Story;
7
+ export declare const Screenshot: Story;
@@ -0,0 +1,43 @@
1
+ import { Button, Stack } from '@mui/material';
2
+ import React from 'react';
3
+ const meta = {
4
+ title: 'Button',
5
+ component: Button,
6
+ parameters: { layout: 'centered' },
7
+ tags: ['autodocs']
8
+ };
9
+ export default meta;
10
+ export const Docs = {
11
+ args: {
12
+ variant: 'contained',
13
+ children: 'Button'
14
+ }
15
+ };
16
+ // Visual Regression - All variants combined
17
+ export const Screenshot = {
18
+ tags: ['argos'],
19
+ render: () => (React.createElement(Stack, { spacing: 4 },
20
+ React.createElement("section", null,
21
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Variants"),
22
+ React.createElement(Stack, { direction: "row", spacing: 2 },
23
+ React.createElement(Button, { variant: "contained" }, "Contained"),
24
+ React.createElement(Button, { variant: "outlined" }, "Outlined"),
25
+ React.createElement(Button, { variant: "text" }, "Text"))),
26
+ React.createElement("section", null,
27
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Colors"),
28
+ React.createElement(Stack, { direction: "row", spacing: 2 },
29
+ React.createElement(Button, { variant: "contained", color: "primary" }, "Primary"),
30
+ React.createElement(Button, { variant: "contained", color: "secondary" }, "Secondary"),
31
+ React.createElement(Button, { variant: "contained", color: "error" }, "Error"))),
32
+ React.createElement("section", null,
33
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Sizes"),
34
+ React.createElement(Stack, { direction: "row", spacing: 2, sx: { alignItems: 'center' } },
35
+ React.createElement(Button, { variant: "contained", size: "small" }, "Small"),
36
+ React.createElement(Button, { variant: "contained", size: "medium" }, "Medium"),
37
+ React.createElement(Button, { variant: "contained", size: "large" }, "Large"))),
38
+ React.createElement("section", null,
39
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "States"),
40
+ React.createElement(Stack, { direction: "row", spacing: 2 },
41
+ React.createElement(Button, { variant: "contained" }, "Normal"),
42
+ React.createElement(Button, { variant: "contained", disabled: true }, "Disabled")))))
43
+ };
@@ -0,0 +1,7 @@
1
+ import { Dialog } from '@mui/material';
2
+ import type { Meta, StoryObj } from '@storybook/react-vite';
3
+ declare const meta: Meta<typeof Dialog>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Dialog>;
6
+ export declare const Default: Story;
7
+ export declare const Screenshot: Story;
@@ -0,0 +1,40 @@
1
+ import { Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, Button, Stack } from '@mui/material';
2
+ import React from 'react';
3
+ const meta = {
4
+ title: 'Dialog',
5
+ component: Dialog,
6
+ parameters: { layout: 'centered' },
7
+ tags: ['autodocs']
8
+ };
9
+ export default meta;
10
+ // Basic Dialog with open/close state
11
+ const BasicDialogComponent = () => {
12
+ const [open, setOpen] = React.useState(false);
13
+ return (React.createElement(React.Fragment, null,
14
+ React.createElement(Button, { variant: "contained", onClick: () => setOpen(true) }, "Open Dialog"),
15
+ React.createElement(Dialog, { open: open, onClose: () => setOpen(false) },
16
+ React.createElement(DialogTitle, null, "Dialog Title"),
17
+ React.createElement(DialogContent, null,
18
+ React.createElement(DialogContentText, null, "This is a basic dialog with a title, content, and action buttons. You can put any content here.")),
19
+ React.createElement(DialogActions, null,
20
+ React.createElement(Button, { onClick: () => setOpen(false) }, "Cancel"),
21
+ React.createElement(Button, { onClick: () => setOpen(false), variant: "contained" }, "Confirm")))));
22
+ };
23
+ export const Default = {
24
+ render: () => React.createElement(BasicDialogComponent, null)
25
+ };
26
+ // Visual Regression - Dialog styles
27
+ export const Screenshot = {
28
+ tags: ['argos'],
29
+ render: () => (React.createElement(Stack, { spacing: 4 },
30
+ React.createElement("section", null,
31
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Dialog Components"),
32
+ React.createElement(Stack, { spacing: 2 },
33
+ React.createElement(Dialog, { open: true },
34
+ React.createElement(DialogTitle, null, "Standard Dialog"),
35
+ React.createElement(DialogContent, null,
36
+ React.createElement(DialogContentText, null, "This demonstrates the standard dialog appearance with all its subcomponents styled according to the Twake theme.")),
37
+ React.createElement(DialogActions, null,
38
+ React.createElement(Button, null, "Cancel"),
39
+ React.createElement(Button, { variant: "contained" }, "Confirm")))))))
40
+ };
@@ -0,0 +1,7 @@
1
+ import { TextField } from '@mui/material';
2
+ import type { Meta, StoryObj } from '@storybook/react-vite';
3
+ declare const meta: Meta<typeof TextField>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof TextField>;
6
+ export declare const Default: Story;
7
+ export declare const Screenshot: Story;
@@ -0,0 +1,41 @@
1
+ import { TextField, Select, MenuItem, Stack, Box } from '@mui/material';
2
+ import React from 'react';
3
+ const meta = {
4
+ title: 'Input',
5
+ component: TextField,
6
+ parameters: { layout: 'centered' },
7
+ tags: ['autodocs']
8
+ };
9
+ export default meta;
10
+ export const Default = {
11
+ args: {
12
+ label: 'Label',
13
+ variant: 'outlined',
14
+ defaultValue: 'Sample text'
15
+ }
16
+ };
17
+ // Visual Regression - All inputs combined
18
+ export const Screenshot = {
19
+ tags: ['argos'],
20
+ render: () => (React.createElement(Stack, { spacing: 4 },
21
+ React.createElement("section", null,
22
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "TextField Variants"),
23
+ React.createElement(Stack, { spacing: 2 },
24
+ React.createElement(TextField, { label: "Outlined", variant: "outlined", defaultValue: "Sample text" }),
25
+ React.createElement(TextField, { label: "Filled", variant: "filled", defaultValue: "Sample text" }),
26
+ React.createElement(TextField, { label: "Standard", variant: "standard", defaultValue: "Sample text" }))),
27
+ React.createElement("section", null,
28
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "TextField States"),
29
+ React.createElement(Stack, { spacing: 2 },
30
+ React.createElement(TextField, { label: "Normal", variant: "outlined", defaultValue: "Sample text" }),
31
+ React.createElement(TextField, { label: "Disabled", variant: "outlined", defaultValue: "Cannot edit", disabled: true }),
32
+ React.createElement(TextField, { label: "Error", variant: "outlined", defaultValue: "Invalid value", error: true, helperText: "This field has an error" }),
33
+ React.createElement(TextField, { label: "Required", variant: "outlined", required: true }))),
34
+ React.createElement("section", null,
35
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Select"),
36
+ React.createElement(Box, { sx: { minWidth: 200 } },
37
+ React.createElement(Select, { value: 10, fullWidth: true },
38
+ React.createElement(MenuItem, { value: 10 }, "Ten"),
39
+ React.createElement(MenuItem, { value: 20 }, "Twenty"),
40
+ React.createElement(MenuItem, { value: 30 }, "Thirty"))))))
41
+ };
@@ -0,0 +1,7 @@
1
+ import { Checkbox } from '@mui/material';
2
+ import type { Meta, StoryObj } from '@storybook/react-vite';
3
+ declare const meta: Meta<typeof Checkbox>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Checkbox>;
6
+ export declare const Default: Story;
7
+ export declare const Screenshot: Story;
@@ -0,0 +1,37 @@
1
+ import FormatBoldIcon from '@mui/icons-material/FormatBold';
2
+ import FormatItalicIcon from '@mui/icons-material/FormatItalic';
3
+ import FormatUnderlinedIcon from '@mui/icons-material/FormatUnderlined';
4
+ import { Checkbox, FormControlLabel, ToggleButton, ToggleButtonGroup, Stack, Box } from '@mui/material';
5
+ import React from 'react';
6
+ const meta = {
7
+ title: 'Selection',
8
+ component: Checkbox,
9
+ parameters: { layout: 'centered' },
10
+ tags: ['autodocs']
11
+ };
12
+ export default meta;
13
+ export const Default = {
14
+ render: () => React.createElement(FormControlLabel, { control: React.createElement(Checkbox, null), label: "Checkbox" })
15
+ };
16
+ // Visual Regression - All selection components
17
+ export const Screenshot = {
18
+ tags: ['argos'],
19
+ render: () => (React.createElement(Stack, { spacing: 4 },
20
+ React.createElement("section", null,
21
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Checkbox States"),
22
+ React.createElement(Stack, { direction: "row", spacing: 4 },
23
+ React.createElement(FormControlLabel, { control: React.createElement(Checkbox, { checked: false }), label: "Unchecked" }),
24
+ React.createElement(FormControlLabel, { control: React.createElement(Checkbox, { checked: true }), label: "Checked" }),
25
+ React.createElement(FormControlLabel, { control: React.createElement(Checkbox, { indeterminate: true }), label: "Indeterminate" }),
26
+ React.createElement(FormControlLabel, { control: React.createElement(Checkbox, { disabled: true }), label: "Disabled" }))),
27
+ React.createElement("section", null,
28
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Toggle Buttons"),
29
+ React.createElement(Box, null,
30
+ React.createElement(ToggleButtonGroup, { value: ['bold'] },
31
+ React.createElement(ToggleButton, { value: "bold", "aria-label": "bold" },
32
+ React.createElement(FormatBoldIcon, null)),
33
+ React.createElement(ToggleButton, { value: "italic", "aria-label": "italic" },
34
+ React.createElement(FormatItalicIcon, null)),
35
+ React.createElement(ToggleButton, { value: "underlined", "aria-label": "underlined" },
36
+ React.createElement(FormatUnderlinedIcon, null)))))))
37
+ };
@@ -0,0 +1,7 @@
1
+ import { Typography } from '@mui/material';
2
+ import type { Meta, StoryObj } from '@storybook/react-vite';
3
+ declare const meta: Meta<typeof Typography>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Typography>;
6
+ export declare const Default: Story;
7
+ export declare const Screenshot: Story;
@@ -0,0 +1,45 @@
1
+ import { Typography, Paper, Stack } from '@mui/material';
2
+ import React from 'react';
3
+ const meta = {
4
+ title: 'Typography',
5
+ component: Typography,
6
+ parameters: { layout: 'centered' },
7
+ tags: ['autodocs']
8
+ };
9
+ export default meta;
10
+ export const Default = {
11
+ args: {
12
+ variant: 'body1',
13
+ children: 'This is sample typography text.'
14
+ }
15
+ };
16
+ // Visual Regression - All typography combined
17
+ export const Screenshot = {
18
+ tags: ['argos'],
19
+ render: () => (React.createElement(Paper, { sx: { p: 4, maxWidth: 600 } },
20
+ React.createElement(Stack, { spacing: 2 },
21
+ React.createElement("section", null,
22
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "All Variants"),
23
+ React.createElement(Stack, { spacing: 1 },
24
+ React.createElement(Typography, { variant: "h1" }, "Heading 1"),
25
+ React.createElement(Typography, { variant: "h2" }, "Heading 2"),
26
+ React.createElement(Typography, { variant: "h3" }, "Heading 3"),
27
+ React.createElement(Typography, { variant: "h4" }, "Heading 4"),
28
+ React.createElement(Typography, { variant: "h5" }, "Heading 5"),
29
+ React.createElement(Typography, { variant: "h6" }, "Heading 6"),
30
+ React.createElement(Typography, { variant: "subtitle1" }, "Subtitle 1"),
31
+ React.createElement(Typography, { variant: "subtitle2" }, "Subtitle 2"),
32
+ React.createElement(Typography, { variant: "body1" }, "Body 1 - This is the default body text style used for most content."),
33
+ React.createElement(Typography, { variant: "body2" }, "Body 2 - This is a smaller body text style for secondary content."),
34
+ React.createElement(Typography, { variant: "button" }, "Button Text"),
35
+ React.createElement(Typography, { variant: "caption" }, "Caption text"),
36
+ React.createElement(Typography, { variant: "overline" }, "OVERLINE TEXT"))),
37
+ React.createElement("section", null,
38
+ React.createElement("h3", { style: { marginBottom: '12px', marginTop: '24px' } }, "Colors"),
39
+ React.createElement(Stack, { spacing: 1 },
40
+ React.createElement(Typography, { color: "primary" }, "Primary color text"),
41
+ React.createElement(Typography, { color: "secondary" }, "Secondary color text"),
42
+ React.createElement(Typography, { color: "error" }, "Error color text"),
43
+ React.createElement(Typography, { color: "text.primary" }, "Text primary color"),
44
+ React.createElement(Typography, { color: "text.secondary" }, "Text secondary color"))))))
45
+ };
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@linagora/twake-mui",
3
- "version": "1.5.0",
3
+ "type": "module",
4
+ "version": "1.6.0",
4
5
  "description": "MUI v7 theme system for Twake applications",
5
6
  "author": "Twake",
6
7
  "license": "MIT",
@@ -21,9 +22,8 @@
21
22
  ],
22
23
  "exports": {
23
24
  ".": {
24
- "import": "./dist/index.js",
25
- "require": "./dist/index.js",
26
- "types": "./dist/index.d.ts"
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.js"
27
27
  }
28
28
  },
29
29
  "main": "dist/index.js",
@@ -38,36 +38,44 @@
38
38
  },
39
39
  "scripts": {
40
40
  "build": "tsc",
41
+ "build:doc": "storybook build --output-dir storybook-static",
41
42
  "start": "tsc --watch",
42
43
  "test": "echo \"Error: no test specified\" && exit 1",
43
44
  "lint": "eslint src --ext .ts,.tsx",
44
45
  "lint:fix": "eslint src --ext .ts,.tsx --fix",
45
- "clean": "rm -rf dist"
46
- },
47
- "dependencies": {
48
- "react": "^18.2.0",
49
- "react-dom": "^18.2.0"
46
+ "clean": "rm -rf dist",
47
+ "doc": "storybook dev -p 6006",
48
+ "screenshots": "vitest run"
50
49
  },
51
50
  "peerDependencies": {
52
- "@emotion/react": "^11.14.0",
53
- "@emotion/styled": "^11.14.1",
51
+ "@emotion/react": "^11.5.0",
52
+ "@emotion/styled": "^11.3.0",
54
53
  "@mui/material": "^7.1.2",
55
- "react": "^18.2.0",
56
- "react-dom": "^18.2.0"
54
+ "react": "^18",
55
+ "react-dom": "^18"
57
56
  },
58
57
  "devDependencies": {
59
- "@types/react": "18.3.26",
60
- "@types/react-dom": "18.3.7",
61
- "cozy-tsconfig": "^1.9.0",
62
- "eslint": "10.1.0",
63
- "eslint-config-cozy-app": "7.0.0"
64
- },
65
- "peerDependenciesMeta": {
66
- "react": {
67
- "optional": false
68
- },
69
- "react-dom": {
70
- "optional": false
71
- }
58
+ "@argos-ci/cli": "4.2.0",
59
+ "@argos-ci/storybook": "5.3.2",
60
+ "@emotion/react": "^11.5.0",
61
+ "@emotion/styled": "^11.3.0",
62
+ "@mui/icons-material": "7.3.10",
63
+ "@mui/material": "^7.1.2",
64
+ "@storybook/addon-docs": "10.3.5",
65
+ "@storybook/addon-vitest": "10.3.5",
66
+ "@storybook/builder-vite": "10.3.5",
67
+ "@storybook/react": "10.3.5",
68
+ "@storybook/react-vite": "10.3.5",
69
+ "@vitest/browser-playwright": "4.1.5",
70
+ "cozy-tsconfig": "^2.0.0",
71
+ "eslint": "10.2.1",
72
+ "eslint-config-cozy-app": "7.0.0",
73
+ "eslint-plugin-storybook": "10.3.5",
74
+ "playwright": "1.59.1",
75
+ "react": "^18.2.0",
76
+ "react-dom": "^18.2.0",
77
+ "storybook": "10.3.5",
78
+ "vite": "8.0.9",
79
+ "vitest": "4.1.5"
72
80
  }
73
81
  }