@linagora/twake-mui 9.9.0 → 9.10.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/components/ContactPopover/ContactPopover.stories.js +7 -11
  3. package/dist/components/ContactPopover/ContactPopoverCalendarAction.js +1 -1
  4. package/dist/components/ContactPopover/ContactPopoverChatAction.js +1 -1
  5. package/dist/components/ContactPopover/ContactPopoverEmailAction.js +1 -1
  6. package/dist/components/ContactPopover/ContactPopoverVideoAction.js +1 -1
  7. package/dist/components/ContactPopover/index.js +1 -1
  8. package/dist/components/Dialog/Dialog.stories.js +3 -1
  9. package/dist/components/ListItem/ListItem.stories.d.ts +9 -0
  10. package/dist/components/ListItem/ListItem.stories.js +135 -0
  11. package/dist/components/ListItem/helpers.d.ts +24 -0
  12. package/dist/components/ListItem/helpers.js +30 -0
  13. package/dist/components/ListItem/index.d.ts +7 -0
  14. package/dist/components/ListItem/index.js +19 -0
  15. package/dist/components/ListItemButton/index.d.ts +6 -0
  16. package/dist/components/ListItemButton/index.js +23 -0
  17. package/dist/components/ListItemText/ListItemText.stories.d.ts +7 -0
  18. package/dist/components/ListItemText/ListItemText.stories.js +58 -0
  19. package/dist/components/ListItemText/index.d.ts +7 -0
  20. package/dist/components/ListItemText/index.js +23 -0
  21. package/dist/components/ListSubheader/ListSubheader.stories.d.ts +7 -0
  22. package/dist/components/ListSubheader/ListSubheader.stories.js +59 -0
  23. package/dist/components/ListSubheader/index.d.ts +8 -0
  24. package/dist/components/ListSubheader/index.js +6 -0
  25. package/dist/components/Nav/index.d.ts +1 -1
  26. package/dist/components/NavDesktopDropdown/index.js +2 -7
  27. package/dist/components/NavIcon/index.js +2 -0
  28. package/dist/components/NavItem/index.d.ts +1 -1
  29. package/dist/components/NavItem/index.js +1 -0
  30. package/dist/components/NavLink/index.js +2 -0
  31. package/dist/index.d.ts +8 -0
  32. package/dist/index.js +4 -0
  33. package/dist/lib/overrides.js +109 -0
  34. package/dist/stories/List.stories.d.ts +12 -0
  35. package/dist/stories/List.stories.js +141 -0
  36. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ # @linagora/twake-mui [9.10.0](https://github.com/linagora/twake-ui/compare/@linagora/twake-mui@9.9.1...@linagora/twake-mui@9.10.0) (2026-09-28)
2
+
3
+
4
+ ### Features
5
+
6
+ * **twake-mui:** Apply review on list components ([b5971e8](https://github.com/linagora/twake-ui/commit/b5971e8cdc66d12e24479cc1dee5d657c86495a7))
7
+ * **twake-mui:** Migrate ListItem from cozy-ui ([f3f4d0a](https://github.com/linagora/twake-ui/commit/f3f4d0ab092b8cd0c5344831193607da23d353a0))
8
+ * **twake-mui:** Migrate ListItemText from cozy-ui ([ee840a6](https://github.com/linagora/twake-ui/commit/ee840a671b7e0f823a28d1d7a33c325b0bb0f9c9))
9
+ * **twake-mui:** Migrate ListSubheader from cozy-ui ([af32dbd](https://github.com/linagora/twake-ui/commit/af32dbdde9365b86237ca7754a91c562e28913e0))
10
+
11
+ ## @linagora/twake-mui [9.9.1](https://github.com/linagora/twake-ui/compare/@linagora/twake-mui@9.9.0...@linagora/twake-mui@9.9.1) (2026-09-24)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * **twake-mui:** Fixed contactPopover click propagation & opening link in new pages ([b11270b](https://github.com/linagora/twake-ui/commit/b11270b060bcc749805f59059214c8a011b7b20d))
17
+
1
18
  # @linagora/twake-mui [9.9.0](https://github.com/linagora/twake-ui/compare/@linagora/twake-mui@9.8.0...@linagora/twake-mui@9.9.0) (2026-09-24)
2
19
 
3
20
 
@@ -1,5 +1,6 @@
1
1
  import { Chip, Box, Typography } from '@mui/material';
2
- import React, { useEffect, useRef } from 'react';
2
+ import React from 'react';
3
+ import { screen } from 'storybook/test';
3
4
  import { ContactPopover } from './index';
4
5
  const meta = {
5
6
  title: 'Components/ContactPopover',
@@ -32,16 +33,7 @@ const meta = {
32
33
  export default meta;
33
34
  export const Default = {
34
35
  render: () => {
35
- const containerRef = useRef(null);
36
- useEffect(() => {
37
- const timer = setTimeout(() => {
38
- containerRef.current
39
- ?.querySelectorAll('[role="button"]')[0]
40
- .click();
41
- }, 100);
42
- return () => clearTimeout(timer);
43
- }, []);
44
- return (React.createElement(Box, { ref: containerRef, sx: { display: 'flex', flexDirection: 'column', gap: 3 } },
36
+ return (React.createElement(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 3 } },
45
37
  React.createElement(Box, null,
46
38
  React.createElement(Typography, { variant: "subtitle2", gutterBottom: true }, "Default \u2014 all actions"),
47
39
  React.createElement(ContactPopover, { name: "John Doe", email: "john.doe@example.com" },
@@ -69,5 +61,9 @@ export const Default = {
69
61
  React.createElement(ContactPopover.ChatAction, { url: "https://chat.example.com/christopher" }),
70
62
  React.createElement(ContactPopover.VideoAction, { url: "https://meet.example.com/christopher" }),
71
63
  React.createElement(ContactPopover.CalendarAction, { url: "https://calendar.example.com/christopher" }))))));
64
+ },
65
+ play: async ({ canvas, userEvent }) => {
66
+ await userEvent.click(canvas.getByText('John Doe'));
67
+ await screen.findByText('john.doe@example.com');
72
68
  }
73
69
  };
@@ -4,6 +4,6 @@ import { IconButton, useTheme } from '@mui/material';
4
4
  import React from 'react';
5
5
  export const ContactPopoverCalendarAction = ({ url }) => {
6
6
  const theme = useTheme();
7
- return (React.createElement(IconButton, { href: url, size: "small", sx: { border: `1px solid ${theme.palette.divider}` } },
7
+ return (React.createElement(IconButton, { href: url, target: "_blank", rel: "noopener noreferrer", size: "small", sx: { border: `1px solid ${theme.palette.divider}` } },
8
8
  React.createElement(Icon, { icon: CalendarToday, size: 20, color: theme.palette.text.icon })));
9
9
  };
@@ -4,6 +4,6 @@ import { IconButton, useTheme } from '@mui/material';
4
4
  import React from 'react';
5
5
  export const ContactPopoverChatAction = ({ url }) => {
6
6
  const theme = useTheme();
7
- return (React.createElement(IconButton, { href: url, size: "small", sx: { border: `1px solid ${theme.palette.divider}` } },
7
+ return (React.createElement(IconButton, { href: url, target: "_blank", rel: "noopener noreferrer", size: "small", sx: { border: `1px solid ${theme.palette.divider}` } },
8
8
  React.createElement(Icon, { icon: Discuss, size: 20, color: theme.palette.text.icon })));
9
9
  };
@@ -4,7 +4,7 @@ import { useI18n } from 'twake-i18n';
4
4
  export const ContactPopoverEmailAction = ({ url }) => {
5
5
  const theme = useTheme();
6
6
  const { t } = useI18n();
7
- return (React.createElement(Button, { href: url, variant: "outlined", size: "small", fullWidth: true, sx: {
7
+ return (React.createElement(Button, { href: url, target: "_blank", rel: "noopener noreferrer", variant: "outlined", size: "small", fullWidth: true, sx: {
8
8
  justifyContent: 'center',
9
9
  color: theme.palette.text.primary,
10
10
  borderColor: theme.palette.divider
@@ -4,6 +4,6 @@ import { IconButton, useTheme } from '@mui/material';
4
4
  import React from 'react';
5
5
  export const ContactPopoverVideoAction = ({ url }) => {
6
6
  const theme = useTheme();
7
- return (React.createElement(IconButton, { href: url, size: "small", sx: { border: `1px solid ${theme.palette.divider}` } },
7
+ return (React.createElement(IconButton, { href: url, target: "_blank", rel: "noopener noreferrer", size: "small", sx: { border: `1px solid ${theme.palette.divider}` } },
8
8
  React.createElement(Icon, { icon: Camera, size: 20, color: theme.palette.text.icon })));
9
9
  };
@@ -119,7 +119,7 @@ export const ContactPopover = ({ name, email, children, onEmailCopy, onClose, di
119
119
  onMouseLeave: handleMouseLeave
120
120
  }
121
121
  } },
122
- React.createElement(StyledPopoverContent, null,
122
+ React.createElement(StyledPopoverContent, { onClick: event => event.stopPropagation() },
123
123
  React.createElement(CloseButton, { size: "small", onClick: handleClose },
124
124
  React.createElement(Icon, { icon: Cross, size: 16 })),
125
125
  React.createElement(AttendeeInfo, { name: name, email: email, onEmailCopy: onEmailCopy }),
@@ -1,7 +1,9 @@
1
1
  import { CrossMedium, FileTypeFolder, FileTypeText, Icon } from '@linagora/twake-icons';
2
- import { Button, DialogActions, DialogContent, DialogContentText, DialogTitle, Divider, IconButton, List, ListItemButton, ListItemIcon, ListItemText, Stack } from '@mui/material';
2
+ import { Button, DialogActions, DialogContent, DialogContentText, DialogTitle, Divider, IconButton, List, ListItemIcon, Stack } from '@mui/material';
3
3
  import React from 'react';
4
4
  import { Dialog } from './index';
5
+ import ListItemButton from '../ListItemButton';
6
+ import ListItemText from '../ListItemText';
5
7
  const sizes = ['small', 'medium', 'large', 'full'];
6
8
  const meta = {
7
9
  title: 'Dialog',
@@ -0,0 +1,9 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import ListItem from './index';
3
+ import ListItemButton from '../ListItemButton';
4
+ declare const meta: Meta<typeof ListItem>;
5
+ export default meta;
6
+ type Story = StoryObj<typeof meta>;
7
+ export declare const Default: Story;
8
+ export declare const Button: StoryObj<typeof ListItemButton>;
9
+ export declare const Screenshot: Story;
@@ -0,0 +1,135 @@
1
+ import { Comment, Dots, Icon, Pen, People, Right, Trash } from '@linagora/twake-icons';
2
+ import { Box, Checkbox, IconButton, List, ListItemAvatar, ListItemIcon, ListItemSecondaryAction, Radio, Stack } from '@mui/material';
3
+ import React from 'react';
4
+ import ListItem from './index';
5
+ import { Avatar } from '../Avatar';
6
+ import ListItemButton from '../ListItemButton';
7
+ import ListItemText from '../ListItemText';
8
+ import ListSubheader from '../ListSubheader';
9
+ const longText = 'Ada Lovelace wrote the first algorithm meant to be carried out by a machine, long before any computer existed to run it.';
10
+ const layoutArgTypes = {
11
+ gutters: {
12
+ control: 'select',
13
+ options: ['default', 'double', 'disabled']
14
+ },
15
+ size: {
16
+ control: 'select',
17
+ options: ['small', 'medium', 'large']
18
+ },
19
+ ellipsis: { control: 'boolean' },
20
+ dense: { control: 'boolean' },
21
+ divider: { control: 'boolean' },
22
+ alignItems: {
23
+ control: 'select',
24
+ options: ['center', 'flex-start']
25
+ }
26
+ };
27
+ const meta = {
28
+ title: 'ListItem',
29
+ component: ListItem,
30
+ subcomponents: { ListItemButton },
31
+ tags: ['autodocs'],
32
+ argTypes: layoutArgTypes,
33
+ decorators: [
34
+ (Story) => (React.createElement(Box, { sx: { maxWidth: 480 } },
35
+ React.createElement(Story, null)))
36
+ ]
37
+ };
38
+ export default meta;
39
+ const defaultContent = [
40
+ React.createElement(ListItemIcon, { key: "icon" },
41
+ React.createElement(Icon, { icon: Comment })),
42
+ React.createElement(ListItemText, { key: "text", primary: "I'm a primary text" })
43
+ ];
44
+ export const Default = {
45
+ args: {
46
+ gutters: 'default',
47
+ size: 'medium',
48
+ ellipsis: true
49
+ },
50
+ render: args => (React.createElement(List, null,
51
+ React.createElement(ListItem, { ...args }, defaultContent)))
52
+ };
53
+ export const Button = {
54
+ argTypes: {
55
+ ...layoutArgTypes,
56
+ selected: { control: 'boolean' },
57
+ disabled: { control: 'boolean' }
58
+ },
59
+ args: {
60
+ gutters: 'default',
61
+ size: 'medium',
62
+ ellipsis: true
63
+ },
64
+ render: args => (React.createElement(List, null,
65
+ React.createElement(ListItemButton, { ...args }, defaultContent)))
66
+ };
67
+ const Example = ({ title, button = true, dense, selected, disabled, longText: isLongText, iconSize = 16, multipleLeftIcons, multipleRightIcons, withActions, ...props }) => {
68
+ const content = [
69
+ React.createElement(ListItemIcon, { key: "comment" },
70
+ React.createElement(Icon, { icon: Comment, size: iconSize })),
71
+ multipleLeftIcons && (React.createElement(React.Fragment, { key: "left" },
72
+ React.createElement(ListItemIcon, null,
73
+ React.createElement(Icon, { icon: People, size: iconSize })),
74
+ React.createElement(ListItemIcon, null,
75
+ React.createElement(Radio, null)),
76
+ React.createElement(ListItemIcon, null,
77
+ React.createElement(Checkbox, null)))),
78
+ React.createElement(ListItemText, { key: "text", primary: isLongText ? longText : "I'm a primary text" }),
79
+ multipleRightIcons && (React.createElement(React.Fragment, { key: "right" },
80
+ React.createElement(ListItemIcon, null,
81
+ React.createElement(Icon, { icon: Right, size: iconSize })),
82
+ React.createElement(ListItemIcon, null,
83
+ React.createElement(Radio, null)),
84
+ React.createElement(ListItemIcon, null,
85
+ React.createElement(Checkbox, null)))),
86
+ withActions && (React.createElement(ListItemSecondaryAction, { key: "actions" },
87
+ React.createElement(IconButton, null,
88
+ React.createElement(Icon, { icon: Pen })),
89
+ React.createElement(IconButton, null,
90
+ React.createElement(Icon, { icon: Trash })),
91
+ React.createElement(IconButton, null,
92
+ React.createElement(Icon, { icon: Dots }))))
93
+ ];
94
+ return (React.createElement("section", null,
95
+ React.createElement("h3", null, title),
96
+ React.createElement(List, { dense: dense, subheader: React.createElement(ListSubheader, null, "Section 1") }, button ? (React.createElement(ListItemButton, { selected: selected, disabled: disabled, ...props }, content)) : (React.createElement(ListItem, { ...props }, content)))));
97
+ };
98
+ // Visual Regression - Combined view for Argos testing
99
+ export const Screenshot = {
100
+ tags: ['argos'],
101
+ render: () => (React.createElement(Stack, { spacing: 4 },
102
+ React.createElement(Example, { title: "Default" }),
103
+ React.createElement(Example, { title: "Dense", dense: true }),
104
+ React.createElement(Example, { title: "Long text", longText: true }),
105
+ React.createElement(Example, { title: "Long text without ellipsis", longText: true, ellipsis: false }),
106
+ React.createElement(Example, { title: "Disabled gutters", gutters: "disabled" }),
107
+ React.createElement(Example, { title: "Double gutters", gutters: "double" }),
108
+ React.createElement(Example, { title: "Small", size: "small" }),
109
+ React.createElement(Example, { title: "Large", size: "large" }),
110
+ React.createElement(Example, { title: "Dense small", dense: true, size: "small" }),
111
+ React.createElement(Example, { title: "Dense large", dense: true, size: "large" }),
112
+ React.createElement(Example, { title: "Big icons", iconSize: 32 }),
113
+ React.createElement(Example, { title: "Small icons", iconSize: 8 }),
114
+ React.createElement(Example, { title: "Multiple left icons", multipleLeftIcons: true }),
115
+ React.createElement(Example, { title: "Multiple right icons", multipleRightIcons: true }),
116
+ React.createElement(Example, { title: "Multiple right icons, double gutters", multipleRightIcons: true, gutters: "double" }),
117
+ React.createElement(Example, { title: "With actions", withActions: true, longText: true }),
118
+ React.createElement(Example, { title: "With actions, double gutters", withActions: true, longText: true, gutters: "double" }),
119
+ React.createElement("section", null,
120
+ React.createElement("h3", null, "With avatar"),
121
+ React.createElement(List, null,
122
+ React.createElement(ListItemButton, null,
123
+ React.createElement(ListItemAvatar, null,
124
+ React.createElement(Avatar, null, "Ada Lovelace")),
125
+ React.createElement(ListItemText, { primary: "Ada Lovelace", secondary: longText })),
126
+ React.createElement(ListItemButton, { alignItems: "flex-start", ellipsis: false },
127
+ React.createElement(ListItemAvatar, null,
128
+ React.createElement(Avatar, null, "Ada Lovelace")),
129
+ React.createElement(ListItemText, { primary: "Ada Lovelace", secondary: longText })))),
130
+ React.createElement(Example, { title: "Selected", selected: true }),
131
+ React.createElement(Example, { title: "Disabled", disabled: true }),
132
+ React.createElement(Example, { title: "Not a button", button: false }),
133
+ React.createElement(Example, { title: "Not a button, dense small", button: false, dense: true, size: "small" }),
134
+ React.createElement(Example, { title: "Not a button, with actions", button: false, withActions: true })))
135
+ };
@@ -0,0 +1,24 @@
1
+ import { SxProps, Theme } from '@mui/material/styles';
2
+ import React from 'react';
3
+ export type ListItemGutters = 'default' | 'double' | 'disabled';
4
+ export type ListItemSize = 'small' | 'medium' | 'large';
5
+ export interface ListItemLayoutProps {
6
+ gutters?: ListItemGutters;
7
+ size?: ListItemSize;
8
+ ellipsis?: boolean;
9
+ }
10
+ interface ListItemRowOptions extends ListItemLayoutProps {
11
+ className?: string;
12
+ disableGutters?: boolean;
13
+ sx?: SxProps<Theme>;
14
+ children?: React.ReactNode;
15
+ }
16
+ export interface ListItemRow {
17
+ className: string;
18
+ disableGutters: boolean;
19
+ sx: SxProps<Theme>;
20
+ action: React.ReactElement | null;
21
+ content: React.ReactNode;
22
+ }
23
+ export declare function computeListItemRow({ className, gutters, size, ellipsis, disableGutters, sx, children }: ListItemRowOptions): ListItemRow;
24
+ export {};
@@ -0,0 +1,30 @@
1
+ import { isMuiElement } from '@mui/material/utils';
2
+ import cx from 'classnames';
3
+ import { Children, cloneElement, isValidElement } from 'react';
4
+ import ListItemText from '../ListItemText';
5
+ const ACTION_BUTTON_SIZE = 48;
6
+ export function computeListItemRow({ className, gutters = 'default', size = 'medium', ellipsis = true, disableGutters = false, sx, children }) {
7
+ const items = Children.toArray(children);
8
+ const lastItem = items.at(-1);
9
+ const action = isValidElement(lastItem) &&
10
+ isMuiElement(lastItem, ['ListItemSecondaryAction'])
11
+ ? lastItem
12
+ : null;
13
+ const actionPadding = action
14
+ ? Children.count(action.props.children) * ACTION_BUTTON_SIZE +
15
+ (gutters === 'double' ? 24 : 8)
16
+ : 0;
17
+ return {
18
+ className: cx(className, size, { doubleGutters: gutters === 'double' }),
19
+ disableGutters: disableGutters || gutters === 'disabled',
20
+ sx: [
21
+ // && outranks the theme's .doubleGutters padding
22
+ actionPadding > 0 && { '&&': { paddingRight: `${actionPadding}px` } },
23
+ sx ?? false
24
+ ].flat(),
25
+ action,
26
+ content: (action ? items.slice(0, -1) : items).map(item => isValidElement(item) && item.type === ListItemText
27
+ ? cloneElement(item, { ellipsis })
28
+ : item)
29
+ };
30
+ }
@@ -0,0 +1,7 @@
1
+ import { ListItemProps as MuiListItemProps } from '@mui/material';
2
+ import React from 'react';
3
+ import { ListItemLayoutProps } from './helpers';
4
+ export type { ListItemGutters, ListItemSize } from './helpers';
5
+ export type ListItemProps = Omit<MuiListItemProps, 'ref'> & ListItemLayoutProps;
6
+ declare const ListItem: React.ForwardRefExoticComponent<Omit<MuiListItemProps, "ref"> & ListItemLayoutProps & React.RefAttributes<HTMLLIElement>>;
7
+ export default ListItem;
@@ -0,0 +1,19 @@
1
+ import { ListItem as MuiListItem } from '@mui/material';
2
+ import React, { forwardRef } from 'react';
3
+ import { computeListItemRow } from './helpers';
4
+ const ListItem = forwardRef(({ className, gutters, size, ellipsis, disableGutters, sx, children, ...props }, ref) => {
5
+ const row = computeListItemRow({
6
+ className,
7
+ gutters,
8
+ size,
9
+ ellipsis,
10
+ disableGutters,
11
+ sx,
12
+ children
13
+ });
14
+ return (React.createElement(MuiListItem, { ref: ref, ...props, className: row.className, disableGutters: row.disableGutters, sx: row.sx },
15
+ row.content,
16
+ row.action));
17
+ });
18
+ ListItem.displayName = 'ListItem';
19
+ export default ListItem;
@@ -0,0 +1,6 @@
1
+ import { ListItemButtonProps as MuiListItemButtonProps } from '@mui/material';
2
+ import React from 'react';
3
+ import { ListItemLayoutProps } from '../ListItem/helpers';
4
+ export type ListItemButtonProps = Omit<MuiListItemButtonProps, 'ref'> & ListItemLayoutProps;
5
+ declare const ListItemButton: React.ForwardRefExoticComponent<Omit<MuiListItemButtonProps, "ref"> & ListItemLayoutProps & React.RefAttributes<HTMLDivElement>>;
6
+ export default ListItemButton;
@@ -0,0 +1,23 @@
1
+ import { ListItem, ListItemButton as MuiListItemButton } from '@mui/material';
2
+ import React, { forwardRef } from 'react';
3
+ import { computeListItemRow } from '../ListItem/helpers';
4
+ const ListItemButton = forwardRef(({ className, gutters, size, ellipsis, disableGutters, sx, children, ...props }, ref) => {
5
+ const row = computeListItemRow({
6
+ className,
7
+ gutters,
8
+ size,
9
+ ellipsis,
10
+ disableGutters,
11
+ sx,
12
+ children
13
+ });
14
+ const button = (React.createElement(MuiListItemButton, { ref: ref, ...props, className: row.className, disableGutters: row.disableGutters, sx: row.sx }, row.content));
15
+ if (row.action === null)
16
+ return button;
17
+ // Keeps the action out of the button, so clicking it does not click the row
18
+ return (React.createElement(ListItem, { disablePadding: true },
19
+ button,
20
+ row.action));
21
+ });
22
+ ListItemButton.displayName = 'ListItemButton';
23
+ export default ListItemButton;
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import ListItemText from './index';
3
+ declare const meta: Meta<typeof ListItemText>;
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,58 @@
1
+ import { Box, List, Stack, Typography } from '@mui/material';
2
+ import React from 'react';
3
+ import ListItemText from './index';
4
+ const longText = 'Ada Lovelace wrote the first algorithm meant to be carried out by a machine, long before any computer existed to run it.';
5
+ const meta = {
6
+ title: 'ListItemText',
7
+ component: ListItemText,
8
+ tags: ['autodocs'],
9
+ argTypes: {
10
+ primary: { control: 'text' },
11
+ secondary: { control: 'text' },
12
+ ellipsis: { control: 'boolean' },
13
+ inset: { control: 'boolean' },
14
+ disableTypography: { control: 'boolean' }
15
+ },
16
+ decorators: [
17
+ (Story) => (React.createElement(Box, { sx: { maxWidth: 480 } },
18
+ React.createElement(Story, null)))
19
+ ]
20
+ };
21
+ export default meta;
22
+ export const Default = {
23
+ args: {
24
+ primary: "I'm a primary text",
25
+ secondary: "I'm a secondary text",
26
+ ellipsis: true
27
+ }
28
+ };
29
+ const Row = ({ title, children }) => (React.createElement("section", null,
30
+ React.createElement("h3", null, title),
31
+ children));
32
+ // Visual Regression - Combined view for Argos testing
33
+ export const Screenshot = {
34
+ tags: ['argos'],
35
+ render: () => (React.createElement(Stack, { spacing: 4 },
36
+ React.createElement(Row, { title: "Primary text" },
37
+ React.createElement(ListItemText, { primary: "I'm a list item text" })),
38
+ React.createElement(Row, { title: "Secondary text" },
39
+ React.createElement(ListItemText, { primary: "I'm a primary text", secondary: "I'm a secondary text" })),
40
+ React.createElement(Row, { title: "Custom" },
41
+ React.createElement(ListItemText, null,
42
+ React.createElement(Typography, { variant: "body1" }, "I'm a primary text"),
43
+ React.createElement(Typography, { component: "a", href: "http://cozy.io", variant: "caption", color: "textSecondary" }, longText))),
44
+ React.createElement(Row, { title: "Ellipsis" },
45
+ React.createElement(ListItemText, { primary: longText, secondary: longText })),
46
+ React.createElement(Row, { title: "Without ellipsis" },
47
+ React.createElement(ListItemText, { primary: longText, secondary: longText, ellipsis: false })),
48
+ React.createElement(Row, { title: "Dense" },
49
+ React.createElement(List, { dense: true, disablePadding: true },
50
+ React.createElement(ListItemText, { primary: "I'm a primary text", secondary: "I'm a secondary text" }))),
51
+ React.createElement(Row, { title: "Inset" },
52
+ React.createElement(ListItemText, { inset: true, primary: "I'm a primary text" })),
53
+ React.createElement(Row, { title: "Slot props" },
54
+ React.createElement(ListItemText, { primary: "I'm a primary text", secondary: "I'm a secondary text", slotProps: {
55
+ primary: { variant: 'caption' },
56
+ secondary: { color: 'inherit', variant: 'body1' }
57
+ } }))))
58
+ };
@@ -0,0 +1,7 @@
1
+ import { ListItemTextProps as MuiListItemTextProps } from '@mui/material';
2
+ import React from 'react';
3
+ export interface ListItemTextProps extends Omit<MuiListItemTextProps, 'ref'> {
4
+ ellipsis?: boolean;
5
+ }
6
+ declare const ListItemText: React.ForwardRefExoticComponent<ListItemTextProps & React.RefAttributes<HTMLDivElement>>;
7
+ export default ListItemText;
@@ -0,0 +1,23 @@
1
+ import { ListItemText as MuiListItemText } from '@mui/material';
2
+ import React, { forwardRef } from 'react';
3
+ const ListItemText = forwardRef(({ ellipsis = true, slotProps, ...props }, ref) => {
4
+ const primarySlot = slotProps?.primary;
5
+ return (React.createElement(MuiListItemText, { ref: ref, ...props,
6
+ // A primary or secondary slot replaces these defaults, ellipsis included
7
+ slotProps: {
8
+ ...slotProps,
9
+ primary: typeof primarySlot === 'function'
10
+ ? primarySlot
11
+ : {
12
+ // Keeps a caption primary out of the theme's grey caption rule
13
+ color: 'inherit',
14
+ ...(primarySlot ?? { noWrap: ellipsis })
15
+ },
16
+ secondary: slotProps?.secondary ?? {
17
+ variant: 'caption',
18
+ noWrap: ellipsis
19
+ }
20
+ } }));
21
+ });
22
+ ListItemText.displayName = 'ListItemText';
23
+ export default ListItemText;
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import ListSubheader from './index';
3
+ declare const meta: Meta<typeof ListSubheader>;
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,59 @@
1
+ import { FileTypeFolder, Icon } from '@linagora/twake-icons';
2
+ import { Box, List, ListItemIcon, Stack } from '@mui/material';
3
+ import React from 'react';
4
+ import ListSubheader from './index';
5
+ import ListItemButton from '../ListItemButton';
6
+ import ListItemText from '../ListItemText';
7
+ const meta = {
8
+ title: 'ListSubheader',
9
+ component: ListSubheader,
10
+ tags: ['autodocs'],
11
+ argTypes: {
12
+ gutters: {
13
+ control: 'select',
14
+ options: ['default', 'double', 'disabled']
15
+ },
16
+ color: {
17
+ control: 'select',
18
+ options: ['default', 'primary', 'inherit']
19
+ },
20
+ inset: { control: 'boolean' },
21
+ disableSticky: { control: 'boolean' }
22
+ },
23
+ decorators: [
24
+ (Story) => (React.createElement(Box, { sx: { maxWidth: 480 } },
25
+ React.createElement(Story, null)))
26
+ ]
27
+ };
28
+ export default meta;
29
+ const Example = props => (React.createElement(List, { subheader: React.createElement(ListSubheader, { ...props }, "This is the subheader") },
30
+ React.createElement(ListItemButton, null,
31
+ React.createElement(ListItemIcon, null,
32
+ React.createElement(Icon, { icon: FileTypeFolder, size: 32 })),
33
+ React.createElement(ListItemText, { primary: "I'm a primary text" }))));
34
+ export const Default = {
35
+ args: {
36
+ gutters: 'default'
37
+ },
38
+ render: args => React.createElement(Example, { ...args })
39
+ };
40
+ const Row = ({ title, children }) => (React.createElement("section", null,
41
+ React.createElement("h3", null, title),
42
+ children));
43
+ // Visual Regression - Combined view for Argos testing
44
+ export const Screenshot = {
45
+ tags: ['argos'],
46
+ render: () => (React.createElement(Stack, { spacing: 4 },
47
+ React.createElement(Row, { title: "Default gutters" },
48
+ React.createElement(Example, null)),
49
+ React.createElement(Row, { title: "Disabled gutters" },
50
+ React.createElement(Example, { gutters: "disabled" })),
51
+ React.createElement(Row, { title: "Double gutters" },
52
+ React.createElement(Example, { gutters: "double" })),
53
+ React.createElement(Row, { title: "Inset" },
54
+ React.createElement(Example, { inset: true })),
55
+ React.createElement(Row, { title: "Not sticky" },
56
+ React.createElement(Example, { disableSticky: true })),
57
+ React.createElement(Row, { title: "Primary color" },
58
+ React.createElement(Example, { color: "primary" }))))
59
+ };
@@ -0,0 +1,8 @@
1
+ import { ListSubheaderProps as MuiListSubheaderProps } from '@mui/material';
2
+ import React from 'react';
3
+ import { ListItemGutters } from '../ListItem/helpers';
4
+ export interface ListSubheaderProps extends Omit<MuiListSubheaderProps, 'ref'> {
5
+ gutters?: ListItemGutters;
6
+ }
7
+ declare const ListSubheader: React.ForwardRefExoticComponent<ListSubheaderProps & React.RefAttributes<HTMLLIElement>>;
8
+ export default ListSubheader;
@@ -0,0 +1,6 @@
1
+ import { ListSubheader as MuiListSubheader } from '@mui/material';
2
+ import cx from 'classnames';
3
+ import React, { forwardRef } from 'react';
4
+ const ListSubheader = forwardRef(({ className, gutters = 'default', disableGutters, ...props }, ref) => (React.createElement(MuiListSubheader, { ref: ref, ...props, className: cx(className, { doubleGutters: gutters === 'double' }), disableGutters: disableGutters || gutters === 'disabled' })));
5
+ ListSubheader.displayName = 'ListSubheader';
6
+ export default ListSubheader;
@@ -2,7 +2,7 @@ import { Theme } from '@mui/material/styles';
2
2
  import React from 'react';
3
3
  declare const NavRoot: import("@emotion/styled").StyledComponent<import("@mui/material").ListOwnProps & Omit<import("@mui/material").ListOwnProps, keyof import("@mui/material").ListOwnProps> & import("@mui/material/OverridableComponent").CommonProps & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>, "ref"> & {
4
4
  ref?: ((instance: HTMLUListElement | null) => void) | React.RefObject<HTMLUListElement> | null | undefined;
5
- }, "style" | "className" | "children" | "classes" | "sx" | "dense" | "disablePadding" | "subheader"> & import("@mui/system").MUIStyledCommonProps<Theme>, {}, {}>;
5
+ }, "style" | "className" | "children" | "dense" | "disablePadding" | "classes" | "sx" | "subheader"> & import("@mui/system").MUIStyledCommonProps<Theme>, {}, {}>;
6
6
  export type NavProps = React.ComponentProps<typeof NavRoot>;
7
7
  export declare const Nav: (props: NavProps) => React.ReactElement;
8
8
  export {};
@@ -1,7 +1,7 @@
1
- import { ListItem } from '@mui/material';
2
1
  import React, { Children, isValidElement, useState } from 'react';
3
2
  import { useBreakpoints } from '../../hooks/useBreakpoints';
4
3
  import DropdownText from '../DropdownText';
4
+ import ListItem from '../ListItem';
5
5
  export const NavDesktopDropdown = ({ label, children, defaultOpen = true, limit = 5 }) => {
6
6
  const { isDesktop } = useBreakpoints();
7
7
  const [open, setOpen] = useState(defaultOpen);
@@ -10,12 +10,7 @@ export const NavDesktopDropdown = ({ label, children, defaultOpen = true, limit
10
10
  if (!isDesktop)
11
11
  return null;
12
12
  return (React.createElement(React.Fragment, null,
13
- React.createElement(ListItem, { sx: {
14
- minHeight: 48,
15
- py: 1,
16
- px: 2,
17
- cursor: isActivated ? 'pointer' : undefined
18
- } },
13
+ React.createElement(ListItem, { size: "small", sx: { cursor: isActivated ? 'pointer' : undefined } },
19
14
  React.createElement(DropdownText, { variant: "caption", color: "textSecondary", spaceBetween: true, onClick: isActivated ? onToggle : undefined, innerIconProps: {
20
15
  rotate: open ? 0 : -90,
21
16
  display: isActivated ? undefined : 'none'
@@ -4,6 +4,8 @@ import { styled } from '@mui/material/styles';
4
4
  import React from 'react';
5
5
  const NavIconRoot = styled(ListItemIcon)(({ theme }) => ({
6
6
  minWidth: 0,
7
+ width: 'auto',
8
+ height: 'auto',
7
9
  marginRight: 12,
8
10
  color: theme.vars.palette.text.primary,
9
11
  [theme.breakpoints.down('lg')]: {
@@ -2,7 +2,7 @@ import { Theme } from '@mui/material/styles';
2
2
  import React from 'react';
3
3
  export declare const NavItem: import("@emotion/styled").StyledComponent<import("@mui/material").ListItemOwnProps & import("@mui/material/OverridableComponent").CommonProps & Omit<Omit<React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "ref"> & {
4
4
  ref?: ((instance: HTMLLIElement | null) => void) | React.RefObject<HTMLLIElement> | null | undefined;
5
- }, "style" | "className" | "children" | "classes" | "sx" | "alignItems" | "dense" | "divider" | "slotProps" | "slots" | "disableGutters" | "disablePadding" | "secondaryAction"> & import("@mui/system").MUIStyledCommonProps<Theme> & {
5
+ }, "style" | "className" | "children" | "alignItems" | "dense" | "disablePadding" | "disableGutters" | "classes" | "sx" | "divider" | "slotProps" | "slots" | "secondaryAction"> & import("@mui/system").MUIStyledCommonProps<Theme> & {
6
6
  secondary?: boolean;
7
7
  }, {}, {}>;
8
8
  export type NavItemProps = React.ComponentProps<typeof NavItem>;
@@ -5,6 +5,7 @@ export const NavItem = styled(ListItem, {
5
5
  })(({ theme, secondary }) => ({
6
6
  padding: 0,
7
7
  height: 36,
8
+ minHeight: 0,
8
9
  [theme.breakpoints.down('lg')]: {
9
10
  display: 'block',
10
11
  height: 'auto',
@@ -5,6 +5,8 @@ export const NavLink = styled(ListItemButton)(({ theme }) => ({
5
5
  margin: '0 16px',
6
6
  padding: '0 8px',
7
7
  height: '100%',
8
+ minHeight: 0,
9
+ gap: 0,
8
10
  borderRadius: 8,
9
11
  lineHeight: 1.375,
10
12
  color: theme.vars.palette.text.primary,
package/dist/index.d.ts CHANGED
@@ -13,6 +13,10 @@ export { Dialog, default as DialogDefault } from './components/Dialog';
13
13
  export { ContactPopover, default as ContactPopoverDefault } from './components/ContactPopover';
14
14
  export { default as DropdownButton } from './components/DropdownButton';
15
15
  export { default as DropdownText } from './components/DropdownText';
16
+ export { default as ListItem } from './components/ListItem';
17
+ export { default as ListItemButton } from './components/ListItemButton';
18
+ export { default as ListItemText } from './components/ListItemText';
19
+ export { default as ListSubheader } from './components/ListSubheader';
16
20
  export { Tabs, default as TabsDefault } from './components/Tabs';
17
21
  export { Switch, default as SwitchDefault } from './components/Switch';
18
22
  export { SearchBar, default as SearchBarDefault } from './components/SearchBar';
@@ -45,6 +49,10 @@ export type { ChipProps } from './components/Chip';
45
49
  export type { DialogProps, DialogSize } from './components/Dialog';
46
50
  export type { DropdownButtonProps } from './components/DropdownButton';
47
51
  export type { DropdownTextProps, DropdownTextVariant } from './components/DropdownText';
52
+ export type { ListItemProps, ListItemGutters, ListItemSize } from './components/ListItem';
53
+ export type { ListItemButtonProps } from './components/ListItemButton';
54
+ export type { ListItemTextProps } from './components/ListItemText';
55
+ export type { ListSubheaderProps } from './components/ListSubheader';
48
56
  export type { TabsProps } from './components/Tabs';
49
57
  export type { SwitchProps } from './components/Switch';
50
58
  export type { SearchBarProps } from './components/SearchBar/types';
package/dist/index.js CHANGED
@@ -16,6 +16,10 @@ export { Dialog, default as DialogDefault } from './components/Dialog';
16
16
  export { ContactPopover, default as ContactPopoverDefault } from './components/ContactPopover';
17
17
  export { default as DropdownButton } from './components/DropdownButton';
18
18
  export { default as DropdownText } from './components/DropdownText';
19
+ export { default as ListItem } from './components/ListItem';
20
+ export { default as ListItemButton } from './components/ListItemButton';
21
+ export { default as ListItemText } from './components/ListItemText';
22
+ export { default as ListSubheader } from './components/ListSubheader';
19
23
  export { Tabs, default as TabsDefault } from './components/Tabs';
20
24
  export { Switch, default as SwitchDefault } from './components/Switch';
21
25
  export { SearchBar, default as SearchBarDefault } from './components/SearchBar';
@@ -5,6 +5,7 @@ import { checkboxClasses } from '@mui/material/Checkbox';
5
5
  import { dialogTitleClasses } from '@mui/material/DialogTitle';
6
6
  import { formHelperTextClasses } from '@mui/material/FormHelperText';
7
7
  import { formLabelClasses } from '@mui/material/FormLabel';
8
+ import { listItemButtonClasses } from '@mui/material/ListItemButton';
8
9
  import { listItemIconClasses } from '@mui/material/ListItemIcon';
9
10
  import { listItemTextClasses } from '@mui/material/ListItemText';
10
11
  import { outlinedInputClasses } from '@mui/material/OutlinedInput';
@@ -97,6 +98,38 @@ const radioColors = [
97
98
  'warning',
98
99
  'info'
99
100
  ];
101
+ const listItemRoot = {
102
+ gap: 16,
103
+ variants: [
104
+ {
105
+ props: ({ dense, disablePadding }) => !dense && !disablePadding,
106
+ style: {
107
+ paddingTop: 12,
108
+ paddingBottom: 12,
109
+ minHeight: 56,
110
+ '&.small': { paddingTop: 8, paddingBottom: 8, minHeight: 48 },
111
+ '&.large': { paddingTop: 16, paddingBottom: 16, minHeight: 64 }
112
+ }
113
+ },
114
+ {
115
+ props: ({ dense, disablePadding }) => dense && !disablePadding,
116
+ style: {
117
+ paddingTop: 8,
118
+ paddingBottom: 8,
119
+ minHeight: 48,
120
+ '&.small': { paddingTop: 4, paddingBottom: 4, minHeight: 40 },
121
+ '&.large': { paddingTop: 12, paddingBottom: 12, minHeight: 56 }
122
+ }
123
+ },
124
+ {
125
+ props: { disableGutters: false },
126
+ style: {
127
+ '&.doubleGutters': { paddingLeft: 32, paddingRight: 32 },
128
+ [`& > .${listItemIconClasses.root}:last-child`]: { marginRight: -8 }
129
+ }
130
+ }
131
+ ]
132
+ };
100
133
  export const overrides = {
101
134
  MuiButton: {
102
135
  defaultProps: {
@@ -1015,6 +1048,80 @@ export const overrides = {
1015
1048
  })
1016
1049
  }
1017
1050
  },
1051
+ MuiListItem: {
1052
+ styleOverrides: {
1053
+ root: listItemRoot
1054
+ }
1055
+ },
1056
+ MuiListItemButton: {
1057
+ styleOverrides: {
1058
+ root: ({ theme }) => ({
1059
+ ...listItemRoot,
1060
+ [`&.${listItemButtonClasses.selected}, &.${listItemButtonClasses.selected}:hover, &.${listItemButtonClasses.focusVisible}, &.${listItemButtonClasses.selected}.${listItemButtonClasses.focusVisible}`]: {
1061
+ backgroundColor: theme.vars.palette.action.selected
1062
+ },
1063
+ [`&.${listItemButtonClasses.disabled}`]: {
1064
+ opacity: 0.5
1065
+ }
1066
+ })
1067
+ }
1068
+ },
1069
+ MuiListItemIcon: {
1070
+ styleOverrides: {
1071
+ root: ({ theme }) => ({
1072
+ minWidth: 'auto',
1073
+ width: 32,
1074
+ height: 32,
1075
+ alignItems: 'center',
1076
+ justifyContent: 'center',
1077
+ color: theme.vars.palette.text.icon
1078
+ })
1079
+ }
1080
+ },
1081
+ MuiListSubheader: {
1082
+ styleOverrides: {
1083
+ root: ({ theme }) => ({
1084
+ ...theme.typography.subtitle2,
1085
+ paddingTop: 8,
1086
+ paddingBottom: 8,
1087
+ marginBottom: '0.5rem',
1088
+ backgroundColor: theme.vars.palette.background.contrast,
1089
+ variants: [
1090
+ {
1091
+ props: { disableSticky: false },
1092
+ style: { backgroundColor: theme.vars.palette.background.default }
1093
+ },
1094
+ {
1095
+ props: { disableGutters: false },
1096
+ style: {
1097
+ '&.doubleGutters': { paddingLeft: 32, paddingRight: 32 }
1098
+ }
1099
+ }
1100
+ ]
1101
+ })
1102
+ }
1103
+ },
1104
+ MuiListItemText: {
1105
+ styleOverrides: {
1106
+ root: {
1107
+ marginTop: 1,
1108
+ marginBottom: 1
1109
+ },
1110
+ secondary: {
1111
+ marginTop: 1
1112
+ }
1113
+ }
1114
+ },
1115
+ MuiListItemSecondaryAction: {
1116
+ styleOverrides: {
1117
+ root: {
1118
+ right: 0,
1119
+ '.doubleGutters > &, .doubleGutters ~ &': {
1120
+ marginRight: 16
1121
+ }
1122
+ }
1123
+ }
1124
+ },
1018
1125
  MuiMenu: {
1019
1126
  styleOverrides: {
1020
1127
  paper: { maxWidth: 320 }
@@ -1030,6 +1137,8 @@ export const overrides = {
1030
1137
  wordBreak: 'break-word',
1031
1138
  [`& .${listItemIconClasses.root}`]: {
1032
1139
  minWidth: 'auto',
1140
+ width: 'auto',
1141
+ height: 'auto',
1033
1142
  color: theme.vars.palette.text.icon
1034
1143
  },
1035
1144
  [`& .${listItemTextClasses.root}`]: {
@@ -0,0 +1,12 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import React from 'react';
3
+ import { ListItemLayoutProps } from '../components/ListItem/helpers';
4
+ interface DemoProps extends ListItemLayoutProps {
5
+ dense?: boolean;
6
+ }
7
+ declare const Demo: React.FC<DemoProps>;
8
+ declare const meta: Meta<typeof Demo>;
9
+ export default meta;
10
+ type Story = StoryObj<typeof meta>;
11
+ export declare const Default: Story;
12
+ export declare const Screenshot: Story;
@@ -0,0 +1,141 @@
1
+ import { Comment, Dots, FileTypeFolder, FileTypeText, Help, Icon, LinkOut, MagicTrick, People, PieChart, Right } from '@linagora/twake-icons';
2
+ import { Box, Divider, IconButton, List, ListItemIcon, ListItemSecondaryAction, Radio, Stack, Typography } from '@mui/material';
3
+ import React from 'react';
4
+ import ListItemButton from '../components/ListItemButton';
5
+ import ListItemText from '../components/ListItemText';
6
+ import ListSubheader from '../components/ListSubheader';
7
+ const longText = 'Ada Lovelace wrote the first algorithm meant to be carried out by a machine, long before any computer existed to run it.';
8
+ const Demo = ({ dense, ...itemProps }) => (React.createElement(React.Fragment, null,
9
+ React.createElement(List, { dense: dense, subheader: React.createElement(ListSubheader, null, "Section 1") },
10
+ React.createElement(ListItemButton, { ...itemProps },
11
+ React.createElement(ListItemIcon, null,
12
+ React.createElement(Icon, { icon: FileTypeFolder, size: 32 })),
13
+ React.createElement(ListItemText, { primary: "I'm a primary text" }),
14
+ React.createElement(ListItemText, { secondary: "Metadata" }),
15
+ React.createElement(ListItemText, { secondary: "Metadata" })),
16
+ React.createElement(Divider, { component: "li", variant: "inset" }),
17
+ React.createElement(ListItemButton, { ...itemProps },
18
+ React.createElement(ListItemIcon, null,
19
+ React.createElement(Icon, { icon: FileTypeText, size: 32 })),
20
+ React.createElement(ListItemText, { primary: "I'm a primary text", secondary: "I'm a secondary text" })),
21
+ React.createElement(Divider, { component: "li", variant: "inset" }),
22
+ React.createElement(ListItemButton, { ...itemProps },
23
+ React.createElement(ListItemIcon, null,
24
+ React.createElement(Icon, { icon: FileTypeText, size: 32 })),
25
+ React.createElement(ListItemText, { primary: "I'm a primary text", secondary: "I'm a secondary text", slotProps: {
26
+ primary: { variant: 'caption' },
27
+ secondary: { color: 'inherit', variant: dense ? 'body2' : 'body1' }
28
+ } }))),
29
+ React.createElement(List, { dense: dense, subheader: React.createElement(ListSubheader, null, "Section 2") },
30
+ React.createElement(ListItemButton, { ...itemProps },
31
+ React.createElement(ListItemIcon, null,
32
+ React.createElement(Icon, { icon: Comment })),
33
+ React.createElement(ListItemText, { primary: "Support" }),
34
+ React.createElement(ListItemSecondaryAction, null,
35
+ React.createElement(IconButton, null,
36
+ React.createElement(Icon, { icon: Dots })))),
37
+ React.createElement(Divider, { component: "li", variant: "inset" }),
38
+ React.createElement(ListItemButton, { ...itemProps },
39
+ React.createElement(ListItemIcon, null,
40
+ React.createElement(Icon, { icon: MagicTrick })),
41
+ React.createElement(ListItemText, { primary: "Double actions" }),
42
+ React.createElement(ListItemSecondaryAction, null,
43
+ React.createElement(IconButton, null,
44
+ React.createElement(Icon, { icon: Right })),
45
+ React.createElement(IconButton, null,
46
+ React.createElement(Icon, { icon: Dots }))))),
47
+ React.createElement(Divider, null),
48
+ React.createElement(List, { dense: dense },
49
+ React.createElement(ListItemButton, { ...itemProps },
50
+ React.createElement(ListItemIcon, null,
51
+ React.createElement(Icon, { icon: People })),
52
+ React.createElement(ListItemText, { primary: "Profil" }),
53
+ React.createElement(ListItemIcon, null,
54
+ React.createElement(Icon, { icon: Right }))),
55
+ React.createElement(Divider, { component: "li", variant: "inset" }),
56
+ React.createElement(ListItemButton, { ...itemProps },
57
+ React.createElement(ListItemIcon, null,
58
+ React.createElement(Icon, { icon: People })),
59
+ React.createElement(ListItemText, { primary: longText, secondary: longText }),
60
+ React.createElement(ListItemIcon, null,
61
+ React.createElement(Radio, null))),
62
+ React.createElement(Divider, { component: "li", variant: "inset" }),
63
+ React.createElement(ListItemButton, { ...itemProps },
64
+ React.createElement(ListItemIcon, null,
65
+ React.createElement(Icon, { icon: Help })),
66
+ React.createElement(ListItemText, { primary: "Help" }),
67
+ React.createElement(ListItemIcon, null,
68
+ React.createElement(Icon, { icon: LinkOut }))),
69
+ React.createElement(Divider, { component: "li", variant: "inset" }),
70
+ React.createElement(ListItemButton, { ...itemProps },
71
+ React.createElement(ListItemIcon, null,
72
+ React.createElement(Icon, { icon: PieChart })),
73
+ React.createElement(ListItemText, { primary: "Storage" }),
74
+ React.createElement(Typography, { variant: "body2", color: "textSecondary" }, "82% used"),
75
+ React.createElement(ListItemIcon, null,
76
+ React.createElement(Icon, { icon: Right }))))));
77
+ const HighlightedItem = () => (React.createElement(List, null,
78
+ React.createElement(ListItemButton, null,
79
+ React.createElement(ListItemIcon, null,
80
+ React.createElement(Icon, { icon: FileTypeFolder, size: 32 })),
81
+ React.createElement(ListItemText, { primary: "I'm a primary text" })),
82
+ React.createElement(Divider, { variant: "inset" }),
83
+ React.createElement(ListItemButton, { selected: true },
84
+ React.createElement(ListItemIcon, null,
85
+ React.createElement(Icon, { icon: FileTypeText, size: 32 })),
86
+ React.createElement(ListItemText, { primary: "I'm a primary text", secondary: "I'm a secondary text" })),
87
+ React.createElement(Divider, { variant: "inset" }),
88
+ React.createElement(ListItemButton, null,
89
+ React.createElement(ListItemIcon, null,
90
+ React.createElement(Icon, { icon: FileTypeText, size: 32 })),
91
+ React.createElement(ListItemText, { primary: "I'm a primary text" }))));
92
+ const meta = {
93
+ title: 'List',
94
+ component: Demo,
95
+ tags: ['autodocs'],
96
+ argTypes: {
97
+ dense: { control: 'boolean' },
98
+ gutters: {
99
+ control: 'select',
100
+ options: ['default', 'double', 'disabled']
101
+ },
102
+ size: {
103
+ control: 'select',
104
+ options: ['small', 'medium', 'large']
105
+ }
106
+ },
107
+ decorators: [
108
+ (Story) => (React.createElement(Box, { sx: { maxWidth: 480 } },
109
+ React.createElement(Story, null)))
110
+ ]
111
+ };
112
+ export default meta;
113
+ export const Default = {
114
+ args: {
115
+ dense: false,
116
+ gutters: 'default',
117
+ size: 'medium'
118
+ }
119
+ };
120
+ const Row = ({ title, children }) => (React.createElement("section", null,
121
+ React.createElement("h3", null, title),
122
+ children));
123
+ // Visual Regression - Combined view for Argos testing
124
+ export const Screenshot = {
125
+ tags: ['argos'],
126
+ render: () => (React.createElement(Stack, { spacing: 4 },
127
+ React.createElement(Row, { title: "Default" },
128
+ React.createElement(Demo, null)),
129
+ React.createElement(Row, { title: "Dense" },
130
+ React.createElement(Demo, { dense: true })),
131
+ React.createElement(Row, { title: "Disabled gutters" },
132
+ React.createElement(Demo, { gutters: "disabled" })),
133
+ React.createElement(Row, { title: "Double gutters" },
134
+ React.createElement(Demo, { gutters: "double" })),
135
+ React.createElement(Row, { title: "Small" },
136
+ React.createElement(Demo, { size: "small" })),
137
+ React.createElement(Row, { title: "Large" },
138
+ React.createElement(Demo, { size: "large" })),
139
+ React.createElement(Row, { title: "Highlighted item" },
140
+ React.createElement(HighlightedItem, null))))
141
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@linagora/twake-mui",
3
3
  "type": "module",
4
- "version": "9.9.0",
4
+ "version": "9.10.0",
5
5
  "description": "MUI v9 theme system for Twake applications",
6
6
  "author": "Twake",
7
7
  "license": "MIT",