@lunit/design-system 1.0.0-b.4 → 2.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/dist/cjs/components/Alert/index.js +1 -1
- package/dist/cjs/components/Alert/index.js.map +1 -1
- package/dist/cjs/components/Button/index.js +1 -1
- package/dist/cjs/components/Button/index.js.map +1 -1
- package/dist/cjs/components/Checkbox/index.js +1 -1
- package/dist/cjs/components/Checkbox/index.js.map +1 -1
- package/dist/cjs/components/Chip/index.js +1 -1
- package/dist/cjs/components/Chip/index.js.map +1 -1
- package/dist/cjs/components/Dialog/index.js +2 -0
- package/dist/cjs/components/Dialog/index.js.map +1 -0
- package/dist/cjs/components/Radio/index.js +1 -1
- package/dist/cjs/components/Radio/index.js.map +1 -1
- package/dist/cjs/components/TextField/index.js +1 -1
- package/dist/cjs/components/TextField/index.js.map +1 -1
- package/dist/cjs/components/ToggleButton/index.js +1 -1
- package/dist/cjs/components/ToggleButton/index.js.map +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/components/Button/Button.js +21 -3
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Button/Button.styled.js +3 -6
- package/dist/components/Button/Button.styled.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.js +9 -19
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/Chip/Chip.js +6 -5
- package/dist/components/Chip/Chip.js.map +1 -1
- package/dist/components/Dialog/Dialog.js +61 -0
- package/dist/components/Dialog/Dialog.js.map +1 -0
- package/dist/components/Dialog/Dialog.styled.js +137 -0
- package/dist/components/Dialog/Dialog.styled.js.map +1 -0
- package/dist/components/Dialog/components/DialogAction.js +18 -0
- package/dist/components/Dialog/components/DialogAction.js.map +1 -0
- package/dist/components/Dialog/index.js +2 -0
- package/dist/components/Dialog/index.js.map +1 -0
- package/dist/components/Radio/Radio.js +7 -21
- package/dist/components/Radio/Radio.js.map +1 -1
- package/dist/components/TextField/TextField.js +4 -4
- package/dist/components/TextField/TextField.js.map +1 -1
- package/dist/components/ToggleButton/ToggleButton.styled.js +2 -3
- package/dist/components/ToggleButton/ToggleButton.styled.js.map +1 -1
- package/dist/foundation/Elevation/index.js +1 -1
- package/dist/foundation/Elevation/index.js.map +1 -1
- package/dist/foundation/Typography/index.js +12 -0
- package/dist/foundation/Typography/index.js.map +1 -1
- package/dist/foundation/Typography/tokens.js +1 -17
- package/dist/foundation/Typography/tokens.js.map +1 -1
- package/dist/foundation/colors/base/grey.js +3 -1
- package/dist/foundation/colors/base/grey.js.map +1 -1
- package/dist/foundation/colors/index.js +9 -6
- package/dist/foundation/colors/index.js.map +1 -1
- package/dist/foundation/colors/token/component.js +31 -115
- package/dist/foundation/colors/token/component.js.map +1 -1
- package/dist/foundation/colors/token/core.js +43 -75
- package/dist/foundation/colors/token/core.js.map +1 -1
- package/dist/foundation/index.js +1 -1
- package/dist/foundation/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/components/Alert/Alert.utils.d.ts +3 -3
- package/dist/types/components/Button/Button.styled.d.ts +9 -12
- package/dist/types/components/Button/Button.types.d.ts +8 -5
- package/dist/types/components/Chip/Chip.styled.d.ts +12 -12
- package/dist/types/components/Chip/Chip.types.d.ts +7 -2
- package/dist/types/components/Dialog/Dialog.d.ts +50 -0
- package/dist/types/components/Dialog/Dialog.styled.d.ts +12 -0
- package/dist/types/components/Dialog/components/DialogAction.d.ts +8 -0
- package/dist/types/components/Dialog/index.d.ts +2 -0
- package/dist/types/components/TextField/TextField.types.d.ts +8 -3
- package/dist/types/components/Toast/Toast.utils.d.ts +1 -1
- package/dist/types/components/ToggleButton/ToggleButton.styled.d.ts +2 -2
- package/dist/types/foundation/Elevation/index.d.ts +1 -1
- package/dist/types/foundation/Typography/index.d.ts +13 -1
- package/dist/types/foundation/Typography/tokens.d.ts +1 -1
- package/dist/types/foundation/colors/base/grey.d.ts +2 -0
- package/dist/types/foundation/colors/index.d.ts +9 -6
- package/dist/types/foundation/colors/token/types.d.ts +0 -2
- package/dist/types/foundation/colors/types.d.ts +78 -76
- package/dist/types/foundation/index.d.ts +9 -0
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/Button/Button.styled.ts +3 -6
- package/src/components/Button/Button.tsx +117 -42
- package/src/components/Button/Button.types.ts +8 -4
- package/src/components/Checkbox/Checkbox.tsx +39 -22
- package/src/components/Chip/Chip.tsx +15 -4
- package/src/components/Chip/Chip.types.ts +9 -2
- package/src/components/Dialog/Dialog.styled.ts +165 -0
- package/src/components/Dialog/Dialog.tsx +195 -0
- package/src/components/Dialog/components/DialogAction.tsx +36 -0
- package/src/components/Dialog/index.ts +14 -0
- package/src/components/Radio/Radio.tsx +37 -25
- package/src/components/TextField/TextField.tsx +10 -10
- package/src/components/TextField/TextField.types.ts +11 -4
- package/src/components/ToggleButton/ToggleButton.styled.ts +2 -3
- package/src/foundation/Elevation/index.ts +1 -1
- package/src/foundation/Typography/index.ts +12 -0
- package/src/foundation/Typography/tokens.ts +1 -17
- package/src/foundation/colors/base/grey.ts +3 -1
- package/src/foundation/colors/index.ts +9 -6
- package/src/foundation/colors/token/component.ts +24 -108
- package/src/foundation/colors/token/core.ts +39 -71
- package/src/foundation/colors/token/types.ts +0 -2
- package/src/foundation/colors/types.ts +78 -75
- package/src/foundation/index.ts +1 -1
- package/src/index.ts +1 -1
- package/src/stories/GettingStarted.mdx +88 -0
- package/src/stories/components/Button/BasicButton.stories.tsx +91 -52
- package/src/stories/components/Button/ButtonDocs.mdx +187 -0
- package/src/stories/components/Button/Color.stories.tsx +132 -0
- package/src/stories/components/Button/IconButton.stories.tsx +42 -25
- package/src/stories/components/Button/Kind.stories.tsx +75 -77
- package/src/stories/components/{SelectControl/Checkbox.stories.tsx → CheckBox/BasicCheckbox.stories.tsx} +84 -105
- package/src/stories/components/CheckBox/CheckboxDocs.mdx +85 -0
- package/src/stories/components/Chip/Chip.stories.tsx +80 -5
- package/src/stories/components/Chip/ChipDocs.mdx +132 -0
- package/src/stories/components/Dialog/Dialog.stories.tsx +320 -0
- package/src/stories/components/TextField/BasicTextField.stories.tsx +214 -0
- package/src/stories/components/TextField/TextFieldDocs.mdx +140 -0
- package/src/stories/components/TextField/TextFieldSize.stories.tsx +26 -3
- package/src/stories/components/ToggleButton/Basic.stories.tsx +312 -0
- package/src/stories/components/ToggleButton/ToggleButtonDocs.mdx +180 -0
- package/src/stories/components/ToggleButton/ToggleButtonKind.stories.tsx +65 -0
- package/src/stories/components/ToggleButton/WithIcon.stories.tsx +138 -0
- package/src/stories/foundation/Typography/Typography.mdx +31 -46
- package/src/stories/foundation/Typography/Typography.stories.tsx +30 -1
- package/src/stories/foundation/colors/ColorSystem.tsx +86 -0
- package/src/stories/foundation/colors/Docs.mdx +225 -0
- package/src/stories/foundation/colors/TokenPaletteTable.tsx +1 -5
- package/src/components/Modal/Modal.tsx +0 -8
- package/src/components/Modal/index.ts +0 -1
- package/src/stories/components/Modal/Modal.stories.tsx +0 -15
- package/src/stories/foundation/Typography/TypographyExamples.stories.tsx +0 -44
|
@@ -6,7 +6,7 @@ import type { CheckboxProps } from "@mui/material";
|
|
|
6
6
|
const CustomCheckbox = styled(MuiCheckbox)(({ theme }) => ({
|
|
7
7
|
width: 20,
|
|
8
8
|
height: 20,
|
|
9
|
-
padding:
|
|
9
|
+
padding: 0,
|
|
10
10
|
"&.Mui-disabled": {
|
|
11
11
|
opacity: 0.38,
|
|
12
12
|
},
|
|
@@ -27,30 +27,47 @@ const iconSize = {
|
|
|
27
27
|
|
|
28
28
|
const DefaultIcon = styled("span")(({ theme }) => ({
|
|
29
29
|
...iconSize,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 18'%3E%3Cpath" +
|
|
33
|
-
" fill-rule='evenodd' clip-rule='evenodd' d='M14 1.5H4C2.61929 1.5 1.5 2.61929 1.5 4V14C1.5 15.3807 2.61929 16.5 4 16.5H14C15.3807 " +
|
|
34
|
-
"16.5 16.5 15.3807 16.5 14V4C16.5 2.61929 15.3807 1.5 14 1.5ZM4 0C1.79086 0 0 1.79086 0 4V14C0 16.2091 1.79086 18 4 18H14C16.2091 18 18 16.2091 18 14V4C18 1.79086 16.2091 0 14 0H4Z' /%3E%3C/svg%3E\")",
|
|
30
|
+
borderRadius: "20%",
|
|
31
|
+
boxShadow: `inset 0 0 0 1.5px ${theme.palette.lunit_token.component.selectcontrol_off}`,
|
|
35
32
|
}));
|
|
36
33
|
|
|
37
|
-
const CheckedIcon =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
const CheckedIcon = () => {
|
|
35
|
+
return (
|
|
36
|
+
<svg
|
|
37
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
38
|
+
width="20"
|
|
39
|
+
height="20"
|
|
40
|
+
viewBox="0 0 20 20"
|
|
41
|
+
fill="none"
|
|
42
|
+
>
|
|
43
|
+
<path
|
|
44
|
+
fill-rule="evenodd"
|
|
45
|
+
clip-rule="evenodd"
|
|
46
|
+
d="M5 1C2.79086 1 1 2.79086 1 5V15C1 17.2091 2.79086 19 5 19H15C17.2091 19 19 17.2091 19 15V5C19 2.79086 17.2091 1 15 1H5ZM15.2516 8.14413C15.6074 7.72168 15.5533 7.09083 15.1309 6.73508C14.7084 6.37933 14.0776 6.43341 13.7218 6.85586L9.31824 12.0851L6.14993 9.37556C5.7302 9.01661 5.09895 9.06588 4.74 9.48561C4.38105 9.90533 4.43032 10.5366 4.85005 10.8955L8.78416 14.26C8.98672 14.4332 9.25006 14.5184 9.51571 14.4967C9.78135 14.4749 10.0273 14.348 10.199 14.1441L15.2516 8.14413Z"
|
|
47
|
+
fill="#00C9EA"
|
|
48
|
+
/>
|
|
49
|
+
</svg>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
45
52
|
|
|
46
|
-
const IndeterminateIcon =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
const IndeterminateIcon = () => {
|
|
54
|
+
return (
|
|
55
|
+
<svg
|
|
56
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
57
|
+
width="20"
|
|
58
|
+
height="20"
|
|
59
|
+
viewBox="0 0 20 20"
|
|
60
|
+
fill="none"
|
|
61
|
+
>
|
|
62
|
+
<path
|
|
63
|
+
fill-rule="evenodd"
|
|
64
|
+
clip-rule="evenodd"
|
|
65
|
+
d="M5 1C2.79086 1 1 2.79086 1 5V15C1 17.2091 2.79086 19 5 19H15C17.2091 19 19 17.2091 19 15V5C19 2.79086 17.2091 1 15 1H5ZM5 9C4.44772 9 4 9.44771 4 10C4 10.5523 4.44771 11 5 11L15 11C15.5523 11 16 10.5523 16 10C16 9.44772 15.5523 9 15 9L5 9Z"
|
|
66
|
+
fill="#00C9EA"
|
|
67
|
+
/>
|
|
68
|
+
</svg>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
54
71
|
|
|
55
72
|
const Checkbox = (props: CheckboxProps) => {
|
|
56
73
|
return (
|
|
@@ -19,8 +19,11 @@ import type {
|
|
|
19
19
|
} from "./Chip.types";
|
|
20
20
|
|
|
21
21
|
const Chip: ChipType = (props: ChipProps) => {
|
|
22
|
-
const { kind, onDelete, onClick, ...restProps } = props;
|
|
23
|
-
|
|
22
|
+
const { kind, variant, onDelete, onClick, ...restProps } = props;
|
|
23
|
+
|
|
24
|
+
const isOutlined = kind === "outlined" || variant === "outlined";
|
|
25
|
+
|
|
26
|
+
if (isOutlined) return <OutlinedChip {...props} />;
|
|
24
27
|
else if (onClick) return <EnableContainedChip {...props} />;
|
|
25
28
|
else if (onDelete) return <DeletableContainedChip {...props} />;
|
|
26
29
|
|
|
@@ -63,7 +66,7 @@ const getLabelMargin = (
|
|
|
63
66
|
};
|
|
64
67
|
|
|
65
68
|
const ReadOnlyContainedChip = (props: ReadOnlyContainedChipProps) => {
|
|
66
|
-
const { color = "primary", thumbnail, sx, ...restProps } = props;
|
|
69
|
+
const { color = "primary", thumbnail, sx, variant, ...restProps } = props;
|
|
67
70
|
|
|
68
71
|
return (
|
|
69
72
|
<StyledContainedChipBase
|
|
@@ -89,6 +92,7 @@ const EnableContainedChip = (props: EnableContainedChipProps) => {
|
|
|
89
92
|
onDelete,
|
|
90
93
|
onClick,
|
|
91
94
|
sx,
|
|
95
|
+
variant,
|
|
92
96
|
...restProps
|
|
93
97
|
} = props;
|
|
94
98
|
|
|
@@ -117,7 +121,14 @@ const DeleteIconWithHoverLayer = ({ onClick }: { onClick: () => void }) => {
|
|
|
117
121
|
);
|
|
118
122
|
};
|
|
119
123
|
const DeletableContainedChip = (props: DeletableContainedChipProps) => {
|
|
120
|
-
const {
|
|
124
|
+
const {
|
|
125
|
+
color = "primary",
|
|
126
|
+
thumbnail,
|
|
127
|
+
onDelete,
|
|
128
|
+
sx,
|
|
129
|
+
variant,
|
|
130
|
+
...restProps
|
|
131
|
+
} = props;
|
|
121
132
|
|
|
122
133
|
return (
|
|
123
134
|
<StyledContainedChipDeletable
|
|
@@ -6,6 +6,8 @@ import type {
|
|
|
6
6
|
} from "@mui/material";
|
|
7
7
|
import type { OverridableComponent } from "@mui/material/OverridableComponent";
|
|
8
8
|
|
|
9
|
+
type DesignSystemChipKind = "outlined" | "contained";
|
|
10
|
+
type DesignSystemAndMuiContainedChipKind = "filled" | "contained";
|
|
9
11
|
type ColorKeys = keyof typeof CHIP_COLORS;
|
|
10
12
|
export type ChipColor = (typeof CHIP_COLORS)[ColorKeys];
|
|
11
13
|
export type ChipThumbnail = string | JSX.Element;
|
|
@@ -18,12 +20,16 @@ export interface BaseChipProps
|
|
|
18
20
|
MuiChipProps,
|
|
19
21
|
"label" | "sx" | "style" | "classes" | "onDelete"
|
|
20
22
|
> {
|
|
21
|
-
kind
|
|
23
|
+
// either kind or variant
|
|
24
|
+
kind?: DesignSystemChipKind;
|
|
25
|
+
variant?: "outlined" | DesignSystemAndMuiContainedChipKind;
|
|
26
|
+
// mui variant = outlined | "filled" | undefined
|
|
22
27
|
color?: ChipColor;
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
export interface OutlinedChipProps extends BaseChipProps {
|
|
26
31
|
kind?: "outlined";
|
|
32
|
+
variant?: "outlined";
|
|
27
33
|
onClick?: never;
|
|
28
34
|
onDelete?: never;
|
|
29
35
|
}
|
|
@@ -32,9 +38,10 @@ export interface BaseContainedChipProps
|
|
|
32
38
|
extends BaseChipProps,
|
|
33
39
|
Omit<
|
|
34
40
|
MuiChipProps,
|
|
35
|
-
"color" | "size" | "
|
|
41
|
+
"color" | "size" | "avatar" | "deleteIcon" | "icon" | "variant"
|
|
36
42
|
> {
|
|
37
43
|
kind?: "contained";
|
|
44
|
+
variant?: DesignSystemAndMuiContainedChipKind;
|
|
38
45
|
thumbnail?: ChipThumbnail;
|
|
39
46
|
onClick?: () => void;
|
|
40
47
|
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { styled } from "@mui/material/styles";
|
|
2
|
+
|
|
3
|
+
import type { DialogBase } from "./Dialog";
|
|
4
|
+
import type { CSSObject } from "@mui/material/styles";
|
|
5
|
+
|
|
6
|
+
export interface DialogElementStyle {
|
|
7
|
+
[key: string]: CSSObject;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type DialogStyle = Pick<DialogBase, "size" | "type" | "nonModal">;
|
|
11
|
+
|
|
12
|
+
const DIALOG_WRAPPER_STYLE: DialogElementStyle = {
|
|
13
|
+
small: {
|
|
14
|
+
width: "320px",
|
|
15
|
+
maxWidth: "320px",
|
|
16
|
+
},
|
|
17
|
+
medium: {
|
|
18
|
+
width: "500px",
|
|
19
|
+
maxWidth: "840px",
|
|
20
|
+
},
|
|
21
|
+
modal: {
|
|
22
|
+
position: "relative",
|
|
23
|
+
boxShadow:
|
|
24
|
+
"0px 12px 24px 8px rgba(0, 0, 0, 0.12), 0px 12px 44px 3px rgba(0, 0, 0, 0.18)",
|
|
25
|
+
},
|
|
26
|
+
nonModal: {
|
|
27
|
+
position: "fixed",
|
|
28
|
+
top: "30px",
|
|
29
|
+
right: "30px",
|
|
30
|
+
boxShadow:
|
|
31
|
+
"0px 12px 24px 8px rgba(0, 0, 0, 0.36), 0px 12px 44px 3px rgba(0, 0, 0, 0.48)",
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const DIALOG_TITLE_STYLE: DialogElementStyle = {
|
|
36
|
+
small: {
|
|
37
|
+
height: "52px",
|
|
38
|
+
maxHeight: "100%",
|
|
39
|
+
padding: "20px 20px 8px 20px",
|
|
40
|
+
},
|
|
41
|
+
medium: {
|
|
42
|
+
height: "64px",
|
|
43
|
+
maxHeight: "100%",
|
|
44
|
+
padding: "30px 32px 6px 32px",
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const DIALOG_CONTENT_STYLE: DialogElementStyle = {
|
|
49
|
+
small: {
|
|
50
|
+
paddingInline: "20px calc(20px - 10px)",
|
|
51
|
+
paddingBottom: "28px",
|
|
52
|
+
},
|
|
53
|
+
smallAction: {
|
|
54
|
+
paddingInline: "20px calc(20px - 10px)",
|
|
55
|
+
paddingBottom: "8px",
|
|
56
|
+
},
|
|
57
|
+
medium: {
|
|
58
|
+
paddingInline: "32px calc(32px - 14px)",
|
|
59
|
+
paddingBottom: "32px",
|
|
60
|
+
},
|
|
61
|
+
mediumAction: {
|
|
62
|
+
paddingInline: "32px calc(32px - 14px)",
|
|
63
|
+
paddingBottom: "16px",
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const DIALOG_ACTION_STYLE: DialogElementStyle = {
|
|
68
|
+
small: {
|
|
69
|
+
height: "64px",
|
|
70
|
+
padding: "8px 20px 20px 20px",
|
|
71
|
+
},
|
|
72
|
+
medium: {
|
|
73
|
+
height: "84px",
|
|
74
|
+
padding: "16px 32px 32px 32px",
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const StyledBackdrop = styled("div")({
|
|
79
|
+
position: "fixed",
|
|
80
|
+
top: 0,
|
|
81
|
+
left: 0,
|
|
82
|
+
width: "100%",
|
|
83
|
+
height: "100%",
|
|
84
|
+
backgroundColor: "rgba(17, 17, 19, 0.7)",
|
|
85
|
+
zIndex: 1000,
|
|
86
|
+
display: "grid",
|
|
87
|
+
placeItems: "center",
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export const StyledDialog = styled("div")<DialogStyle>(
|
|
91
|
+
({ theme, size, nonModal, type }) => ({
|
|
92
|
+
zIndex: 1001,
|
|
93
|
+
maxHeight: "80vh",
|
|
94
|
+
display: "flex",
|
|
95
|
+
flexDirection: "column",
|
|
96
|
+
boxSizing: "border-box",
|
|
97
|
+
borderRadius: "10px",
|
|
98
|
+
backgroundColor: theme.palette.lunit_token.core.bg_03,
|
|
99
|
+
color: theme.palette.lunit_token.core.text_normal,
|
|
100
|
+
|
|
101
|
+
...DIALOG_WRAPPER_STYLE[size === "small" ? "small" : "medium"],
|
|
102
|
+
...DIALOG_WRAPPER_STYLE[nonModal ? "nonModal" : "modal"],
|
|
103
|
+
|
|
104
|
+
"& #dialog-title": {
|
|
105
|
+
...DIALOG_TITLE_STYLE[size === "small" ? "small" : "medium"],
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
"& #dialog-content": {
|
|
109
|
+
...DIALOG_CONTENT_STYLE[
|
|
110
|
+
size === "small" && type !== "passive"
|
|
111
|
+
? "smallAction"
|
|
112
|
+
: size === "small"
|
|
113
|
+
? "small"
|
|
114
|
+
: size === "medium" && type !== "passive"
|
|
115
|
+
? "mediumAction"
|
|
116
|
+
: "medium"
|
|
117
|
+
],
|
|
118
|
+
|
|
119
|
+
scrollbarGutter: "stable",
|
|
120
|
+
"::-webkit-scrollbar": {
|
|
121
|
+
width: size === "small" ? "10px" : "14px",
|
|
122
|
+
},
|
|
123
|
+
"::webkit-scrollbar-track": {
|
|
124
|
+
background: "transparent",
|
|
125
|
+
},
|
|
126
|
+
"::-webkit-scrollbar-thumb": {
|
|
127
|
+
backgroundClip: "padding-box",
|
|
128
|
+
border: `2px solid transparent`,
|
|
129
|
+
/**
|
|
130
|
+
* Figma's border-radius is 6px, but actual border radius is 10px since padding 2px is added.
|
|
131
|
+
*/
|
|
132
|
+
borderRadius: "10px",
|
|
133
|
+
backgroundColor: theme.palette.lunit_token.component.scrollbars_bg,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
"& #dialog-action": {
|
|
138
|
+
...DIALOG_ACTION_STYLE[size === "small" ? "small" : "medium"],
|
|
139
|
+
},
|
|
140
|
+
})
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
export const StyledDialogTitle = styled("header")({
|
|
144
|
+
display: "flex",
|
|
145
|
+
width: "100%",
|
|
146
|
+
flex: "0 0 auto",
|
|
147
|
+
alignItems: "center",
|
|
148
|
+
justifyContent: "flex-start",
|
|
149
|
+
gap: "8px",
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
export const StyledDialogTitleIconWrapper = styled("div")({
|
|
153
|
+
display: "flex",
|
|
154
|
+
justifyContent: "center",
|
|
155
|
+
width: "20px",
|
|
156
|
+
height: "20px",
|
|
157
|
+
position: "relative",
|
|
158
|
+
marginBottom: "1px",
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
export const StyledDialogContent = styled("div")(({ theme }) => ({
|
|
162
|
+
...theme.typography.body2_14_regular,
|
|
163
|
+
flex: "1 1 auto",
|
|
164
|
+
overflowY: "scroll",
|
|
165
|
+
}));
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
import { createPortal } from "react-dom";
|
|
3
|
+
import { Close } from "@lunit/design-system-icons";
|
|
4
|
+
|
|
5
|
+
import { DialogAction } from "./components/DialogAction";
|
|
6
|
+
import {
|
|
7
|
+
StyledBackdrop,
|
|
8
|
+
StyledDialog,
|
|
9
|
+
StyledDialogContent,
|
|
10
|
+
StyledDialogTitle,
|
|
11
|
+
StyledDialogTitleIconWrapper,
|
|
12
|
+
} from "./Dialog.styled";
|
|
13
|
+
import Button from "../Button";
|
|
14
|
+
import Typography from "../Typography";
|
|
15
|
+
|
|
16
|
+
import type { SxProps } from "@mui/material/styles";
|
|
17
|
+
import type { TypographyProps } from "@mui/material";
|
|
18
|
+
|
|
19
|
+
export interface DialogBase {
|
|
20
|
+
isOpen: boolean;
|
|
21
|
+
onClose(): void;
|
|
22
|
+
type?: "passive" | "action"; // default passive
|
|
23
|
+
nonModal?: boolean; // default false
|
|
24
|
+
title: string;
|
|
25
|
+
titleIcon?: React.ReactNode;
|
|
26
|
+
titleVariant?: TypographyProps["variant"];
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
actions?: React.ReactNode;
|
|
29
|
+
enableBackButtonClose?: boolean;
|
|
30
|
+
enableBackdropClose?: boolean;
|
|
31
|
+
size?: "small" | "medium"; // default "small"
|
|
32
|
+
sx?: SxProps;
|
|
33
|
+
style?: React.CSSProperties;
|
|
34
|
+
className?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface PassiveDialogType extends DialogBase {
|
|
38
|
+
type: "passive";
|
|
39
|
+
actions?: undefined;
|
|
40
|
+
enableBackButtonClose?: true;
|
|
41
|
+
enableBackdropClose?: true;
|
|
42
|
+
}
|
|
43
|
+
export interface ActionDialogType extends DialogBase {
|
|
44
|
+
type: "action";
|
|
45
|
+
actions: React.ReactNode;
|
|
46
|
+
enableBackButtonClose?: boolean;
|
|
47
|
+
enableBackdropClose?: boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface PassiveModalProps extends PassiveDialogType {
|
|
51
|
+
nonModal?: false;
|
|
52
|
+
}
|
|
53
|
+
export interface ActionModalProps extends ActionDialogType {
|
|
54
|
+
nonModal?: false;
|
|
55
|
+
}
|
|
56
|
+
export type ModalProps = PassiveModalProps | ActionModalProps;
|
|
57
|
+
|
|
58
|
+
export interface PassiveNonModalProps extends PassiveDialogType {
|
|
59
|
+
nonModal?: true;
|
|
60
|
+
}
|
|
61
|
+
export interface ActionNonModalProps extends ActionDialogType {
|
|
62
|
+
nonModal?: true;
|
|
63
|
+
enableBackdropClose?: false;
|
|
64
|
+
}
|
|
65
|
+
export type NonModalProps = PassiveNonModalProps | ActionNonModalProps;
|
|
66
|
+
|
|
67
|
+
export type DialogProps = ModalProps | NonModalProps;
|
|
68
|
+
|
|
69
|
+
function Dialog(props: DialogProps) {
|
|
70
|
+
const { isOpen, type, nonModal = false, onClose } = props;
|
|
71
|
+
|
|
72
|
+
const isActionModal = type === "action" && !nonModal;
|
|
73
|
+
const isPassiveModal = type === "passive" && !nonModal;
|
|
74
|
+
const isActionNonModal = type === "action" && nonModal;
|
|
75
|
+
|
|
76
|
+
function handleBackdropClose(e: React.MouseEvent<HTMLDivElement>) {
|
|
77
|
+
const isClosable =
|
|
78
|
+
isPassiveModal || (isActionModal && props.enableBackdropClose);
|
|
79
|
+
|
|
80
|
+
if (!isClosable) return;
|
|
81
|
+
if (e.target !== e.currentTarget) return;
|
|
82
|
+
|
|
83
|
+
onClose();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
const isClosable =
|
|
88
|
+
isOpen &&
|
|
89
|
+
(isPassiveModal ||
|
|
90
|
+
(isActionModal && props.enableBackdropClose) ||
|
|
91
|
+
(isActionNonModal && props.enableBackButtonClose));
|
|
92
|
+
|
|
93
|
+
if (!isClosable) return;
|
|
94
|
+
|
|
95
|
+
function handleEscClose(event: KeyboardEvent) {
|
|
96
|
+
if (event.key === "Escape") onClose();
|
|
97
|
+
}
|
|
98
|
+
function handleBackButtonClose(event: KeyboardEvent) {
|
|
99
|
+
if (event.key === "Backspace") onClose();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
document.addEventListener("keydown", handleEscClose);
|
|
103
|
+
document.addEventListener("keydown", handleBackButtonClose);
|
|
104
|
+
|
|
105
|
+
return () => {
|
|
106
|
+
document.removeEventListener("keydown", handleEscClose);
|
|
107
|
+
document.removeEventListener("keydown", handleBackButtonClose);
|
|
108
|
+
};
|
|
109
|
+
}, [isOpen, isPassiveModal, onClose]);
|
|
110
|
+
|
|
111
|
+
if (!isOpen) return null;
|
|
112
|
+
return createPortal(
|
|
113
|
+
nonModal ? (
|
|
114
|
+
<DialogBase dialogProps={{ ...props }} />
|
|
115
|
+
) : (
|
|
116
|
+
<StyledBackdrop
|
|
117
|
+
onClick={handleBackdropClose}
|
|
118
|
+
data-testid="dialog-backdrop"
|
|
119
|
+
>
|
|
120
|
+
<DialogBase dialogProps={{ ...props }} />
|
|
121
|
+
</StyledBackdrop>
|
|
122
|
+
),
|
|
123
|
+
|
|
124
|
+
document.body
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function DialogBase({ dialogProps }: { dialogProps: DialogBase }) {
|
|
129
|
+
const {
|
|
130
|
+
nonModal = false,
|
|
131
|
+
onClose,
|
|
132
|
+
title,
|
|
133
|
+
titleIcon,
|
|
134
|
+
titleVariant = "headline5",
|
|
135
|
+
children,
|
|
136
|
+
actions,
|
|
137
|
+
type,
|
|
138
|
+
size = "small",
|
|
139
|
+
sx,
|
|
140
|
+
style,
|
|
141
|
+
className,
|
|
142
|
+
} = dialogProps;
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<StyledDialog
|
|
146
|
+
role="dialog"
|
|
147
|
+
aria-labelledby="dialog-title"
|
|
148
|
+
size={size}
|
|
149
|
+
nonModal={nonModal}
|
|
150
|
+
type={type}
|
|
151
|
+
sx={{
|
|
152
|
+
...sx,
|
|
153
|
+
}}
|
|
154
|
+
style={style}
|
|
155
|
+
className={`dialog ${className ?? ""}`}
|
|
156
|
+
>
|
|
157
|
+
<StyledDialogTitle id="dialog-title" className="dialog-title-wrapper">
|
|
158
|
+
{titleIcon && (
|
|
159
|
+
<StyledDialogTitleIconWrapper className="dialog-title-icon">
|
|
160
|
+
{titleIcon}
|
|
161
|
+
</StyledDialogTitleIconWrapper>
|
|
162
|
+
)}
|
|
163
|
+
<Typography
|
|
164
|
+
component="h2"
|
|
165
|
+
id="dialog-title-text"
|
|
166
|
+
variant={titleVariant}
|
|
167
|
+
>
|
|
168
|
+
{title}
|
|
169
|
+
</Typography>
|
|
170
|
+
{type === "passive" && (
|
|
171
|
+
<Button
|
|
172
|
+
id="dialog-title-close-button"
|
|
173
|
+
data-testid="dialog-title-close-button"
|
|
174
|
+
kind="ghost"
|
|
175
|
+
color="secondary"
|
|
176
|
+
icon={<Close />}
|
|
177
|
+
onClick={onClose}
|
|
178
|
+
sx={{
|
|
179
|
+
marginRight: 0,
|
|
180
|
+
marginLeft: "auto",
|
|
181
|
+
}}
|
|
182
|
+
/>
|
|
183
|
+
)}
|
|
184
|
+
</StyledDialogTitle>
|
|
185
|
+
<StyledDialogContent id="dialog-content">{children}</StyledDialogContent>
|
|
186
|
+
{type === "action" && actions !== null ? (
|
|
187
|
+
// `actions !== null` is used to not render DialogAction when actions is undefined
|
|
188
|
+
// There was a case when actions is undefined, but DialogAction is rendered with null children
|
|
189
|
+
<DialogAction>{actions}</DialogAction>
|
|
190
|
+
) : null}
|
|
191
|
+
</StyledDialog>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export default Dialog;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { styled } from "@mui/material/styles";
|
|
3
|
+
|
|
4
|
+
interface DialogActionProps {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
justifyContent?: React.CSSProperties["justifyContent"];
|
|
7
|
+
sx?: React.CSSProperties;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const StyledDialogActions = styled("div")({
|
|
11
|
+
display: "flex",
|
|
12
|
+
flex: "0 0 auto",
|
|
13
|
+
alignItems: "center",
|
|
14
|
+
justifyContent: "flex-end",
|
|
15
|
+
gap: 8,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export function DialogAction(props: DialogActionProps) {
|
|
19
|
+
const { children, justifyContent, sx } = props;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<StyledDialogActions
|
|
23
|
+
id="dialog-action"
|
|
24
|
+
data-testid="dialog-action"
|
|
25
|
+
className="dialog-action"
|
|
26
|
+
sx={{
|
|
27
|
+
justifyContent,
|
|
28
|
+
...sx,
|
|
29
|
+
}}
|
|
30
|
+
>
|
|
31
|
+
{children}
|
|
32
|
+
</StyledDialogActions>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default DialogAction;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { default } from "./Dialog";
|
|
2
|
+
|
|
3
|
+
export type {
|
|
4
|
+
DialogBase,
|
|
5
|
+
PassiveDialogType,
|
|
6
|
+
ActionDialogType,
|
|
7
|
+
PassiveModalProps,
|
|
8
|
+
ActionModalProps,
|
|
9
|
+
PassiveNonModalProps,
|
|
10
|
+
ActionNonModalProps,
|
|
11
|
+
ModalProps,
|
|
12
|
+
NonModalProps,
|
|
13
|
+
DialogProps,
|
|
14
|
+
} from "./Dialog";
|
|
@@ -13,36 +13,48 @@ const CustomRadio = styled(MuiRadio)(({ theme }) => ({
|
|
|
13
13
|
display: "block",
|
|
14
14
|
width: 24,
|
|
15
15
|
height: 24,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath" +
|
|
19
|
-
" fill-rule='evenodd' clip-rule='evenodd' d='M12 23C18.0751 23 23 18.0751 23 12C23 5.92487 18.0751 1 12 1C5.92487 1 1 5.92487 1 12C1 18.0751 5.92487 23 12 23ZM12 24C18.6274 24 24 18.6274 24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 " +
|
|
20
|
-
"5.37258 0 12C0 18.6274 5.37258 24 12 24Z' /%3E%3C/svg%3E\")",
|
|
16
|
+
borderRadius: "50%",
|
|
17
|
+
border: `1px solid ${theme.palette.lunit_token.core.focused}`,
|
|
21
18
|
},
|
|
22
19
|
}));
|
|
23
20
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
const DefaultIcon = () => {
|
|
22
|
+
return (
|
|
23
|
+
<svg
|
|
24
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
25
|
+
width="20"
|
|
26
|
+
height="20"
|
|
27
|
+
viewBox="0 0 20 20"
|
|
28
|
+
fill="none"
|
|
29
|
+
>
|
|
30
|
+
<path
|
|
31
|
+
fill-rule="evenodd"
|
|
32
|
+
clip-rule="evenodd"
|
|
33
|
+
d="M10 17.5C14.1421 17.5 17.5 14.1421 17.5 10C17.5 5.85786 14.1421 2.5 10 2.5C5.85786 2.5 2.5 5.85786 2.5 10C2.5 14.1421 5.85786 17.5 10 17.5ZM10 19C14.9706 19 19 14.9706 19 10C19 5.02944 14.9706 1 10 1C5.02944 1 1 5.02944 1 10C1 14.9706 5.02944 19 10 19Z"
|
|
34
|
+
fill="#99999B"
|
|
35
|
+
/>
|
|
36
|
+
</svg>
|
|
37
|
+
);
|
|
27
38
|
};
|
|
28
39
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
const CheckedIcon = () => {
|
|
41
|
+
return (
|
|
42
|
+
<svg
|
|
43
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
44
|
+
width="20"
|
|
45
|
+
height="20"
|
|
46
|
+
viewBox="0 0 20 20"
|
|
47
|
+
fill="none"
|
|
48
|
+
>
|
|
49
|
+
<path
|
|
50
|
+
fill-rule="evenodd"
|
|
51
|
+
clip-rule="evenodd"
|
|
52
|
+
d="M10 15C12.7614 15 15 12.7614 15 10C15 7.23858 12.7614 5 10 5C7.23858 5 5 7.23858 5 10C5 12.7614 7.23858 15 10 15ZM10 19C14.9706 19 19 14.9706 19 10C19 5.02944 14.9706 1 10 1C5.02944 1 1 5.02944 1 10C1 14.9706 5.02944 19 10 19Z"
|
|
53
|
+
fill="#00C9EA"
|
|
54
|
+
/>
|
|
55
|
+
</svg>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
46
58
|
|
|
47
59
|
const Radio = (props: RadioProps) => {
|
|
48
60
|
return (
|