|
1 |
| -import { css } from "@emotion/css"; |
2 |
| -import { |
3 |
| - type CSSObject, |
4 |
| - type Interpolation, |
5 |
| - type Theme, |
6 |
| - useTheme, |
7 |
| -} from "@emotion/react"; |
8 | 1 | import VpnKeyOutlined from "@mui/icons-material/VpnKeyOutlined";
|
9 | 2 | import FingerprintOutlinedIcon from "@mui/icons-material/FingerprintOutlined";
|
10 |
| -import { |
11 |
| - type FC, |
12 |
| - type ComponentType, |
13 |
| - type PropsWithChildren, |
14 |
| - type ReactNode, |
15 |
| -} from "react"; |
16 |
| -import { NavLink } from "react-router-dom"; |
17 | 3 | import AccountIcon from "@mui/icons-material/Person";
|
18 | 4 | import ScheduleIcon from "@mui/icons-material/EditCalendarOutlined";
|
19 | 5 | import SecurityIcon from "@mui/icons-material/LockOutlined";
|
20 | 6 | import type { User } from "api/typesGenerated";
|
21 |
| -import { Stack } from "components/Stack/Stack"; |
22 | 7 | import { UserAvatar } from "components/UserAvatar/UserAvatar";
|
23 | 8 | import { useDashboard } from "components/Dashboard/DashboardProvider";
|
24 |
| -import { combineClasses } from "utils/combineClasses"; |
25 |
| - |
26 |
| -const SidebarNavItem: FC< |
27 |
| - PropsWithChildren<{ href: string; icon: ReactNode }> |
28 |
| -> = ({ children, href, icon }) => { |
29 |
| - const theme = useTheme(); |
30 |
| - |
31 |
| - const sidebarNavItemStyles = css` |
32 |
| - color: inherit; |
33 |
| - display: block; |
34 |
| - font-size: 14px; |
35 |
| - text-decoration: none; |
36 |
| - padding: 12px 12px 12px 16px; |
37 |
| - border-radius: 4px; |
38 |
| - transition: background-color 0.15s ease-in-out; |
39 |
| - margin-bottom: 1px; |
40 |
| - position: relative; |
41 |
| -
|
42 |
| - &:hover { |
43 |
| - background-color: theme.palette.action.hover; |
44 |
| - } |
45 |
| - `; |
46 |
| - |
47 |
| - const sidebarNavItemActiveStyles = css` |
48 |
| - background-color: ${theme.palette.action.hover}; |
49 |
| -
|
50 |
| - &:before { |
51 |
| - content: ""; |
52 |
| - display: block; |
53 |
| - width: 3px; |
54 |
| - height: 100%; |
55 |
| - position: absolute; |
56 |
| - left: 0; |
57 |
| - top: 0; |
58 |
| - background-color: ${theme.palette.primary.main}; |
59 |
| - border-top-left-radius: 8px; |
60 |
| - border-bottom-left-radius: 8px; |
61 |
| - } |
62 |
| - `; |
63 |
| - |
64 |
| - return ( |
65 |
| - <NavLink |
66 |
| - to={href} |
67 |
| - className={({ isActive }) => |
68 |
| - combineClasses([ |
69 |
| - sidebarNavItemStyles, |
70 |
| - isActive ? sidebarNavItemActiveStyles : undefined, |
71 |
| - ]) |
72 |
| - } |
73 |
| - > |
74 |
| - <Stack alignItems="center" spacing={1.5} direction="row"> |
75 |
| - {icon} |
76 |
| - {children} |
77 |
| - </Stack> |
78 |
| - </NavLink> |
79 |
| - ); |
80 |
| -}; |
81 |
| - |
82 |
| -const SidebarNavItemIcon: React.FC<{ |
83 |
| - icon: ComponentType<{ className?: string }>; |
84 |
| -}> = ({ icon: Icon }) => { |
85 |
| - return <Icon css={{ width: 16, height: 16 }} />; |
86 |
| -}; |
| 9 | +import { |
| 10 | + Sidebar as BaseSidebar, |
| 11 | + SidebarHeader, |
| 12 | + SidebarNavItem, |
| 13 | +} from "components/Sidebar/Sidebar"; |
87 | 14 |
|
88 | 15 | export const Sidebar: React.FC<{ user: User }> = ({ user }) => {
|
89 | 16 | const { entitlements } = useDashboard();
|
90 | 17 | const allowAutostopRequirement =
|
91 | 18 | entitlements.features.template_autostop_requirement.enabled;
|
92 | 19 |
|
93 | 20 | return (
|
94 |
| - <nav css={styles.sidebar}> |
95 |
| - <Stack direction="row" alignItems="center" css={styles.userInfo}> |
96 |
| - <UserAvatar username={user.username} avatarURL={user.avatar_url} /> |
97 |
| - <Stack spacing={0} css={styles.userData}> |
98 |
| - <span css={styles.username}>{user.username}</span> |
99 |
| - <span css={styles.email}>{user.email}</span> |
100 |
| - </Stack> |
101 |
| - </Stack> |
102 |
| - |
103 |
| - <SidebarNavItem |
104 |
| - href="account" |
105 |
| - icon={<SidebarNavItemIcon icon={AccountIcon} />} |
106 |
| - > |
| 21 | + <BaseSidebar> |
| 22 | + <SidebarHeader |
| 23 | + avatar={ |
| 24 | + <UserAvatar username={user.username} avatarURL={user.avatar_url} /> |
| 25 | + } |
| 26 | + title={user.username} |
| 27 | + subtitle={user.email} |
| 28 | + /> |
| 29 | + ; |
| 30 | + <SidebarNavItem href="account" icon={AccountIcon}> |
107 | 31 | Account
|
108 | 32 | </SidebarNavItem>
|
109 | 33 | {allowAutostopRequirement && (
|
110 |
| - <SidebarNavItem |
111 |
| - href="schedule" |
112 |
| - icon={<SidebarNavItemIcon icon={ScheduleIcon} />} |
113 |
| - > |
| 34 | + <SidebarNavItem href="schedule" icon={ScheduleIcon}> |
114 | 35 | Schedule
|
115 | 36 | </SidebarNavItem>
|
116 | 37 | )}
|
117 |
| - <SidebarNavItem |
118 |
| - href="security" |
119 |
| - icon={<SidebarNavItemIcon icon={SecurityIcon} />} |
120 |
| - > |
| 38 | + <SidebarNavItem href="security" icon={SecurityIcon}> |
121 | 39 | Security
|
122 | 40 | </SidebarNavItem>
|
123 |
| - <SidebarNavItem |
124 |
| - href="ssh-keys" |
125 |
| - icon={<SidebarNavItemIcon icon={FingerprintOutlinedIcon} />} |
126 |
| - > |
| 41 | + <SidebarNavItem href="ssh-keys" icon={FingerprintOutlinedIcon}> |
127 | 42 | SSH Keys
|
128 | 43 | </SidebarNavItem>
|
129 |
| - <SidebarNavItem |
130 |
| - href="tokens" |
131 |
| - icon={<SidebarNavItemIcon icon={VpnKeyOutlined} />} |
132 |
| - > |
| 44 | + <SidebarNavItem href="tokens" icon={VpnKeyOutlined}> |
133 | 45 | Tokens
|
134 | 46 | </SidebarNavItem>
|
135 |
| - </nav> |
| 47 | + </BaseSidebar> |
136 | 48 | );
|
137 | 49 | };
|
138 |
| - |
139 |
| -const styles = { |
140 |
| - sidebar: { |
141 |
| - width: 245, |
142 |
| - flexShrink: 0, |
143 |
| - }, |
144 |
| - userInfo: (theme) => ({ |
145 |
| - ...(theme.typography.body2 as CSSObject), |
146 |
| - marginBottom: 16, |
147 |
| - }), |
148 |
| - userData: { |
149 |
| - overflow: "hidden", |
150 |
| - }, |
151 |
| - username: { |
152 |
| - fontWeight: 600, |
153 |
| - overflow: "hidden", |
154 |
| - textOverflow: "ellipsis", |
155 |
| - whiteSpace: "nowrap", |
156 |
| - }, |
157 |
| - email: (theme) => ({ |
158 |
| - color: theme.palette.text.secondary, |
159 |
| - fontSize: 12, |
160 |
| - overflow: "hidden", |
161 |
| - textOverflow: "ellipsis", |
162 |
| - }), |
163 |
| -} satisfies Record<string, Interpolation<Theme>>; |
0 commit comments