@linagora/twake-mui 7.1.0 → 9.0.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 +58 -0
- package/dist/components/Apptitle/index.js +9 -5
- package/dist/components/Avatar/Avatar.stories.js +58 -37
- package/dist/components/Avatar/helpers.d.ts +0 -28
- package/dist/components/Avatar/helpers.js +0 -28
- package/dist/components/Avatar/index.d.ts +4 -6
- package/dist/components/Avatar/index.js +24 -31
- package/dist/components/Button/index.d.ts +12 -0
- package/dist/components/Button/index.js +8 -0
- package/dist/{stories → components/Dialog}/Dialog.stories.d.ts +2 -2
- package/dist/components/Dialog/Dialog.stories.js +81 -0
- package/dist/components/Dialog/index.d.ts +9 -0
- package/dist/components/Dialog/index.js +9 -0
- package/dist/components/Nav/index.d.ts +8 -0
- package/dist/components/Nav/index.js +14 -0
- package/dist/components/NavDesktopDropdown/index.d.ts +8 -0
- package/dist/components/NavDesktopDropdown/index.js +24 -0
- package/dist/components/NavDesktopLimiter/index.d.ts +6 -0
- package/dist/components/NavDesktopLimiter/index.js +31 -0
- package/dist/components/NavDesktopLimiter/locales/en.json +6 -0
- package/dist/components/NavDesktopLimiter/locales/fr.json +6 -0
- package/dist/components/NavDesktopLimiter/locales/ru.json +6 -0
- package/dist/components/NavDesktopLimiter/locales/vi.json +6 -0
- package/dist/components/NavIcon/index.d.ts +7 -0
- package/dist/components/NavIcon/index.js +17 -0
- package/dist/components/NavItem/index.d.ts +8 -0
- package/dist/components/NavItem/index.js +29 -0
- package/dist/components/NavLink/index.d.ts +3 -0
- package/dist/components/NavLink/index.js +36 -0
- package/dist/components/NavText/index.d.ts +7 -0
- package/dist/components/NavText/index.js +14 -0
- package/dist/components/Sidebar/Sidebar.stories.d.ts +7 -0
- package/dist/components/Sidebar/Sidebar.stories.js +57 -0
- package/dist/components/Sidebar/index.d.ts +7 -0
- package/dist/components/Sidebar/index.js +21 -0
- package/dist/components/Switch/Switch.stories.d.ts +7 -0
- package/dist/components/Switch/Switch.stories.js +58 -0
- package/dist/components/Switch/index.d.ts +9 -0
- package/dist/components/Switch/index.js +8 -0
- package/dist/components/Tabs/Tabs.stories.d.ts +7 -0
- package/dist/components/Tabs/Tabs.stories.js +52 -0
- package/dist/components/Tabs/index.d.ts +10 -0
- package/dist/components/Tabs/index.js +5 -0
- package/dist/components/ThemeProvider/index.js +9 -10
- package/dist/components/ThemeProvider/types.d.ts +6 -0
- package/dist/index.d.ts +26 -1
- package/dist/index.js +13 -1
- package/dist/lib/makePalette.d.ts +1 -1
- package/dist/lib/makePalette.js +3 -1
- package/dist/lib/makeShadows.d.ts +1 -1
- package/dist/lib/makeShadows.js +2 -2
- package/dist/lib/makeTheme.d.ts +3 -2
- package/dist/lib/makeTheme.js +15 -16
- package/dist/lib/overrides.d.ts +2 -0
- package/dist/lib/overrides.js +1027 -0
- package/dist/lib/types.d.ts +14 -0
- package/dist/stories/Alert.stories.js +57 -53
- package/dist/stories/Badge.stories.d.ts +7 -0
- package/dist/stories/Badge.stories.js +84 -0
- package/dist/stories/Button.stories.d.ts +3 -3
- package/dist/stories/Button.stories.js +67 -58
- package/dist/stories/{Selection.stories.d.ts → Checkbox.stories.d.ts} +1 -1
- package/dist/stories/Checkbox.stories.js +59 -0
- package/dist/stories/Divider.stories.d.ts +7 -0
- package/dist/stories/Divider.stories.js +56 -0
- package/dist/stories/Radio.stories.d.ts +7 -0
- package/dist/stories/Radio.stories.js +60 -0
- package/dist/stories/Snackbar.stories.d.ts +7 -0
- package/dist/stories/Snackbar.stories.js +60 -0
- package/dist/stories/{Input.stories.d.ts → TextField.stories.d.ts} +1 -1
- package/dist/stories/TextField.stories.js +86 -0
- package/dist/stories/ThemePlayground.stories.js +20 -113
- package/dist/stories/Typography.stories.d.ts +1 -1
- package/dist/stories/Typography.stories.js +48 -34
- package/package.json +5 -2
- package/dist/lib/darkOverrides.d.ts +0 -2
- package/dist/lib/darkOverrides.js +0 -3
- package/dist/lib/lightOverrides.d.ts +0 -2
- package/dist/lib/lightOverrides.js +0 -551
- package/dist/stories/Dialog.stories.js +0 -40
- package/dist/stories/Input.stories.js +0 -41
- package/dist/stories/Selection.stories.js +0 -37
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,61 @@
|
|
|
1
|
+
# @linagora/twake-mui [9.0.0](https://github.com/linagora/twake-ui/compare/@linagora/twake-mui@8.0.0...@linagora/twake-mui@9.0.0) (2026-09-21)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **twake-mui:** Migrate Nav from cozy-ui ([5dd0516](https://github.com/linagora/twake-ui/commit/5dd05165741159437f796935f81d9d907eb808f2))
|
|
7
|
+
* **twake-mui:** Migrate Sidebar from cozy-ui ([08f4179](https://github.com/linagora/twake-ui/commit/08f4179493090399cca1e59878d405b945777225))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### BREAKING CHANGES
|
|
11
|
+
|
|
12
|
+
* **twake-mui:** You need "twake-i18n" >= "0.5.0"
|
|
13
|
+
|
|
14
|
+
# @linagora/twake-mui [8.0.0](https://github.com/linagora/twake-ui/compare/@linagora/twake-mui@7.1.0...@linagora/twake-mui@8.0.0) (2026-09-18)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* **twake-mui:** Anchor the static Snackbar story top left ([e1cee47](https://github.com/linagora/twake-ui/commit/e1cee476de86ec828cd836b5ce5dd2925360ff29))
|
|
20
|
+
* **twake-mui:** Center the Alert message vertically ([38cb5c2](https://github.com/linagora/twake-ui/commit/38cb5c2200adcaa8b9348fca235a54698b5e26e8))
|
|
21
|
+
* **twake-mui:** Clean old Avatar override ([202ffb6](https://github.com/linagora/twake-ui/commit/202ffb652010dee61e61b0386a4fbe45f6074859))
|
|
22
|
+
* **twake-mui:** Clean old Button override ([f0c45eb](https://github.com/linagora/twake-ui/commit/f0c45eb10e4610176509a1fd89179dcd43d4144a))
|
|
23
|
+
* **twake-mui:** Clean old Dialog override ([50544ef](https://github.com/linagora/twake-ui/commit/50544ef9426294d0d54a843e61d04b829cb914c2))
|
|
24
|
+
* **twake-mui:** Clean old TextField override ([23b4253](https://github.com/linagora/twake-ui/commit/23b42530b26909abd822e6da8b99b250f5fead39))
|
|
25
|
+
* **twake-mui:** Draw the secondary Switch in the success colour like cozy-ui ([cff53f0](https://github.com/linagora/twake-ui/commit/cff53f0cc0c7f0098843d6f5c0acc5dd9ca4553d))
|
|
26
|
+
* **twake-mui:** Emit colorSchemes with our own tokens for both modes ([962054b](https://github.com/linagora/twake-ui/commit/962054b74fa214494b6786bd3bc2ce4c98fd8714))
|
|
27
|
+
* **twake-mui:** Replace the runtime lodash import with @mui/utils deepmerge ([e6940ff](https://github.com/linagora/twake-ui/commit/e6940ff4d99987ea49ef7a370c01aef43e862373))
|
|
28
|
+
* **twake-mui:** Thread mode into ThemeProvider's defaultMode ([1f98a09](https://github.com/linagora/twake-ui/commit/1f98a09b4421497b50717bc36353043838a36c63))
|
|
29
|
+
* **twake-mui:** Use the 16px Alert icons of cozy-ui ([c781a7d](https://github.com/linagora/twake-ui/commit/c781a7dca3ccacf04c94eb9dd7b0f14b4fcecf70))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Features
|
|
33
|
+
|
|
34
|
+
* Expose cssVariables in TypeScript ([23a151e](https://github.com/linagora/twake-ui/commit/23a151eaf47287d1cc49364073d10fd0acceccc9))
|
|
35
|
+
* **twake-mui:** Accept the primary and secondary Button variants of cozy-ui ([daf67fb](https://github.com/linagora/twake-ui/commit/daf67fb9544a11338556201657a6f0e687aab8cd))
|
|
36
|
+
* **twake-mui:** Let apps customize the whole theme ([9af16db](https://github.com/linagora/twake-ui/commit/9af16db3720708f79d69bf48c14522ef65b6b7cc))
|
|
37
|
+
* **twake-mui:** Migrate Alert from cozy-ui ([916405d](https://github.com/linagora/twake-ui/commit/916405d6c2ce25bd83c445a47ba240303291a7b8))
|
|
38
|
+
* **twake-mui:** Migrate Avatar from cozy-ui ([214787f](https://github.com/linagora/twake-ui/commit/214787fbb514b1fe7b510234405821f0256e34e6))
|
|
39
|
+
* **twake-mui:** Migrate Badge from cozy-ui ([3d9509d](https://github.com/linagora/twake-ui/commit/3d9509d318e048505bee95ce80f5369da9fb25b5))
|
|
40
|
+
* **twake-mui:** Migrate Button from cozy-ui ([704f267](https://github.com/linagora/twake-ui/commit/704f267cd13f9998faf3fbb095b3ab798b518950))
|
|
41
|
+
* **twake-mui:** Migrate Checkbox from cozy-ui ([5281cb1](https://github.com/linagora/twake-ui/commit/5281cb1c5eea50ec24bfb528106f13cfb705572a))
|
|
42
|
+
* **twake-mui:** Migrate Dialog from cozy-ui ([d420cf5](https://github.com/linagora/twake-ui/commit/d420cf5c4f9e7aa37c60f6122fd0e903586e046b))
|
|
43
|
+
* **twake-mui:** Migrate Divider from cozy-ui ([44e1d6c](https://github.com/linagora/twake-ui/commit/44e1d6cc13f612a2295895f4be03856eaf90c7a9))
|
|
44
|
+
* **twake-mui:** Migrate Radio from cozy-ui ([effd21f](https://github.com/linagora/twake-ui/commit/effd21fddab6caf43a7e480b16cbd6e93611c34b))
|
|
45
|
+
* **twake-mui:** Migrate Snackbar from cozy-ui ([56f2cac](https://github.com/linagora/twake-ui/commit/56f2cac2d632d19bab976ccee9e70f1b20e5ffdb))
|
|
46
|
+
* **twake-mui:** Migrate Switch from cozy-ui ([545280b](https://github.com/linagora/twake-ui/commit/545280bd72ef81eb62868e7f8b3dc7e058924466))
|
|
47
|
+
* **twake-mui:** Migrate Tabs from cozy-ui ([076ff98](https://github.com/linagora/twake-ui/commit/076ff986612d447c97385898faf10d4ba50bcca1))
|
|
48
|
+
* **twake-mui:** Migrate TextField from cozy-ui ([6a4fd77](https://github.com/linagora/twake-ui/commit/6a4fd77ec5e49c76603b7bd8cd899157ef72fa6b))
|
|
49
|
+
* **twake-mui:** Migrate Typography from cozy-ui ([7f59c34](https://github.com/linagora/twake-ui/commit/7f59c34e4f0a6502f8a30e676c9d7bb2a48f3025))
|
|
50
|
+
* **twake-mui:** Re-export useColorScheme for runtime theme switching ([f3ed328](https://github.com/linagora/twake-ui/commit/f3ed328d45c6b5006403f975a5f07447f5ef2172))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### BREAKING CHANGES
|
|
54
|
+
|
|
55
|
+
* **twake-mui:** You must use `palette` prop instead of
|
|
56
|
+
`themeOptions` of `TwakeMuiThemeProvider` to override
|
|
57
|
+
the palette
|
|
58
|
+
|
|
1
59
|
# @linagora/twake-mui [7.1.0](https://github.com/linagora/twake-ui/compare/@linagora/twake-mui@7.0.0...@linagora/twake-mui@7.1.0) (2026-09-10)
|
|
2
60
|
|
|
3
61
|
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { Icon, TwakeText } from '@linagora/twake-icons';
|
|
2
|
-
import { Box
|
|
2
|
+
import { Box } from '@mui/material';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
const AppTitle = ({ appIcon, appTextIcon }) => {
|
|
5
|
-
const theme = useTheme();
|
|
6
|
-
const isLight = theme.palette.mode === 'light';
|
|
7
5
|
if (!appIcon || !appTextIcon)
|
|
8
6
|
return null;
|
|
9
7
|
const AppTextIcon = appTextIcon;
|
|
10
8
|
return (React.createElement(Box, { sx: { display: 'flex', alignItems: 'center', gap: 1 } },
|
|
11
9
|
React.createElement(Icon, { icon: appIcon, size: "32" }),
|
|
12
|
-
React.createElement(
|
|
13
|
-
|
|
10
|
+
React.createElement(Box, { component: TwakeText, height: "22", sx: [
|
|
11
|
+
{ fill: '#000' },
|
|
12
|
+
(theme) => theme.applyStyles('dark', { fill: '#fff' })
|
|
13
|
+
] }),
|
|
14
|
+
React.createElement(Box, { component: AppTextIcon, height: 22, sx: [
|
|
15
|
+
{ width: 'auto', fill: '#000' },
|
|
16
|
+
(theme) => theme.applyStyles('dark', { fill: '#fff' })
|
|
17
|
+
] })));
|
|
14
18
|
};
|
|
15
19
|
export default AppTitle;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { Icon, Link } from '@linagora/twake-icons';
|
|
2
|
+
import { AvatarGroup, Stack } from '@mui/material';
|
|
1
3
|
import React from 'react';
|
|
2
4
|
import { supportedColors } from './helpers';
|
|
3
5
|
import { Avatar } from './index';
|
|
6
|
+
const sizes = ['xs', 's', 'm', 'l', 'xl'];
|
|
7
|
+
const image = 'https://i.pravatar.cc/150?img=11';
|
|
4
8
|
const meta = {
|
|
5
9
|
title: 'Avatar',
|
|
6
10
|
component: Avatar,
|
|
@@ -13,8 +17,9 @@ const meta = {
|
|
|
13
17
|
},
|
|
14
18
|
size: {
|
|
15
19
|
control: 'select',
|
|
16
|
-
options:
|
|
20
|
+
options: sizes
|
|
17
21
|
},
|
|
22
|
+
textColor: { control: 'color' },
|
|
18
23
|
border: { control: 'boolean' },
|
|
19
24
|
innerBorder: { control: 'boolean' },
|
|
20
25
|
disabled: { control: 'boolean' },
|
|
@@ -30,44 +35,60 @@ export const Default = {
|
|
|
30
35
|
children: 'JD'
|
|
31
36
|
}
|
|
32
37
|
};
|
|
38
|
+
const Row = ({ title, children }) => (React.createElement("section", null,
|
|
39
|
+
React.createElement("h3", { style: { marginBottom: '12px' } }, title),
|
|
40
|
+
React.createElement(Stack, { direction: "row", spacing: 1, useFlexGap: true, sx: { flexWrap: 'wrap' } }, children)));
|
|
33
41
|
// Visual Regression - Combined view for Argos testing
|
|
34
42
|
export const Screenshot = {
|
|
35
43
|
tags: ['argos'],
|
|
36
|
-
render: () => (React.createElement(
|
|
44
|
+
render: () => (React.createElement(Stack, { spacing: 4 },
|
|
45
|
+
React.createElement(Row, { title: "Sizes" }, sizes.map(size => (React.createElement(React.Fragment, { key: size },
|
|
46
|
+
React.createElement(Avatar, { size: size, color: "sunrise" }),
|
|
47
|
+
React.createElement(Avatar, { size: size, color: "sunrise" }, "AB"),
|
|
48
|
+
React.createElement(Avatar, { size: size, color: "sunrise" },
|
|
49
|
+
React.createElement(Icon, { icon: Link })))))),
|
|
50
|
+
React.createElement(Row, { title: "Colors" }, supportedColors.map(color => (React.createElement(Avatar, { key: color, color: color, size: "l" }, color.slice(0, 2).toUpperCase())))),
|
|
51
|
+
React.createElement(Row, { title: "Name-based colors" },
|
|
52
|
+
React.createElement(Avatar, { size: "l" }, "Alice"),
|
|
53
|
+
React.createElement(Avatar, { size: "l" }, "Bob"),
|
|
54
|
+
React.createElement(Avatar, { size: "l" }, "Charlie"),
|
|
55
|
+
React.createElement(Avatar, { size: "l" }, "Diana")),
|
|
56
|
+
React.createElement(Row, { title: "Default color" },
|
|
57
|
+
React.createElement(Avatar, { src: image, alt: "Image" }),
|
|
58
|
+
React.createElement(Avatar, { color: "none", src: image, alt: "Image, no color" }),
|
|
59
|
+
React.createElement(Avatar, { color: "sunrise", src: image, alt: "Image, sunrise" }),
|
|
60
|
+
React.createElement(Avatar, null),
|
|
61
|
+
React.createElement(Avatar, { color: "none" }),
|
|
62
|
+
React.createElement(Avatar, { color: "sunrise" }),
|
|
63
|
+
React.createElement(Avatar, null, "AB"),
|
|
64
|
+
React.createElement(Avatar, { color: "none" }, "BC"),
|
|
65
|
+
React.createElement(Avatar, { color: "sunrise" }, "CD")),
|
|
66
|
+
React.createElement(Row, { title: "Custom size and color" },
|
|
67
|
+
React.createElement(Avatar, { color: "sunrise", size: 94 }, "DE"),
|
|
68
|
+
React.createElement(Avatar, { color: "#0000ff" }, "EF"),
|
|
69
|
+
React.createElement(Avatar, { color: "grey", textColor: "white" }, "FG")),
|
|
70
|
+
React.createElement(Row, { title: "Borders" },
|
|
71
|
+
React.createElement(Avatar, { size: "l" }, "Default"),
|
|
72
|
+
React.createElement(Avatar, { size: "l", border: true }, "Border"),
|
|
73
|
+
React.createElement(Avatar, { size: "l", innerBorder: true }, "Inner"),
|
|
74
|
+
React.createElement(Avatar, { size: "l", border: true, innerBorder: true }, "Both"),
|
|
75
|
+
React.createElement(Avatar, { size: "l", color: "none", border: true, innerBorder: true },
|
|
76
|
+
React.createElement(Icon, { icon: Link }))),
|
|
77
|
+
React.createElement(Row, { title: "Disabled" },
|
|
78
|
+
React.createElement(Avatar, { size: "l", disabled: true }, "AB"),
|
|
79
|
+
React.createElement(Avatar, { size: "l", disabled: true, color: "sunrise" }, "CD"),
|
|
80
|
+
React.createElement(Avatar, { size: "l", disabled: true, src: image, alt: "Disabled" }),
|
|
81
|
+
React.createElement(Avatar, { size: "l", disabled: true, color: "none" },
|
|
82
|
+
React.createElement(Icon, { icon: Link }))),
|
|
37
83
|
React.createElement("section", null,
|
|
38
|
-
React.createElement("h3", { style: { marginBottom: '12px' } }, "
|
|
39
|
-
React.createElement(
|
|
40
|
-
React.createElement(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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" })))))
|
|
84
|
+
React.createElement("h3", { style: { marginBottom: '12px' } }, "Grouped"),
|
|
85
|
+
React.createElement(Stack, { spacing: 1 }, sizes.map(size => (React.createElement(Stack, { key: size, direction: "row", sx: { alignItems: 'center' } },
|
|
86
|
+
React.createElement(AvatarGroup, { max: 4, slotProps: { surplus: { className: `size-${size}` } } },
|
|
87
|
+
React.createElement(Avatar, { size: size, color: supportedColors[0] }, "AB"),
|
|
88
|
+
React.createElement(Avatar, { size: size, color: supportedColors[1] }, "BC"),
|
|
89
|
+
React.createElement(Avatar, { size: size, src: image, alt: "Image" }),
|
|
90
|
+
React.createElement(Avatar, { size: size, color: supportedColors[4] }, "EF"),
|
|
91
|
+
React.createElement(Avatar, { size: size, color: supportedColors[5] }, "FG")),
|
|
92
|
+
React.createElement(Avatar, { size: size, color: "none", border: true, innerBorder: true },
|
|
93
|
+
React.createElement(Icon, { icon: Link })))))))))
|
|
73
94
|
};
|
|
@@ -1,31 +1,3 @@
|
|
|
1
|
-
export declare const sizeToFontSize: {
|
|
2
|
-
xs: number;
|
|
3
|
-
s: number;
|
|
4
|
-
m: number;
|
|
5
|
-
l: number;
|
|
6
|
-
xl: number;
|
|
7
|
-
};
|
|
8
|
-
export declare const sizeToNb: {
|
|
9
|
-
xs: number;
|
|
10
|
-
s: number;
|
|
11
|
-
m: number;
|
|
12
|
-
l: number;
|
|
13
|
-
xl: number;
|
|
14
|
-
};
|
|
15
|
-
export declare const sizeToFontWeight: {
|
|
16
|
-
xs: number;
|
|
17
|
-
s: number;
|
|
18
|
-
m: number;
|
|
19
|
-
l: number;
|
|
20
|
-
xl: number;
|
|
21
|
-
};
|
|
22
|
-
export declare const sizeToLineHeight: {
|
|
23
|
-
xs: number;
|
|
24
|
-
s: number;
|
|
25
|
-
m: number;
|
|
26
|
-
l: number;
|
|
27
|
-
xl: number;
|
|
28
|
-
};
|
|
29
1
|
export declare const supportedColors: readonly ["sunrise", "downy", "sugarCoral", "pinkBonnet", "blueMana", "nightBlue", "snowPea", "pluviophile", "cornflower", "paleGreen", "moonBlue"];
|
|
30
2
|
export declare const colorMapping: Record<string, string>;
|
|
31
3
|
/**
|
|
@@ -1,31 +1,3 @@
|
|
|
1
|
-
export const sizeToFontSize = {
|
|
2
|
-
xs: 9.109,
|
|
3
|
-
s: 12.525,
|
|
4
|
-
m: 18.219,
|
|
5
|
-
l: 27.328,
|
|
6
|
-
xl: 36.438
|
|
7
|
-
};
|
|
8
|
-
export const sizeToNb = {
|
|
9
|
-
xs: 18,
|
|
10
|
-
s: 28,
|
|
11
|
-
m: 36,
|
|
12
|
-
l: 54,
|
|
13
|
-
xl: 72
|
|
14
|
-
};
|
|
15
|
-
export const sizeToFontWeight = {
|
|
16
|
-
xs: 500,
|
|
17
|
-
s: 500,
|
|
18
|
-
m: 500,
|
|
19
|
-
l: 600,
|
|
20
|
-
xl: 600
|
|
21
|
-
};
|
|
22
|
-
export const sizeToLineHeight = {
|
|
23
|
-
xs: 18.219,
|
|
24
|
-
s: 18.219,
|
|
25
|
-
m: 27.328,
|
|
26
|
-
l: 36.438,
|
|
27
|
-
xl: 45.547
|
|
28
|
-
};
|
|
29
1
|
export const supportedColors = [
|
|
30
2
|
'sunrise',
|
|
31
3
|
'downy',
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { AvatarProps as MuiAvatarProps } from '@mui/material';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
|
|
4
|
-
type AvatarSize = 'xs' | 's' | 'm' | 'l' | 'xl';
|
|
5
|
-
type AvatarColor = (typeof supportedColors)[number] | 'none';
|
|
6
|
-
type AvatarDisplay = 'initial' | 'inline';
|
|
3
|
+
export type AvatarSize = 'xs' | 's' | 'm' | 'l' | 'xl';
|
|
7
4
|
export interface AvatarProps extends Omit<MuiAvatarProps, 'color'> {
|
|
8
|
-
color?:
|
|
5
|
+
color?: string;
|
|
9
6
|
size?: AvatarSize | number;
|
|
7
|
+
textColor?: string;
|
|
10
8
|
border?: boolean;
|
|
11
9
|
innerBorder?: boolean;
|
|
12
10
|
disabled?: boolean;
|
|
13
|
-
display?:
|
|
11
|
+
display?: 'initial' | 'inline';
|
|
14
12
|
}
|
|
15
13
|
export declare const Avatar: React.FC<AvatarProps>;
|
|
16
14
|
export default Avatar;
|
|
@@ -1,38 +1,31 @@
|
|
|
1
1
|
import { Avatar as MuiAvatar } from '@mui/material';
|
|
2
2
|
import { styled } from '@mui/material/styles';
|
|
3
|
+
import cx from 'classnames';
|
|
3
4
|
import React from 'react';
|
|
4
|
-
import { colorMapping, nameToColor
|
|
5
|
-
const
|
|
6
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
7
|
-
};
|
|
5
|
+
import { colorMapping, nameToColor } from './helpers';
|
|
6
|
+
const transientProps = ['background', 'textColor', 'customSize'];
|
|
8
7
|
const StyledAvatar = styled(MuiAvatar, {
|
|
9
|
-
shouldForwardProp: prop => prop
|
|
10
|
-
})(({
|
|
11
|
-
...(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
shouldForwardProp: prop => !transientProps.includes(String(prop))
|
|
9
|
+
})(({ background, textColor, customSize }) => ({
|
|
10
|
+
...(customSize && {
|
|
11
|
+
width: customSize,
|
|
12
|
+
height: customSize,
|
|
13
|
+
fontSize: customSize / 2
|
|
14
|
+
}),
|
|
15
|
+
// The text stays white on a coloured avatar whatever the mode
|
|
16
|
+
...(background && { background, color: '#fff' }),
|
|
17
|
+
...(textColor && { color: textColor })
|
|
15
18
|
}));
|
|
16
|
-
export const Avatar = ({ className, color, size, border, innerBorder, disabled, display = 'initial',
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
classNames.push(`size-${size}`);
|
|
28
|
-
if (disabled)
|
|
29
|
-
classNames.push('disabled');
|
|
30
|
-
if (border)
|
|
31
|
-
classNames.push('border');
|
|
32
|
-
if (innerBorder)
|
|
33
|
-
classNames.push('innerBorder');
|
|
34
|
-
if (display !== 'initial')
|
|
35
|
-
classNames.push(`display${capitalize(display)}`);
|
|
36
|
-
return (React.createElement(StyledAvatar, { gradientColor: finalColor, className: classNames.join(' ') || undefined, sx: sx, ...props }));
|
|
19
|
+
export const Avatar = ({ className, color, size = 'm', textColor, border, innerBorder, disabled, display = 'initial', children, ...props }) => {
|
|
20
|
+
const isCustomSize = typeof size === 'number';
|
|
21
|
+
const nameColor = typeof children === 'string' ? nameToColor(children) : '';
|
|
22
|
+
const madeColor = color === 'none' ? '' : color || nameColor;
|
|
23
|
+
return (React.createElement(StyledAvatar, { className: cx(className, {
|
|
24
|
+
[`size-${size}`]: !isCustomSize,
|
|
25
|
+
disabled,
|
|
26
|
+
border,
|
|
27
|
+
innerBorder,
|
|
28
|
+
displayInline: display === 'inline'
|
|
29
|
+
}), customSize: isCustomSize ? size : undefined, background: madeColor ? (colorMapping[madeColor] ?? madeColor) : undefined, textColor: textColor, ...props }, children));
|
|
37
30
|
};
|
|
38
31
|
export default Avatar;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ButtonProps as MuiButtonProps } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
declare const legacyVariants: {
|
|
4
|
+
readonly primary: "contained";
|
|
5
|
+
readonly secondary: "outlined";
|
|
6
|
+
};
|
|
7
|
+
type LegacyVariant = keyof typeof legacyVariants;
|
|
8
|
+
export interface ButtonProps extends Omit<MuiButtonProps, 'variant'> {
|
|
9
|
+
variant?: MuiButtonProps['variant'] | LegacyVariant;
|
|
10
|
+
}
|
|
11
|
+
export declare const Button: React.ForwardRefExoticComponent<Omit<ButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
12
|
+
export default Button;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Button as MuiButton } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
// legacy variant names, mapped to their MUI counterpart
|
|
4
|
+
const legacyVariants = { primary: 'contained', secondary: 'outlined' };
|
|
5
|
+
const isLegacy = (variant) => typeof variant === 'string' && variant in legacyVariants;
|
|
6
|
+
export const Button = React.forwardRef(({ variant, ...props }, ref) => (React.createElement(MuiButton, { ref: ref, variant: isLegacy(variant) ? legacyVariants[variant] : variant, ...props })));
|
|
7
|
+
Button.displayName = 'Button';
|
|
8
|
+
export default Button;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Dialog } from '@mui/material';
|
|
2
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Dialog } from './index';
|
|
3
3
|
declare const meta: Meta<typeof Dialog>;
|
|
4
4
|
export default meta;
|
|
5
|
-
type Story = StoryObj<typeof
|
|
5
|
+
type Story = StoryObj<typeof meta>;
|
|
6
6
|
export declare const Default: Story;
|
|
7
7
|
export declare const Screenshot: Story;
|
|
@@ -0,0 +1,81 @@
|
|
|
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';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Dialog } from './index';
|
|
5
|
+
const sizes = ['small', 'medium', 'large', 'full'];
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Dialog',
|
|
8
|
+
component: Dialog,
|
|
9
|
+
parameters: { layout: 'centered' },
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
argTypes: {
|
|
12
|
+
size: { control: 'select', options: sizes },
|
|
13
|
+
fullScreen: { control: 'boolean' },
|
|
14
|
+
scroll: { control: 'select', options: ['paper', 'body'] }
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export default meta;
|
|
18
|
+
// The cozy-ui doc example: a close button, a title, a list and two actions
|
|
19
|
+
const ExampleDialog = props => (React.createElement(Dialog, { "aria-labelledby": "dialog-title", ...props },
|
|
20
|
+
React.createElement(IconButton, { "aria-label": "Close", size: "medium", sx: { position: 'absolute', top: '1.15rem', right: '1.15rem' }, onClick: event => props.onClose?.(event, 'backdropClick') },
|
|
21
|
+
React.createElement(Icon, { icon: CrossMedium })),
|
|
22
|
+
React.createElement(DialogTitle, { id: "dialog-title", className: "dialogTitleWithClose" }, "Ada Lovelace"),
|
|
23
|
+
React.createElement(Divider, null),
|
|
24
|
+
React.createElement(List, { sx: { my: 1 } },
|
|
25
|
+
React.createElement(ListItemButton, null,
|
|
26
|
+
React.createElement(ListItemIcon, null,
|
|
27
|
+
React.createElement(Icon, { icon: FileTypeFolder, size: 32 })),
|
|
28
|
+
React.createElement(ListItemText, { primary: "I'm a primary text" })),
|
|
29
|
+
React.createElement(Divider, { variant: "inset" }),
|
|
30
|
+
React.createElement(ListItemButton, null,
|
|
31
|
+
React.createElement(ListItemIcon, null,
|
|
32
|
+
React.createElement(Icon, { icon: FileTypeText, size: 32 })),
|
|
33
|
+
React.createElement(ListItemText, { primary: "I'm a primary text", secondary: "I'm a secondary text" })),
|
|
34
|
+
React.createElement(Divider, { variant: "inset" }),
|
|
35
|
+
React.createElement(ListItemButton, null,
|
|
36
|
+
React.createElement(ListItemIcon, null,
|
|
37
|
+
React.createElement(Icon, { icon: FileTypeText, size: 32 })),
|
|
38
|
+
React.createElement(ListItemText, { primary: "I'm a primary text" }))),
|
|
39
|
+
React.createElement(Divider, null),
|
|
40
|
+
React.createElement(DialogActions, null,
|
|
41
|
+
React.createElement(Button, { variant: "outlined", onClick: event => props.onClose?.(event, 'backdropClick') }, "Close Modal"),
|
|
42
|
+
React.createElement(Button, null, "Click Me"))));
|
|
43
|
+
const OpenableDialog = props => {
|
|
44
|
+
const [open, setOpen] = React.useState(false);
|
|
45
|
+
return (React.createElement(React.Fragment, null,
|
|
46
|
+
React.createElement(Button, { onClick: () => setOpen(true) }, "Toggle modal"),
|
|
47
|
+
React.createElement(ExampleDialog, { ...props, open: open, onClose: () => setOpen(false) })));
|
|
48
|
+
};
|
|
49
|
+
export const Default = {
|
|
50
|
+
args: { size: 'medium' },
|
|
51
|
+
render: args => React.createElement(OpenableDialog, { ...args })
|
|
52
|
+
};
|
|
53
|
+
// Renders the dialog in the flow of the page rather than over it
|
|
54
|
+
const staticProps = {
|
|
55
|
+
open: true,
|
|
56
|
+
disablePortal: true,
|
|
57
|
+
hideBackdrop: true,
|
|
58
|
+
disableAutoFocus: true,
|
|
59
|
+
disableScrollLock: true,
|
|
60
|
+
sx: { position: 'static', '& .MuiDialog-container': { height: 'auto' } }
|
|
61
|
+
};
|
|
62
|
+
// Visual Regression - Dialog styles
|
|
63
|
+
export const Screenshot = {
|
|
64
|
+
tags: ['argos'],
|
|
65
|
+
render: () => (React.createElement(Stack, { spacing: 4 },
|
|
66
|
+
React.createElement("section", null,
|
|
67
|
+
React.createElement("h3", { style: { marginBottom: '12px' } }, "Example"),
|
|
68
|
+
React.createElement(ExampleDialog, { ...staticProps })),
|
|
69
|
+
sizes.map(size => (React.createElement("section", { key: size },
|
|
70
|
+
React.createElement("h3", { style: { marginBottom: '12px' } }, size),
|
|
71
|
+
React.createElement(Dialog, { ...staticProps, size: size, fullScreen: false },
|
|
72
|
+
React.createElement(DialogTitle, null, "Dialog Title"),
|
|
73
|
+
React.createElement(DialogContent, null,
|
|
74
|
+
React.createElement(DialogContentText, null,
|
|
75
|
+
"This is a ",
|
|
76
|
+
size,
|
|
77
|
+
" dialog with a title, some content and two action buttons.")),
|
|
78
|
+
React.createElement(DialogActions, null,
|
|
79
|
+
React.createElement(Button, { variant: "outlined" }, "Cancel"),
|
|
80
|
+
React.createElement(Button, null, "Confirm"))))))))
|
|
81
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DialogProps as MuiDialogProps } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export type DialogSize = 'small' | 'medium' | 'large' | 'full';
|
|
4
|
+
export interface DialogProps extends MuiDialogProps {
|
|
5
|
+
/** Paper width. Every size but `small` goes full screen on mobile */
|
|
6
|
+
size?: DialogSize;
|
|
7
|
+
}
|
|
8
|
+
export declare const Dialog: React.FC<DialogProps>;
|
|
9
|
+
export default Dialog;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Dialog as MuiDialog } from '@mui/material';
|
|
2
|
+
import cx from 'classnames';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { useBreakpoints } from '../../hooks/useBreakpoints';
|
|
5
|
+
export const Dialog = ({ size = 'medium', fullScreen, classes, ...props }) => {
|
|
6
|
+
const { isMobile } = useBreakpoints();
|
|
7
|
+
return (React.createElement(MuiDialog, { fullScreen: fullScreen ?? (size !== 'small' && isMobile), classes: { ...classes, paper: cx(size, classes?.paper) }, ...props }));
|
|
8
|
+
};
|
|
9
|
+
export default Dialog;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Theme } from '@mui/material/styles';
|
|
2
|
+
import React from 'react';
|
|
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
|
+
ref?: ((instance: HTMLUListElement | null) => void) | React.RefObject<HTMLUListElement> | null | undefined;
|
|
5
|
+
}, "style" | "className" | "children" | "classes" | "sx" | "dense" | "disablePadding" | "subheader"> & import("@mui/system").MUIStyledCommonProps<Theme>, {}, {}>;
|
|
6
|
+
export type NavProps = React.ComponentProps<typeof NavRoot>;
|
|
7
|
+
export declare const Nav: (props: NavProps) => React.ReactElement;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { List } from '@mui/material';
|
|
2
|
+
import { styled } from '@mui/material/styles';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
const NavRoot = styled(List)(({ theme }) => ({
|
|
5
|
+
margin: '24px 0',
|
|
6
|
+
padding: 0,
|
|
7
|
+
[theme.breakpoints.down('lg')]: {
|
|
8
|
+
display: 'flex',
|
|
9
|
+
justifyContent: 'space-around',
|
|
10
|
+
margin: '6px 0 4px'
|
|
11
|
+
}
|
|
12
|
+
}));
|
|
13
|
+
export const Nav = (props) => (React.createElement("nav", null,
|
|
14
|
+
React.createElement(NavRoot, { ...props })));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface NavDesktopDropdownProps {
|
|
3
|
+
label: string;
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
defaultOpen?: boolean;
|
|
6
|
+
limit?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare const NavDesktopDropdown: ({ label, children, defaultOpen, limit }: NavDesktopDropdownProps) => React.ReactElement | null;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Bottom, Icon } from '@linagora/twake-icons';
|
|
2
|
+
import { ListItem, Typography } from '@mui/material';
|
|
3
|
+
import React, { Children, isValidElement, useState } from 'react';
|
|
4
|
+
import { useBreakpoints } from '../../hooks/useBreakpoints';
|
|
5
|
+
export const NavDesktopDropdown = ({ label, children, defaultOpen = true, limit = 5 }) => {
|
|
6
|
+
const { isDesktop } = useBreakpoints();
|
|
7
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
8
|
+
const isActivated = Children.toArray(children).filter(isValidElement).length > limit;
|
|
9
|
+
const onToggle = () => setOpen(current => !current);
|
|
10
|
+
if (!isDesktop)
|
|
11
|
+
return null;
|
|
12
|
+
return (React.createElement(React.Fragment, null,
|
|
13
|
+
React.createElement(ListItem, { onClick: isActivated ? onToggle : undefined, sx: {
|
|
14
|
+
minHeight: 48,
|
|
15
|
+
py: 1,
|
|
16
|
+
px: 2,
|
|
17
|
+
justifyContent: 'space-between',
|
|
18
|
+
cursor: isActivated ? 'pointer' : undefined
|
|
19
|
+
} },
|
|
20
|
+
React.createElement(Typography, { variant: "caption", sx: { color: 'text.secondary' } }, label),
|
|
21
|
+
isActivated && (React.createElement(Typography, { component: "span", sx: { display: 'flex', ml: '5px', color: 'text.secondary' } },
|
|
22
|
+
React.createElement(Icon, { icon: Bottom, size: 10, rotate: open ? 0 : -90 })))),
|
|
23
|
+
open && children));
|
|
24
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Bottom, Top } from '@linagora/twake-icons';
|
|
2
|
+
import React, { Children, isValidElement, useState } from 'react';
|
|
3
|
+
import { useExtendI18n, useI18n } from 'twake-i18n';
|
|
4
|
+
import { NavIcon } from '../NavIcon';
|
|
5
|
+
import { NavItem } from '../NavItem';
|
|
6
|
+
import { NavLink } from '../NavLink';
|
|
7
|
+
import { NavText } from '../NavText';
|
|
8
|
+
import en from './locales/en.json';
|
|
9
|
+
import fr from './locales/fr.json';
|
|
10
|
+
import ru from './locales/ru.json';
|
|
11
|
+
import vi from './locales/vi.json';
|
|
12
|
+
import { useBreakpoints } from '../../hooks/useBreakpoints';
|
|
13
|
+
const locales = { en, fr, ru, vi };
|
|
14
|
+
export const NavDesktopLimiter = ({ children, max = 5 }) => {
|
|
15
|
+
useExtendI18n(locales);
|
|
16
|
+
const { t } = useI18n();
|
|
17
|
+
const [viewingAll, setViewingAll] = useState(false);
|
|
18
|
+
const { isMobile } = useBreakpoints();
|
|
19
|
+
const items = Children.toArray(children).filter(isValidElement);
|
|
20
|
+
const amountHidden = Math.max(0, items.length - max);
|
|
21
|
+
if (isMobile)
|
|
22
|
+
return null;
|
|
23
|
+
return (React.createElement(React.Fragment, null,
|
|
24
|
+
viewingAll ? items : items.slice(0, max),
|
|
25
|
+
amountHidden > 0 && (React.createElement(NavItem, { secondary: true },
|
|
26
|
+
React.createElement(NavLink, { onClick: () => setViewingAll(current => !current) },
|
|
27
|
+
React.createElement(NavIcon, { icon: viewingAll ? Top : Bottom }),
|
|
28
|
+
React.createElement(NavText, null, viewingAll
|
|
29
|
+
? t('NavDesktopLimiter.showLess')
|
|
30
|
+
: `${t('NavDesktopLimiter.showMore')} (${amountHidden})`))))));
|
|
31
|
+
};
|