Skip to content

Commit e3e626a

Browse files
committed
emotion: NavbarView
1 parent 4201a56 commit e3e626a

File tree

1 file changed

+114
-124
lines changed

1 file changed

+114
-124
lines changed

site/src/components/Dashboard/Navbar/NavbarView.tsx

Lines changed: 114 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@ import Drawer from "@mui/material/Drawer";
22
import IconButton from "@mui/material/IconButton";
33
import List from "@mui/material/List";
44
import ListItem from "@mui/material/ListItem";
5-
import { makeStyles } from "@mui/styles";
65
import MenuIcon from "@mui/icons-material/Menu";
76
import { CoderIcon } from "components/Icons/CoderIcon";
8-
import { FC, useRef, useState } from "react";
7+
import { type FC, type ReactNode, useRef, useState } from "react";
98
import { NavLink, useLocation, useNavigate } from "react-router-dom";
109
import { colors } from "theme/colors";
1110
import * as TypesGen from "api/typesGenerated";
1211
import { navHeight } from "theme/constants";
13-
import { combineClasses } from "utils/combineClasses";
1412
import { UserDropdown } from "./UserDropdown/UserDropdown";
1513
import Box from "@mui/material/Box";
1614
import Menu from "@mui/material/Menu";
@@ -25,6 +23,7 @@ import { BUTTON_SM_HEIGHT } from "theme/theme";
2523
import { ProxyStatusLatency } from "components/ProxyStatusLatency/ProxyStatusLatency";
2624
import { usePermissions } from "hooks/usePermissions";
2725
import Typography from "@mui/material/Typography";
26+
import { css, type Interpolation, type Theme, useTheme } from "@emotion/react";
2827

2928
export const USERS_LINK = `/users?filter=${encodeURIComponent(
3029
"status:active",
@@ -50,52 +49,128 @@ export const Language = {
5049
deployment: "Deployment",
5150
};
5251

53-
const NavItems: React.FC<
54-
React.PropsWithChildren<{
55-
className?: string;
56-
canViewAuditLog: boolean;
57-
canViewDeployment: boolean;
58-
canViewAllUsers: boolean;
59-
}>
60-
> = ({ className, canViewAuditLog, canViewDeployment, canViewAllUsers }) => {
61-
const styles = useStyles();
52+
const styles = {
53+
desktopNavItems: (theme) => css`
54+
display: none;
55+
56+
${theme.breakpoints.up("md")} {
57+
display: flex;
58+
}
59+
`,
60+
mobileMenuButton: (theme) => css`
61+
${theme.breakpoints.up("md")} {
62+
display: none;
63+
}
64+
`,
65+
wrapper: (theme) => css`
66+
position: relative;
67+
display: flex;
68+
justify-content: space-between;
69+
align-items: center;
70+
71+
${theme.breakpoints.up("md")} {
72+
justify-content: flex-start;
73+
}
74+
`,
75+
drawerHeader: (theme) => ({
76+
padding: theme.spacing(2),
77+
paddingTop: theme.spacing(4),
78+
paddingBottom: theme.spacing(4),
79+
}),
80+
logo: (theme) => css`
81+
align-items: center;
82+
display: flex;
83+
height: ${navHeight}px;
84+
color: ${theme.palette.text.primary};
85+
padding: ${theme.spacing(2)};
86+
87+
// svg is for the Coder logo, img is for custom images
88+
& svg,
89+
& img {
90+
height: 100%;
91+
object-fit: contain;
92+
}
93+
`,
94+
drawerLogo: (theme) => ({
95+
padding: 0,
96+
maxHeight: theme.spacing(5),
97+
}),
98+
item: {
99+
padding: 0,
100+
},
101+
link: (theme) => css`
102+
align-items: center;
103+
color: ${colors.gray[6]};
104+
display: flex;
105+
flex: 1;
106+
font-size: 16px;
107+
padding: ${theme.spacing(1.5)} ${theme.spacing(2)};
108+
text-decoration: none;
109+
transition: background-color 0.15s ease-in-out;
110+
111+
&:hover {
112+
background-color: theme.palette.action.hover;
113+
}
114+
115+
${theme.breakpoints.up("md")} {
116+
height: ${navHeight};
117+
padding: 0 ${theme.spacing(3)};
118+
}
119+
`,
120+
} satisfies Record<string, Interpolation<Theme>>;
121+
122+
interface NavItemsProps {
123+
children?: ReactNode;
124+
className?: string;
125+
canViewAuditLog: boolean;
126+
canViewDeployment: boolean;
127+
canViewAllUsers: boolean;
128+
}
129+
130+
const NavItems: React.FC<NavItemsProps> = (props) => {
131+
const { className, canViewAuditLog, canViewDeployment, canViewAllUsers } =
132+
props;
62133
const location = useLocation();
134+
const theme = useTheme();
63135

64136
return (
65-
<List className={combineClasses([styles.navItems, className])}>
66-
<ListItem button className={styles.item}>
137+
<List css={{ padding: 0 }} className={className}>
138+
<ListItem button css={styles.item}>
67139
<NavLink
68-
className={combineClasses([
140+
css={[
69141
styles.link,
70-
location.pathname.startsWith("/@") && "active",
71-
])}
142+
location.pathname.startsWith("/@") && {
143+
color: theme.palette.text.primary,
144+
fontWeight: 500,
145+
},
146+
]}
72147
to="/workspaces"
73148
>
74149
{Language.workspaces}
75150
</NavLink>
76151
</ListItem>
77-
<ListItem button className={styles.item}>
78-
<NavLink className={styles.link} to="/templates">
152+
<ListItem button css={styles.item}>
153+
<NavLink css={styles.link} to="/templates">
79154
{Language.templates}
80155
</NavLink>
81156
</ListItem>
82157
{canViewAllUsers && (
83-
<ListItem button className={styles.item}>
84-
<NavLink className={styles.link} to={USERS_LINK}>
158+
<ListItem button css={styles.item}>
159+
<NavLink css={styles.link} to={USERS_LINK}>
85160
{Language.users}
86161
</NavLink>
87162
</ListItem>
88163
)}
89164
{canViewAuditLog && (
90-
<ListItem button className={styles.item}>
91-
<NavLink className={styles.link} to="/audit">
165+
<ListItem button css={styles.item}>
166+
<NavLink css={styles.link} to="/audit">
92167
{Language.audit}
93168
</NavLink>
94169
</ListItem>
95170
)}
96171
{canViewDeployment && (
97-
<ListItem button className={styles.item}>
98-
<NavLink className={styles.link} to="/deployment/general">
172+
<ListItem button css={styles.item}>
173+
<NavLink css={styles.link} to="/deployment/general">
99174
{Language.deployment}
100175
</NavLink>
101176
</ListItem>
@@ -114,15 +189,20 @@ export const NavbarView: FC<NavbarViewProps> = ({
114189
canViewAllUsers,
115190
proxyContextValue,
116191
}) => {
117-
const styles = useStyles();
118192
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
119193

120194
return (
121-
<nav className={styles.root}>
122-
<div className={styles.wrapper}>
195+
<nav
196+
css={(theme) => ({
197+
height: navHeight,
198+
background: theme.palette.background.paper,
199+
borderBottom: `1px solid ${theme.palette.divider}`,
200+
})}
201+
>
202+
<div css={styles.wrapper}>
123203
<IconButton
124204
aria-label="Open menu"
125-
className={styles.mobileMenuButton}
205+
css={styles.mobileMenuButton}
126206
onClick={() => {
127207
setIsDrawerOpen(true);
128208
}}
@@ -136,9 +216,9 @@ export const NavbarView: FC<NavbarViewProps> = ({
136216
open={isDrawerOpen}
137217
onClose={() => setIsDrawerOpen(false)}
138218
>
139-
<div className={styles.drawer}>
140-
<div className={styles.drawerHeader}>
141-
<div className={combineClasses([styles.logo, styles.drawerLogo])}>
219+
<div css={{ width: 250 }}>
220+
<div css={styles.drawerHeader}>
221+
<div css={[styles.logo, styles.drawerLogo]}>
142222
{logo_url ? (
143223
<img src={logo_url} alt="Custom Logo" />
144224
) : (
@@ -154,7 +234,7 @@ export const NavbarView: FC<NavbarViewProps> = ({
154234
</div>
155235
</Drawer>
156236

157-
<NavLink className={styles.logo} to="/workspaces">
237+
<NavLink css={styles.logo} to="/workspaces">
158238
{logo_url ? (
159239
<img src={logo_url} alt="Custom Logo" />
160240
) : (
@@ -163,7 +243,7 @@ export const NavbarView: FC<NavbarViewProps> = ({
163243
</NavLink>
164244

165245
<NavItems
166-
className={styles.desktopNavItems}
246+
css={styles.desktopNavItems}
167247
canViewAuditLog={canViewAuditLog}
168248
canViewDeployment={canViewDeployment}
169249
canViewAllUsers={canViewAllUsers}
@@ -385,93 +465,3 @@ const ProxyMenu: FC<{ proxyContextValue: ProxyContextValue }> = ({
385465
</>
386466
);
387467
};
388-
389-
const useStyles = makeStyles((theme) => ({
390-
displayInitial: {
391-
display: "initial",
392-
},
393-
root: {
394-
height: navHeight,
395-
background: theme.palette.background.paper,
396-
borderBottom: `1px solid ${theme.palette.divider}`,
397-
},
398-
wrapper: {
399-
position: "relative",
400-
display: "flex",
401-
justifyContent: "space-between",
402-
alignItems: "center",
403-
[theme.breakpoints.up("md")]: {
404-
justifyContent: "flex-start",
405-
},
406-
},
407-
drawer: {
408-
width: 250,
409-
},
410-
drawerHeader: {
411-
padding: theme.spacing(2),
412-
paddingTop: theme.spacing(4),
413-
paddingBottom: theme.spacing(4),
414-
},
415-
navItems: {
416-
padding: 0,
417-
},
418-
desktopNavItems: {
419-
display: "none",
420-
[theme.breakpoints.up("md")]: {
421-
display: "flex",
422-
},
423-
},
424-
mobileMenuButton: {
425-
[theme.breakpoints.up("md")]: {
426-
display: "none",
427-
},
428-
},
429-
logo: {
430-
alignItems: "center",
431-
display: "flex",
432-
height: navHeight,
433-
color: theme.palette.text.primary,
434-
padding: theme.spacing(2),
435-
// svg is for the Coder logo, img is for custom images
436-
"& svg, & img": {
437-
height: "100%",
438-
objectFit: "contain",
439-
},
440-
},
441-
drawerLogo: {
442-
padding: 0,
443-
maxHeight: theme.spacing(5),
444-
},
445-
title: {
446-
flex: 1,
447-
textAlign: "center",
448-
},
449-
item: {
450-
padding: 0,
451-
},
452-
link: {
453-
alignItems: "center",
454-
color: colors.gray[6],
455-
display: "flex",
456-
flex: 1,
457-
fontSize: 16,
458-
padding: `${theme.spacing(1.5)} ${theme.spacing(2)}`,
459-
textDecoration: "none",
460-
transition: "background-color 0.15s ease-in-out",
461-
462-
"&:hover": {
463-
backgroundColor: theme.palette.action.hover,
464-
},
465-
466-
// NavLink adds this class when the current route matches.
467-
"&.active": {
468-
color: theme.palette.text.primary,
469-
fontWeight: 500,
470-
},
471-
472-
[theme.breakpoints.up("md")]: {
473-
height: navHeight,
474-
padding: `0 ${theme.spacing(3)}`,
475-
},
476-
},
477-
}));

0 commit comments

Comments
 (0)