rouse-ui-kit 0.1.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/index.js +5465 -0
- package/dist/index.umd.cjs +103 -0
- package/package.json +40 -0
- package/src/App.tsx +435 -0
- package/src/components/Button/ButtonContained.tsx +37 -0
- package/src/components/Button/ButtonOutlined.tsx +37 -0
- package/src/components/Button/ButtonText.tsx +36 -0
- package/src/components/Button/index.ts +3 -0
- package/src/components/Checkbox/Checkbox.tsx +41 -0
- package/src/components/Checkbox/index.ts +1 -0
- package/src/components/Chip/ChipFilled.tsx +110 -0
- package/src/components/Chip/ChipOutlined.tsx +107 -0
- package/src/components/Chip/ChipStatus.tsx +59 -0
- package/src/components/Chip/ChipStatusOutlined.tsx +59 -0
- package/src/components/Chip/index.ts +7 -0
- package/src/components/IconButton/IconButtonOutlined.tsx +67 -0
- package/src/components/IconButton/index.ts +1 -0
- package/src/components/Label/LabelFilled.tsx +84 -0
- package/src/components/Label/LabelOutlined.tsx +85 -0
- package/src/components/Label/index.ts +3 -0
- package/src/components/Menu/Menu.tsx +205 -0
- package/src/components/Menu/index.ts +2 -0
- package/src/components/Select/SelectOutlined.tsx +77 -0
- package/src/components/Select/index.ts +1 -0
- package/src/components/TextField/TextFieldOutlined.tsx +104 -0
- package/src/components/TextField/index.ts +1 -0
- package/src/design-tokens.ts +120 -0
- package/src/index.ts +32 -0
- package/src/main.tsx +13 -0
- package/src/theme.ts +220 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import CheckIcon from "@mui/icons-material/Check";
|
|
2
|
+
import SearchIcon from "@mui/icons-material/Search";
|
|
3
|
+
import {
|
|
4
|
+
Box,
|
|
5
|
+
Checkbox,
|
|
6
|
+
InputAdornment,
|
|
7
|
+
List,
|
|
8
|
+
ListItemButton,
|
|
9
|
+
OutlinedInput,
|
|
10
|
+
Paper,
|
|
11
|
+
Typography,
|
|
12
|
+
} from "@mui/material";
|
|
13
|
+
|
|
14
|
+
export type MenuOption = { value: string; label: string };
|
|
15
|
+
|
|
16
|
+
type MenuProps = {
|
|
17
|
+
options?: MenuOption[];
|
|
18
|
+
selectedValues?: string[];
|
|
19
|
+
search?: boolean;
|
|
20
|
+
multiSelect?: boolean;
|
|
21
|
+
searchValue?: string;
|
|
22
|
+
onSearchChange?: (value: string) => void;
|
|
23
|
+
onSelect?: (value: string) => void;
|
|
24
|
+
onSelectAll?: () => void;
|
|
25
|
+
onClear?: () => void;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const scrollbarSx = {
|
|
29
|
+
overflowY: "auto",
|
|
30
|
+
// custom scrollbar matching Figma: 6px thumb, #dedede track border
|
|
31
|
+
"&::-webkit-scrollbar": { width: "14px" },
|
|
32
|
+
"&::-webkit-scrollbar-track": {
|
|
33
|
+
background: "white",
|
|
34
|
+
borderLeft: "1px solid #dedede",
|
|
35
|
+
},
|
|
36
|
+
"&::-webkit-scrollbar-thumb": {
|
|
37
|
+
backgroundColor: "#666666",
|
|
38
|
+
borderRadius: "4px",
|
|
39
|
+
border: "4px solid white",
|
|
40
|
+
backgroundClip: "content-box",
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default function Menu({
|
|
45
|
+
options = [],
|
|
46
|
+
selectedValues = [],
|
|
47
|
+
search = false,
|
|
48
|
+
multiSelect = false,
|
|
49
|
+
searchValue = "",
|
|
50
|
+
onSearchChange,
|
|
51
|
+
onSelect,
|
|
52
|
+
onSelectAll,
|
|
53
|
+
onClear,
|
|
54
|
+
}: MenuProps) {
|
|
55
|
+
return (
|
|
56
|
+
<Paper
|
|
57
|
+
elevation={8}
|
|
58
|
+
sx={{
|
|
59
|
+
width: 320,
|
|
60
|
+
height: 300,
|
|
61
|
+
borderRadius: "4px",
|
|
62
|
+
overflow: "hidden",
|
|
63
|
+
display: "flex",
|
|
64
|
+
bgcolor: "white",
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
<Box sx={{ flex: 1, ...scrollbarSx }}>
|
|
68
|
+
<List disablePadding sx={{ py: "8px" }}>
|
|
69
|
+
|
|
70
|
+
{/* Search field */}
|
|
71
|
+
{search && (
|
|
72
|
+
<Box sx={{ px: "16px", py: "8px" }}>
|
|
73
|
+
<OutlinedInput
|
|
74
|
+
fullWidth
|
|
75
|
+
placeholder="Search"
|
|
76
|
+
value={searchValue}
|
|
77
|
+
onChange={(e) => onSearchChange?.(e.target.value)}
|
|
78
|
+
endAdornment={
|
|
79
|
+
<InputAdornment position="end">
|
|
80
|
+
<SearchIcon sx={{ fontSize: 20, color: "#666666" }} />
|
|
81
|
+
</InputAdornment>
|
|
82
|
+
}
|
|
83
|
+
sx={{
|
|
84
|
+
height: 32,
|
|
85
|
+
fontSize: 14,
|
|
86
|
+
letterSpacing: "0.15px",
|
|
87
|
+
color: "#666666",
|
|
88
|
+
"& .MuiOutlinedInput-notchedOutline": { borderColor: "#999999" },
|
|
89
|
+
"&:hover .MuiOutlinedInput-notchedOutline": { borderColor: "#4c4c4c" },
|
|
90
|
+
"& .MuiOutlinedInput-input": { padding: "4px 14px" },
|
|
91
|
+
}}
|
|
92
|
+
/>
|
|
93
|
+
</Box>
|
|
94
|
+
)}
|
|
95
|
+
|
|
96
|
+
{/* Select All / Clear */}
|
|
97
|
+
{multiSelect && (
|
|
98
|
+
<Box
|
|
99
|
+
sx={{
|
|
100
|
+
px: "16px",
|
|
101
|
+
py: "6px",
|
|
102
|
+
display: "flex",
|
|
103
|
+
justifyContent: "space-between",
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
<Typography
|
|
107
|
+
component="span"
|
|
108
|
+
onClick={onSelectAll}
|
|
109
|
+
sx={{
|
|
110
|
+
fontSize: 16,
|
|
111
|
+
lineHeight: 1.5,
|
|
112
|
+
letterSpacing: "0.15px",
|
|
113
|
+
color: "#191919",
|
|
114
|
+
textDecoration: "underline",
|
|
115
|
+
cursor: "pointer",
|
|
116
|
+
userSelect: "none",
|
|
117
|
+
}}
|
|
118
|
+
>
|
|
119
|
+
Select All
|
|
120
|
+
</Typography>
|
|
121
|
+
<Typography
|
|
122
|
+
component="span"
|
|
123
|
+
onClick={onClear}
|
|
124
|
+
sx={{
|
|
125
|
+
fontSize: 16,
|
|
126
|
+
lineHeight: 1.5,
|
|
127
|
+
letterSpacing: "0.15px",
|
|
128
|
+
color: "#4c4c4c",
|
|
129
|
+
textDecoration: "underline",
|
|
130
|
+
cursor: "pointer",
|
|
131
|
+
userSelect: "none",
|
|
132
|
+
}}
|
|
133
|
+
>
|
|
134
|
+
Clear
|
|
135
|
+
</Typography>
|
|
136
|
+
</Box>
|
|
137
|
+
)}
|
|
138
|
+
|
|
139
|
+
{/* Menu items */}
|
|
140
|
+
{options.map((opt) => {
|
|
141
|
+
const isSelected = selectedValues.includes(opt.value);
|
|
142
|
+
return (
|
|
143
|
+
<ListItemButton
|
|
144
|
+
key={opt.value}
|
|
145
|
+
onClick={() => onSelect?.(opt.value)}
|
|
146
|
+
selected={isSelected && !multiSelect}
|
|
147
|
+
sx={{
|
|
148
|
+
px: "16px",
|
|
149
|
+
py: "6px",
|
|
150
|
+
minHeight: 36,
|
|
151
|
+
gap: 0,
|
|
152
|
+
"&.Mui-selected": {
|
|
153
|
+
bgcolor: "rgba(0, 0, 0, 0.08)", // --light/light/selected
|
|
154
|
+
"&:hover": { bgcolor: "rgba(0, 0, 0, 0.08)" },
|
|
155
|
+
},
|
|
156
|
+
"&:hover": { bgcolor: "rgba(0, 0, 0, 0.04)" },
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
159
|
+
{/* Checkbox mode */}
|
|
160
|
+
{multiSelect && (
|
|
161
|
+
<Checkbox
|
|
162
|
+
checked={isSelected}
|
|
163
|
+
size="small"
|
|
164
|
+
tabIndex={-1}
|
|
165
|
+
disableRipple
|
|
166
|
+
sx={{
|
|
167
|
+
padding: "8px",
|
|
168
|
+
mr: "0px",
|
|
169
|
+
ml: "-8px",
|
|
170
|
+
color: "#4c4c4c",
|
|
171
|
+
"&.Mui-checked": { color: "#4c4c4c" },
|
|
172
|
+
}}
|
|
173
|
+
/>
|
|
174
|
+
)}
|
|
175
|
+
|
|
176
|
+
{/* Label */}
|
|
177
|
+
<Typography
|
|
178
|
+
sx={{
|
|
179
|
+
flex: 1,
|
|
180
|
+
fontSize: 16,
|
|
181
|
+
fontWeight: 400,
|
|
182
|
+
lineHeight: 1.5,
|
|
183
|
+
letterSpacing: "0.15px",
|
|
184
|
+
color: "#191919",
|
|
185
|
+
whiteSpace: "nowrap",
|
|
186
|
+
overflow: "hidden",
|
|
187
|
+
textOverflow: "ellipsis",
|
|
188
|
+
}}
|
|
189
|
+
>
|
|
190
|
+
{opt.label}
|
|
191
|
+
</Typography>
|
|
192
|
+
|
|
193
|
+
{/* Check icon for single-select selected state */}
|
|
194
|
+
{!multiSelect && isSelected && (
|
|
195
|
+
<CheckIcon sx={{ fontSize: 20, color: "#4c4c4c", ml: "8px" }} />
|
|
196
|
+
)}
|
|
197
|
+
</ListItemButton>
|
|
198
|
+
);
|
|
199
|
+
})}
|
|
200
|
+
|
|
201
|
+
</List>
|
|
202
|
+
</Box>
|
|
203
|
+
</Paper>
|
|
204
|
+
);
|
|
205
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import CancelIcon from "@mui/icons-material/Cancel";
|
|
2
|
+
import {
|
|
3
|
+
FormControl,
|
|
4
|
+
FormHelperText,
|
|
5
|
+
IconButton,
|
|
6
|
+
InputAdornment,
|
|
7
|
+
InputLabel,
|
|
8
|
+
MenuItem,
|
|
9
|
+
Select,
|
|
10
|
+
type SelectChangeEvent,
|
|
11
|
+
} from "@mui/material";
|
|
12
|
+
|
|
13
|
+
type SelectOption = { value: string; label: string };
|
|
14
|
+
|
|
15
|
+
type SelectOutlinedProps = {
|
|
16
|
+
label?: string;
|
|
17
|
+
value?: string;
|
|
18
|
+
options?: SelectOption[];
|
|
19
|
+
helperText?: string;
|
|
20
|
+
error?: boolean;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
clearable?: boolean;
|
|
23
|
+
onChange?: (value: string) => void;
|
|
24
|
+
onClear?: () => void;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default function SelectOutlined({
|
|
28
|
+
label = "Label",
|
|
29
|
+
value = "",
|
|
30
|
+
options = [],
|
|
31
|
+
helperText,
|
|
32
|
+
error = false,
|
|
33
|
+
disabled = false,
|
|
34
|
+
clearable = false,
|
|
35
|
+
onChange,
|
|
36
|
+
onClear,
|
|
37
|
+
}: SelectOutlinedProps) {
|
|
38
|
+
const showClear = clearable && !!value;
|
|
39
|
+
|
|
40
|
+
const handleChange = (event: SelectChangeEvent) => {
|
|
41
|
+
onChange?.(event.target.value);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<FormControl variant="outlined" error={error} disabled={disabled} fullWidth>
|
|
46
|
+
<InputLabel>{label}</InputLabel>
|
|
47
|
+
<Select
|
|
48
|
+
value={value}
|
|
49
|
+
label={label}
|
|
50
|
+
onChange={handleChange}
|
|
51
|
+
endAdornment={
|
|
52
|
+
showClear ? (
|
|
53
|
+
<InputAdornment position="end" sx={{ mr: "4px" }}>
|
|
54
|
+
<IconButton
|
|
55
|
+
size="small"
|
|
56
|
+
onClick={onClear}
|
|
57
|
+
tabIndex={-1}
|
|
58
|
+
sx={{ padding: "2px", color: "#666666" }}
|
|
59
|
+
>
|
|
60
|
+
<CancelIcon sx={{ fontSize: 20 }} />
|
|
61
|
+
</IconButton>
|
|
62
|
+
</InputAdornment>
|
|
63
|
+
) : undefined
|
|
64
|
+
}
|
|
65
|
+
// Make room for the clear button before the dropdown arrow
|
|
66
|
+
sx={showClear ? { "& .MuiSelect-select": { paddingRight: "60px !important" } } : undefined}
|
|
67
|
+
>
|
|
68
|
+
{options.map((opt) => (
|
|
69
|
+
<MenuItem key={opt.value} value={opt.value}>
|
|
70
|
+
{opt.label}
|
|
71
|
+
</MenuItem>
|
|
72
|
+
))}
|
|
73
|
+
</Select>
|
|
74
|
+
{helperText && <FormHelperText>{helperText}</FormHelperText>}
|
|
75
|
+
</FormControl>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as SelectOutlined } from "./SelectOutlined";
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import CancelIcon from "@mui/icons-material/Cancel";
|
|
2
|
+
import { IconButton, InputAdornment, TextField } from "@mui/material";
|
|
3
|
+
import type { ElementType } from "react";
|
|
4
|
+
|
|
5
|
+
type TextFieldOutlinedProps = {
|
|
6
|
+
label?: string;
|
|
7
|
+
value?: string;
|
|
8
|
+
helperText?: string;
|
|
9
|
+
error?: boolean;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
clearable?: boolean;
|
|
12
|
+
icon?: ElementType;
|
|
13
|
+
type?: string;
|
|
14
|
+
onChange?: (value: string) => void;
|
|
15
|
+
onClear?: () => void;
|
|
16
|
+
onIconClick?: () => void;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Border selectors self-contained here — resting color is #999 (--light/gray/40),
|
|
20
|
+
// different from SelectOutlined which uses rgba(0,0,0,0.23).
|
|
21
|
+
const borderSx = {
|
|
22
|
+
"& .MuiOutlinedInput-root": {
|
|
23
|
+
"& .MuiOutlinedInput-notchedOutline": {
|
|
24
|
+
borderColor: "#999999", // --light/gray/40
|
|
25
|
+
},
|
|
26
|
+
"&:hover .MuiOutlinedInput-notchedOutline": {
|
|
27
|
+
borderColor: "#4c4c4c", // --light/primary/main
|
|
28
|
+
},
|
|
29
|
+
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
|
|
30
|
+
borderColor: "#4c4c4c",
|
|
31
|
+
borderWidth: "2px",
|
|
32
|
+
},
|
|
33
|
+
"&.Mui-error .MuiOutlinedInput-notchedOutline": {
|
|
34
|
+
borderColor: "#d32f2f", // --light/error/main
|
|
35
|
+
borderWidth: "2px",
|
|
36
|
+
},
|
|
37
|
+
"&.Mui-disabled .MuiOutlinedInput-notchedOutline": {
|
|
38
|
+
borderColor: "rgba(0, 0, 0, 0.12)", // --light/other/divider
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default function TextFieldOutlined({
|
|
44
|
+
label = "Label",
|
|
45
|
+
value = "",
|
|
46
|
+
helperText,
|
|
47
|
+
error = false,
|
|
48
|
+
disabled = false,
|
|
49
|
+
clearable = false,
|
|
50
|
+
icon: Icon,
|
|
51
|
+
type = "text",
|
|
52
|
+
onChange,
|
|
53
|
+
onClear,
|
|
54
|
+
onIconClick,
|
|
55
|
+
}: TextFieldOutlinedProps) {
|
|
56
|
+
const showClear = clearable && !!value;
|
|
57
|
+
|
|
58
|
+
const endAdornment =
|
|
59
|
+
showClear || Icon ? (
|
|
60
|
+
<>
|
|
61
|
+
{showClear && (
|
|
62
|
+
<InputAdornment position="end">
|
|
63
|
+
<IconButton
|
|
64
|
+
size="small"
|
|
65
|
+
onClick={onClear}
|
|
66
|
+
tabIndex={-1}
|
|
67
|
+
sx={{ padding: "2px", color: "#666666" }}
|
|
68
|
+
>
|
|
69
|
+
<CancelIcon sx={{ fontSize: 20 }} />
|
|
70
|
+
</IconButton>
|
|
71
|
+
</InputAdornment>
|
|
72
|
+
)}
|
|
73
|
+
{Icon && (
|
|
74
|
+
<InputAdornment position="end">
|
|
75
|
+
{onIconClick ? (
|
|
76
|
+
<IconButton size="small" onClick={onIconClick} tabIndex={-1} edge="end">
|
|
77
|
+
<Icon sx={{ fontSize: 24, color: "#666666" }} />
|
|
78
|
+
</IconButton>
|
|
79
|
+
) : (
|
|
80
|
+
<Icon sx={{ fontSize: 24, color: "#666666" }} />
|
|
81
|
+
)}
|
|
82
|
+
</InputAdornment>
|
|
83
|
+
)}
|
|
84
|
+
</>
|
|
85
|
+
) : undefined;
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<TextField
|
|
89
|
+
variant="outlined"
|
|
90
|
+
label={label}
|
|
91
|
+
value={value}
|
|
92
|
+
helperText={helperText}
|
|
93
|
+
error={error}
|
|
94
|
+
disabled={disabled}
|
|
95
|
+
type={type}
|
|
96
|
+
fullWidth
|
|
97
|
+
onChange={(e) => onChange?.(e.target.value)}
|
|
98
|
+
slotProps={{
|
|
99
|
+
input: { endAdornment },
|
|
100
|
+
}}
|
|
101
|
+
sx={borderSx}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as TextFieldOutlined } from "./TextFieldOutlined";
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rouse Design System — Design Tokens
|
|
3
|
+
* Source: Rouse Design System Figma library
|
|
4
|
+
* Reflects all --light/* CSS variables used across components.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// ─── Primary ──────────────────────────────────────────────────────────────────
|
|
8
|
+
export const primary = {
|
|
9
|
+
lighter: "#d9d9d9",
|
|
10
|
+
light: "#808080",
|
|
11
|
+
main: "#4c4c4c",
|
|
12
|
+
dark: "#191919",
|
|
13
|
+
tint: "#f1f1f1",
|
|
14
|
+
shade4p: "rgba(76, 76, 76, 0.04)",
|
|
15
|
+
shade8p: "rgba(76, 76, 76, 0.08)",
|
|
16
|
+
shade12p: "rgba(76, 76, 76, 0.12)",
|
|
17
|
+
shade30p: "rgba(76, 76, 76, 0.30)",
|
|
18
|
+
shade50p: "rgba(76, 76, 76, 0.50)",
|
|
19
|
+
contrastText: "#ffffff",
|
|
20
|
+
} as const;
|
|
21
|
+
|
|
22
|
+
// ─── Secondary ────────────────────────────────────────────────────────────────
|
|
23
|
+
export const secondary = {
|
|
24
|
+
light: "#6f8de3",
|
|
25
|
+
main: "#2c4d9e",
|
|
26
|
+
dark: "#00215f",
|
|
27
|
+
tint: "#eef1fc",
|
|
28
|
+
shade4p: "rgba(44, 77, 158, 0.04)",
|
|
29
|
+
shade12p: "rgba(44, 77, 158, 0.12)",
|
|
30
|
+
contrastText: "#ffffff",
|
|
31
|
+
} as const;
|
|
32
|
+
|
|
33
|
+
// ─── Semantic ─────────────────────────────────────────────────────────────────
|
|
34
|
+
export const error = {
|
|
35
|
+
light: "#ef5350",
|
|
36
|
+
main: "#d32f2f",
|
|
37
|
+
tint: "#fdeaea",
|
|
38
|
+
} as const;
|
|
39
|
+
|
|
40
|
+
export const warning = {
|
|
41
|
+
lighter: "#ffd28c",
|
|
42
|
+
main: "#ef6c00",
|
|
43
|
+
tint: "#fff3e0",
|
|
44
|
+
} as const;
|
|
45
|
+
|
|
46
|
+
export const success = {
|
|
47
|
+
light: "#4caf50",
|
|
48
|
+
main: "#2e7d32",
|
|
49
|
+
tint: "#eaf5ea",
|
|
50
|
+
} as const;
|
|
51
|
+
|
|
52
|
+
export const info = {
|
|
53
|
+
light: "#03a9f4",
|
|
54
|
+
main: "#0288d1",
|
|
55
|
+
tint: "#e1f5fe",
|
|
56
|
+
} as const;
|
|
57
|
+
|
|
58
|
+
// ─── Text ─────────────────────────────────────────────────────────────────────
|
|
59
|
+
export const text = {
|
|
60
|
+
primary: "#191919",
|
|
61
|
+
secondary: "#666666",
|
|
62
|
+
disabled: "#999999",
|
|
63
|
+
} as const;
|
|
64
|
+
|
|
65
|
+
// ─── Background ───────────────────────────────────────────────────────────────
|
|
66
|
+
export const background = {
|
|
67
|
+
white: "#ffffff",
|
|
68
|
+
paper: "#fafafa",
|
|
69
|
+
default: "#f5f5f5",
|
|
70
|
+
} as const;
|
|
71
|
+
|
|
72
|
+
// ─── Gray scale ───────────────────────────────────────────────────────────────
|
|
73
|
+
export const gray = {
|
|
74
|
+
1: "#f7f7f7", // --light/gray/1
|
|
75
|
+
10: "#e5e5e5", // --light/gray/10
|
|
76
|
+
20: "#cccccc", // --light/gray/20
|
|
77
|
+
30: "#b2b2b2", // --light/gray/30
|
|
78
|
+
40: "#999999", // --light/gray/40
|
|
79
|
+
} as const;
|
|
80
|
+
|
|
81
|
+
// ─── Interaction overlays ─────────────────────────────────────────────────────
|
|
82
|
+
export const interaction = {
|
|
83
|
+
hover: "rgba(0, 0, 0, 0.04)", // --light/light/hover
|
|
84
|
+
selected: "rgba(0, 0, 0, 0.08)", // --light/light/selected
|
|
85
|
+
focus: "#dee0ff", // --light/blue/10
|
|
86
|
+
focusRing: "#bbc3ff", // --light/blue/20
|
|
87
|
+
} as const;
|
|
88
|
+
|
|
89
|
+
// ─── Other / borders ──────────────────────────────────────────────────────────
|
|
90
|
+
export const other = {
|
|
91
|
+
outlinedBorder: "rgba(0, 0, 0, 0.23)", // --light/other/outlined-border
|
|
92
|
+
divider: "rgba(0, 0, 0, 0.12)", // --light/other/divider
|
|
93
|
+
} as const;
|
|
94
|
+
|
|
95
|
+
// ─── Typography scale ─────────────────────────────────────────────────────────
|
|
96
|
+
// Source: Rouse Design System (Roboto font family, MUI Material Design scale)
|
|
97
|
+
export const typography = {
|
|
98
|
+
fontFamily: "'Roboto', sans-serif",
|
|
99
|
+
h1: { fontSize: "6rem", fontWeight: 300, lineHeight: 1.167, letterSpacing: "-0.01563em" },
|
|
100
|
+
h2: { fontSize: "3.75rem", fontWeight: 300, lineHeight: 1.2, letterSpacing: "-0.00833em" },
|
|
101
|
+
h3: { fontSize: "3rem", fontWeight: 400, lineHeight: 1.167, letterSpacing: "0em" },
|
|
102
|
+
h4: { fontSize: "2.125rem",fontWeight: 400, lineHeight: 1.235, letterSpacing: "0.00735em" },
|
|
103
|
+
h5: { fontSize: "1.5rem", fontWeight: 400, lineHeight: 1.334, letterSpacing: "0em" },
|
|
104
|
+
h6: { fontSize: "1.25rem", fontWeight: 500, lineHeight: 1.6, letterSpacing: "0.0075em" },
|
|
105
|
+
subtitle1: { fontSize: "1rem", fontWeight: 400, lineHeight: 1.75, letterSpacing: "0.00938em" },
|
|
106
|
+
subtitle2: { fontSize: "0.875rem",fontWeight: 500, lineHeight: 1.57, letterSpacing: "0.00714em" },
|
|
107
|
+
body1: { fontSize: "1rem", fontWeight: 400, lineHeight: 1.5, letterSpacing: "0.00938em" },
|
|
108
|
+
body2: { fontSize: "0.875rem",fontWeight: 400, lineHeight: 1.43, letterSpacing: "0.01071em" },
|
|
109
|
+
// Custom text styles found in components
|
|
110
|
+
button: { fontSize: "1rem", fontWeight: 500, lineHeight: "26px", letterSpacing: "0.4px", textTransform: "none" as const },
|
|
111
|
+
caption: { fontSize: "0.75rem", fontWeight: 400, lineHeight: 1.6, letterSpacing: "0.4px" },
|
|
112
|
+
overline: { fontSize: "0.75rem", fontWeight: 400, lineHeight: 2.66, letterSpacing: "0.08333em", textTransform: "uppercase" as const },
|
|
113
|
+
// Component-specific text styles
|
|
114
|
+
inputText: { fontSize: "1rem", fontWeight: 400, lineHeight: "24px", letterSpacing: "0.15px" },
|
|
115
|
+
inputLabel: { fontSize: "0.75rem", fontWeight: 400, lineHeight: "12px", letterSpacing: "0.15px" },
|
|
116
|
+
menuItem: { fontSize: "1rem", fontWeight: 400, lineHeight: 1.5, letterSpacing: "0.15px" },
|
|
117
|
+
chip: { fontSize: "0.8125rem",fontWeight: 400, lineHeight: "18px", letterSpacing: "0.16px" },
|
|
118
|
+
badgeLabel: { fontSize: "0.75rem", fontWeight: 500, lineHeight: "20px", letterSpacing: "0.14px" },
|
|
119
|
+
helperText: { fontSize: "0.75rem", fontWeight: 400, lineHeight: 1.6, letterSpacing: "0.4px" },
|
|
120
|
+
} as const;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Rouse UI Kit — public exports
|
|
2
|
+
// Import this package in Figma Make to use all components.
|
|
3
|
+
|
|
4
|
+
export { default as ButtonContained } from "./components/Button/ButtonContained";
|
|
5
|
+
export { default as ButtonOutlined } from "./components/Button/ButtonOutlined";
|
|
6
|
+
export { default as ButtonText } from "./components/Button/ButtonText";
|
|
7
|
+
|
|
8
|
+
export { default as Checkbox } from "./components/Checkbox/Checkbox";
|
|
9
|
+
|
|
10
|
+
export { default as IconButtonOutlined } from "./components/IconButton/IconButtonOutlined";
|
|
11
|
+
|
|
12
|
+
export { default as LabelFilled } from "./components/Label/LabelFilled";
|
|
13
|
+
export { default as LabelOutlined } from "./components/Label/LabelOutlined";
|
|
14
|
+
|
|
15
|
+
export { default as Menu } from "./components/Menu/Menu";
|
|
16
|
+
|
|
17
|
+
export { default as SelectOutlined } from "./components/Select/SelectOutlined";
|
|
18
|
+
|
|
19
|
+
export { default as TextFieldOutlined } from "./components/TextField/TextFieldOutlined";
|
|
20
|
+
|
|
21
|
+
export { default as ChipFilled } from "./components/Chip/ChipFilled";
|
|
22
|
+
export { default as ChipOutlined } from "./components/Chip/ChipOutlined";
|
|
23
|
+
export { default as ChipStatus } from "./components/Chip/ChipStatus";
|
|
24
|
+
export { default as ChipStatusOutlined } from "./components/Chip/ChipStatusOutlined";
|
|
25
|
+
|
|
26
|
+
export { default as theme } from "./theme";
|
|
27
|
+
export * from "./design-tokens";
|
|
28
|
+
|
|
29
|
+
export type { ChipColor } from "./components/Chip/ChipFilled";
|
|
30
|
+
export type { ChipStatusColor } from "./components/Chip/ChipStatus";
|
|
31
|
+
export type { LabelColor, LabelIcon } from "./components/Label/LabelFilled";
|
|
32
|
+
export type { MenuOption } from "./components/Menu/Menu";
|
package/src/main.tsx
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ThemeProvider } from "@mui/material/styles";
|
|
2
|
+
import { StrictMode } from "react";
|
|
3
|
+
import { createRoot } from "react-dom/client";
|
|
4
|
+
import App from "./App";
|
|
5
|
+
import theme from "./theme";
|
|
6
|
+
|
|
7
|
+
createRoot(document.getElementById("root")!).render(
|
|
8
|
+
<StrictMode>
|
|
9
|
+
<ThemeProvider theme={theme}>
|
|
10
|
+
<App />
|
|
11
|
+
</ThemeProvider>
|
|
12
|
+
</StrictMode>
|
|
13
|
+
);
|