@linagora/twake-mui 9.7.0 → 9.9.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 +14 -0
- package/dist/components/DropdownButton/DropdownButton.stories.d.ts +7 -0
- package/dist/components/DropdownButton/DropdownButton.stories.js +66 -0
- package/dist/components/DropdownButton/index.d.ts +11 -0
- package/dist/components/DropdownButton/index.js +20 -0
- package/dist/components/DropdownText/DropdownText.stories.d.ts +7 -0
- package/dist/components/DropdownText/DropdownText.stories.js +74 -0
- package/dist/components/DropdownText/index.d.ts +29 -0
- package/dist/components/DropdownText/index.js +34 -0
- package/dist/components/NavDesktopDropdown/index.js +7 -7
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/stories/Menu.stories.js +4 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# @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
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **twake-mui:** Migrate DropdownButton from cozy-ui ([58ef06a](https://github.com/linagora/twake-ui/commit/58ef06a9dd53659aab952824bf7ac2bc8bf2255e))
|
|
7
|
+
|
|
8
|
+
# @linagora/twake-mui [9.8.0](https://github.com/linagora/twake-ui/compare/@linagora/twake-mui@9.7.0...@linagora/twake-mui@9.8.0) (2026-09-24)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **twake-mui:** Migrate DropdownText from cozy-ui ([777b07c](https://github.com/linagora/twake-ui/commit/777b07c26e72cc21ac278dd33b1e0a8210dc19e9))
|
|
14
|
+
|
|
1
15
|
# @linagora/twake-mui [9.7.0](https://github.com/linagora/twake-ui/compare/@linagora/twake-mui@9.6.0...@linagora/twake-mui@9.7.0) (2026-09-24)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import DropdownButton from './index';
|
|
3
|
+
declare const meta: Meta<typeof DropdownButton>;
|
|
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,66 @@
|
|
|
1
|
+
import { Box, Grid, Stack, Typography } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import DropdownButton from './index';
|
|
4
|
+
const variants = [
|
|
5
|
+
'h1',
|
|
6
|
+
'h2',
|
|
7
|
+
'h3',
|
|
8
|
+
'h4',
|
|
9
|
+
'h5',
|
|
10
|
+
'subtitle1',
|
|
11
|
+
'subtitle2',
|
|
12
|
+
'body1',
|
|
13
|
+
'body2',
|
|
14
|
+
'caption'
|
|
15
|
+
];
|
|
16
|
+
const meta = {
|
|
17
|
+
title: 'DropdownButton',
|
|
18
|
+
component: DropdownButton,
|
|
19
|
+
parameters: { layout: 'centered' },
|
|
20
|
+
tags: ['autodocs'],
|
|
21
|
+
argTypes: {
|
|
22
|
+
textVariant: { control: 'select', options: variants },
|
|
23
|
+
spaceBetween: { control: 'boolean' },
|
|
24
|
+
disabled: { control: 'boolean' },
|
|
25
|
+
fullWidth: { control: 'boolean' },
|
|
26
|
+
noWrap: { control: 'boolean' }
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
export default meta;
|
|
30
|
+
export const Default = {
|
|
31
|
+
args: {
|
|
32
|
+
children: 'Dropdown button'
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const Container = ({ width, children }) => (React.createElement(Box, { sx: { border: '1px dashed', borderColor: 'divider', width } }, children));
|
|
36
|
+
// Visual Regression - Combined view for Argos testing
|
|
37
|
+
export const Screenshot = {
|
|
38
|
+
tags: ['argos'],
|
|
39
|
+
render: () => (React.createElement(Stack, { spacing: 4 },
|
|
40
|
+
React.createElement(Grid, { container: true },
|
|
41
|
+
React.createElement(Grid, { size: 6 },
|
|
42
|
+
React.createElement(Typography, null, "Default"),
|
|
43
|
+
variants.map(variant => (React.createElement(Box, { key: variant, sx: { mb: 2 } },
|
|
44
|
+
React.createElement(DropdownButton, { textVariant: variant }, variant))))),
|
|
45
|
+
React.createElement(Grid, { size: 6 },
|
|
46
|
+
React.createElement(Typography, null, "Disabled"),
|
|
47
|
+
variants.map(variant => (React.createElement(Box, { key: variant, sx: { mb: 2 } },
|
|
48
|
+
React.createElement(DropdownButton, { textVariant: variant, disabled: true }, variant)))))),
|
|
49
|
+
React.createElement(Container, null,
|
|
50
|
+
React.createElement(DropdownButton, null, "This is a long text without ellipsis without restrictive container")),
|
|
51
|
+
React.createElement(Container, { width: 150 },
|
|
52
|
+
React.createElement(DropdownButton, null, "This is a long text without ellipsis inside a restrictive container")),
|
|
53
|
+
React.createElement(Container, { width: 150 },
|
|
54
|
+
React.createElement(DropdownButton, { noWrap: true }, "This is a long text with ellipsis inside a container")),
|
|
55
|
+
React.createElement(Container, { width: "100%" },
|
|
56
|
+
React.createElement(DropdownButton, null,
|
|
57
|
+
"Text with",
|
|
58
|
+
React.createElement("br", null),
|
|
59
|
+
"breaking spaces",
|
|
60
|
+
React.createElement("br", null),
|
|
61
|
+
"inside content")),
|
|
62
|
+
React.createElement(Container, { width: "100%" },
|
|
63
|
+
React.createElement(DropdownButton, { fullWidth: true, spaceBetween: true }, "Space between text and icon (fullWidth needed)")),
|
|
64
|
+
React.createElement(Container, { width: "100%" },
|
|
65
|
+
React.createElement(DropdownButton, { fullWidth: true }, "Full width but no space between text and icon"))))
|
|
66
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ButtonProps } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { DropdownTextProps, DropdownTextVariant } from '../DropdownText';
|
|
4
|
+
export interface DropdownButtonProps extends ButtonProps {
|
|
5
|
+
textVariant?: DropdownTextVariant;
|
|
6
|
+
spaceBetween?: boolean;
|
|
7
|
+
noWrap?: boolean;
|
|
8
|
+
dropdownTextProps?: Partial<DropdownTextProps>;
|
|
9
|
+
}
|
|
10
|
+
declare const DropdownButton: React.ForwardRefExoticComponent<Omit<DropdownButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
11
|
+
export default DropdownButton;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Button } from '@mui/material';
|
|
2
|
+
import { styled } from '@mui/material/styles';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import DropdownText from '../DropdownText';
|
|
5
|
+
const StyledButton = styled(Button)({
|
|
6
|
+
minHeight: 'auto',
|
|
7
|
+
margin: -8,
|
|
8
|
+
padding: 8,
|
|
9
|
+
textAlign: 'left',
|
|
10
|
+
variants: [
|
|
11
|
+
{
|
|
12
|
+
props: { fullWidth: true },
|
|
13
|
+
style: { width: 'calc(100% + 16px)' }
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
});
|
|
17
|
+
const DropdownButton = React.forwardRef(({ textVariant = 'body1', spaceBetween = false, disabled = false, fullWidth = false, noWrap = false, dropdownTextProps, children, ...props }, ref) => (React.createElement(StyledButton, { ref: ref, variant: "text", color: "inherit", disabled: disabled, fullWidth: fullWidth || noWrap, ...props },
|
|
18
|
+
React.createElement(DropdownText, { variant: textVariant, spaceBetween: spaceBetween, disabled: disabled, noWrap: noWrap, ...dropdownTextProps }, children))));
|
|
19
|
+
DropdownButton.displayName = 'DropdownButton';
|
|
20
|
+
export default DropdownButton;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import DropdownText from './index';
|
|
3
|
+
declare const meta: Meta<typeof DropdownText>;
|
|
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,74 @@
|
|
|
1
|
+
import { Box, Grid, Stack } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import DropdownText from './index';
|
|
4
|
+
const variants = [
|
|
5
|
+
'h1',
|
|
6
|
+
'h2',
|
|
7
|
+
'h3',
|
|
8
|
+
'h4',
|
|
9
|
+
'h5',
|
|
10
|
+
'h6',
|
|
11
|
+
'subtitle1',
|
|
12
|
+
'subtitle2',
|
|
13
|
+
'body1',
|
|
14
|
+
'body2',
|
|
15
|
+
'caption'
|
|
16
|
+
];
|
|
17
|
+
const columns = [
|
|
18
|
+
{ title: 'Default', props: {} },
|
|
19
|
+
{ title: 'Disabled', props: { disabled: true } },
|
|
20
|
+
{ title: 'Color primary', props: { color: 'primary' } },
|
|
21
|
+
{ title: 'Color error', props: { color: 'error' } }
|
|
22
|
+
];
|
|
23
|
+
const meta = {
|
|
24
|
+
title: 'DropdownText',
|
|
25
|
+
component: DropdownText,
|
|
26
|
+
parameters: { layout: 'centered' },
|
|
27
|
+
tags: ['autodocs'],
|
|
28
|
+
argTypes: {
|
|
29
|
+
variant: { control: 'select', options: variants },
|
|
30
|
+
color: {
|
|
31
|
+
control: 'select',
|
|
32
|
+
options: ['inherit', 'primary', 'secondary', 'error', 'textSecondary']
|
|
33
|
+
},
|
|
34
|
+
disabled: { control: 'boolean' },
|
|
35
|
+
noWrap: { control: 'boolean' },
|
|
36
|
+
spaceBetween: { control: 'boolean' }
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
export default meta;
|
|
40
|
+
export const Default = {
|
|
41
|
+
args: {
|
|
42
|
+
children: 'Dropdown'
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const Frame = ({ width, children }) => (React.createElement(Box, { sx: { width, border: 1, borderStyle: 'dashed', borderColor: 'divider' } }, children));
|
|
46
|
+
// Visual Regression - Combined view for Argos testing
|
|
47
|
+
export const Screenshot = {
|
|
48
|
+
tags: ['argos'],
|
|
49
|
+
render: () => (React.createElement(Stack, { spacing: 4 },
|
|
50
|
+
React.createElement("section", null,
|
|
51
|
+
React.createElement("h3", { style: { marginBottom: '12px' } }, "Variants"),
|
|
52
|
+
React.createElement(Grid, { container: true, spacing: 2 }, columns.map(({ title, props }) => (React.createElement(Grid, { key: title, size: { xs: 6, sm: 3 } },
|
|
53
|
+
React.createElement(Stack, { spacing: 2 },
|
|
54
|
+
React.createElement("div", null, title),
|
|
55
|
+
variants.map(variant => (React.createElement(DropdownText, { key: variant, variant: variant, ...props }, variant))))))))),
|
|
56
|
+
React.createElement("section", null,
|
|
57
|
+
React.createElement("h3", { style: { marginBottom: '12px' } }, "Containers"),
|
|
58
|
+
React.createElement(Stack, { spacing: 2 },
|
|
59
|
+
React.createElement(Frame, null,
|
|
60
|
+
React.createElement(DropdownText, null, "This is a long text without ellipsis without restrictive container")),
|
|
61
|
+
React.createElement(Frame, { width: "150px" },
|
|
62
|
+
React.createElement(DropdownText, null, "This is a long text without ellipsis inside a restrictive container")),
|
|
63
|
+
React.createElement(Frame, { width: "150px" },
|
|
64
|
+
React.createElement(DropdownText, { noWrap: true }, "This is a long text with ellipsis inside a container")),
|
|
65
|
+
React.createElement(Frame, null,
|
|
66
|
+
React.createElement(DropdownText, null,
|
|
67
|
+
"Text with",
|
|
68
|
+
React.createElement("br", null),
|
|
69
|
+
"breaking spaces",
|
|
70
|
+
React.createElement("br", null),
|
|
71
|
+
"inside content")),
|
|
72
|
+
React.createElement(Frame, null,
|
|
73
|
+
React.createElement(DropdownText, { spaceBetween: true }, "Space between text and icon"))))))
|
|
74
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { IconProps } from '@linagora/twake-icons';
|
|
2
|
+
import { TypographyProps } from '@mui/material';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
declare const iconSizeByVariant: {
|
|
5
|
+
readonly h1: 24;
|
|
6
|
+
readonly h2: 17;
|
|
7
|
+
readonly h3: 15;
|
|
8
|
+
readonly h4: 14;
|
|
9
|
+
readonly h5: 13;
|
|
10
|
+
readonly h6: 12;
|
|
11
|
+
readonly body1: 12;
|
|
12
|
+
readonly body2: 11;
|
|
13
|
+
readonly caption: 10;
|
|
14
|
+
readonly subtitle1: 11;
|
|
15
|
+
readonly subtitle2: 10;
|
|
16
|
+
};
|
|
17
|
+
export type DropdownTextVariant = keyof typeof iconSizeByVariant;
|
|
18
|
+
export interface DropdownTextProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
|
|
19
|
+
variant?: DropdownTextVariant;
|
|
20
|
+
color?: TypographyProps['color'];
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
noWrap?: boolean;
|
|
23
|
+
spaceBetween?: boolean;
|
|
24
|
+
innerTextProps?: TypographyProps;
|
|
25
|
+
innerIconContainerProps?: TypographyProps;
|
|
26
|
+
innerIconProps?: Omit<IconProps, 'icon'>;
|
|
27
|
+
}
|
|
28
|
+
declare const DropdownText: React.ForwardRefExoticComponent<DropdownTextProps & React.RefAttributes<HTMLDivElement>>;
|
|
29
|
+
export default DropdownText;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Icon, Bottom } from '@linagora/twake-icons';
|
|
2
|
+
import { Box, Typography } from '@mui/material';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
const iconSizeByVariant = {
|
|
5
|
+
h1: 24,
|
|
6
|
+
h2: 17,
|
|
7
|
+
h3: 15,
|
|
8
|
+
h4: 14,
|
|
9
|
+
h5: 13,
|
|
10
|
+
h6: 12,
|
|
11
|
+
body1: 12,
|
|
12
|
+
body2: 11,
|
|
13
|
+
caption: 10,
|
|
14
|
+
subtitle1: 11,
|
|
15
|
+
subtitle2: 10
|
|
16
|
+
};
|
|
17
|
+
const DropdownText = React.forwardRef(({ variant = 'body1', color = 'inherit', disabled = false, noWrap = false, spaceBetween = false, innerTextProps, innerIconContainerProps, innerIconProps, children, ...props }, ref) => {
|
|
18
|
+
const textColor = disabled ? 'textDisabled' : color;
|
|
19
|
+
return (React.createElement(Box, { ref: ref, sx: {
|
|
20
|
+
display: 'flex',
|
|
21
|
+
width: '100%',
|
|
22
|
+
alignItems: 'center',
|
|
23
|
+
justifyContent: spaceBetween ? 'space-between' : undefined
|
|
24
|
+
}, ...props },
|
|
25
|
+
React.createElement(Typography, { variant: variant, color: textColor, noWrap: noWrap, ...innerTextProps }, children),
|
|
26
|
+
React.createElement(Typography, { component: "span", color: textColor, sx: {
|
|
27
|
+
display: 'flex',
|
|
28
|
+
ml: '5px',
|
|
29
|
+
mt: variant === 'body1' ? '3px' : undefined
|
|
30
|
+
}, ...innerIconContainerProps },
|
|
31
|
+
React.createElement(Icon, { icon: Bottom, size: iconSizeByVariant[variant], ...innerIconProps }))));
|
|
32
|
+
});
|
|
33
|
+
DropdownText.displayName = 'DropdownText';
|
|
34
|
+
export default DropdownText;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ListItem, Typography } from '@mui/material';
|
|
1
|
+
import { ListItem } from '@mui/material';
|
|
3
2
|
import React, { Children, isValidElement, useState } from 'react';
|
|
4
3
|
import { useBreakpoints } from '../../hooks/useBreakpoints';
|
|
4
|
+
import DropdownText from '../DropdownText';
|
|
5
5
|
export const NavDesktopDropdown = ({ label, children, defaultOpen = true, limit = 5 }) => {
|
|
6
6
|
const { isDesktop } = useBreakpoints();
|
|
7
7
|
const [open, setOpen] = useState(defaultOpen);
|
|
@@ -10,15 +10,15 @@ 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, {
|
|
13
|
+
React.createElement(ListItem, { sx: {
|
|
14
14
|
minHeight: 48,
|
|
15
15
|
py: 1,
|
|
16
16
|
px: 2,
|
|
17
|
-
justifyContent: 'space-between',
|
|
18
17
|
cursor: isActivated ? 'pointer' : undefined
|
|
19
18
|
} },
|
|
20
|
-
React.createElement(
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
React.createElement(DropdownText, { variant: "caption", color: "textSecondary", spaceBetween: true, onClick: isActivated ? onToggle : undefined, innerIconProps: {
|
|
20
|
+
rotate: open ? 0 : -90,
|
|
21
|
+
display: isActivated ? undefined : 'none'
|
|
22
|
+
} }, label)),
|
|
23
23
|
open && children));
|
|
24
24
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export { Button, default as ButtonDefault } from './components/Button';
|
|
|
11
11
|
export { default as Chip } from './components/Chip';
|
|
12
12
|
export { Dialog, default as DialogDefault } from './components/Dialog';
|
|
13
13
|
export { ContactPopover, default as ContactPopoverDefault } from './components/ContactPopover';
|
|
14
|
+
export { default as DropdownButton } from './components/DropdownButton';
|
|
15
|
+
export { default as DropdownText } from './components/DropdownText';
|
|
14
16
|
export { Tabs, default as TabsDefault } from './components/Tabs';
|
|
15
17
|
export { Switch, default as SwitchDefault } from './components/Switch';
|
|
16
18
|
export { SearchBar, default as SearchBarDefault } from './components/SearchBar';
|
|
@@ -41,6 +43,8 @@ export type { ContactPopoverCalendarActionProps } from './components/ContactPopo
|
|
|
41
43
|
export type { ContactPopoverEmailActionProps } from './components/ContactPopover/ContactPopoverEmailAction';
|
|
42
44
|
export type { ChipProps } from './components/Chip';
|
|
43
45
|
export type { DialogProps, DialogSize } from './components/Dialog';
|
|
46
|
+
export type { DropdownButtonProps } from './components/DropdownButton';
|
|
47
|
+
export type { DropdownTextProps, DropdownTextVariant } from './components/DropdownText';
|
|
44
48
|
export type { TabsProps } from './components/Tabs';
|
|
45
49
|
export type { SwitchProps } from './components/Switch';
|
|
46
50
|
export type { SearchBarProps } from './components/SearchBar/types';
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,8 @@ export { Button, default as ButtonDefault } from './components/Button';
|
|
|
14
14
|
export { default as Chip } from './components/Chip';
|
|
15
15
|
export { Dialog, default as DialogDefault } from './components/Dialog';
|
|
16
16
|
export { ContactPopover, default as ContactPopoverDefault } from './components/ContactPopover';
|
|
17
|
+
export { default as DropdownButton } from './components/DropdownButton';
|
|
18
|
+
export { default as DropdownText } from './components/DropdownText';
|
|
17
19
|
export { Tabs, default as TabsDefault } from './components/Tabs';
|
|
18
20
|
export { Switch, default as SwitchDefault } from './components/Switch';
|
|
19
21
|
export { SearchBar, default as SearchBarDefault } from './components/SearchBar';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Attachment, Attention,
|
|
2
|
-
import { Box,
|
|
1
|
+
import { Attachment, Attention, Contrast, Copy, Icon, Pen, People, Telephone } from '@linagora/twake-icons';
|
|
2
|
+
import { Box, Divider, ListItemIcon, ListItemText, Menu, MenuItem, Typography } from '@mui/material';
|
|
3
3
|
import React, { useState } from 'react';
|
|
4
|
+
import DropdownButton from '../components/DropdownButton';
|
|
4
5
|
const items = [
|
|
5
6
|
React.createElement(MenuItem, { key: "modify" },
|
|
6
7
|
React.createElement(ListItemIcon, null,
|
|
@@ -41,7 +42,7 @@ const ExampleMenu = ({ defaultOpen = false, ...props }) => {
|
|
|
41
42
|
const [button, setButton] = useState(null);
|
|
42
43
|
const [open, setOpen] = useState(defaultOpen);
|
|
43
44
|
return (React.createElement(React.Fragment, null,
|
|
44
|
-
React.createElement(
|
|
45
|
+
React.createElement(DropdownButton, { ref: setButton, onClick: () => setOpen(!open) }, "Show menu"),
|
|
45
46
|
React.createElement(Menu, { anchorOrigin: { vertical: 'bottom', horizontal: 'left' }, ...props, anchorEl: button, open: open && Boolean(button), onClose: () => setOpen(false) }, items)));
|
|
46
47
|
};
|
|
47
48
|
const meta = {
|