Skip to content

Commit 51efe96

Browse files
aslilacericpaulsen
authored andcommitted
refactor: avoid @emotion/css when possible (#10807)
1 parent 7612d9e commit 51efe96

File tree

20 files changed

+645
-604
lines changed

20 files changed

+645
-604
lines changed
Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import IconButton from "@mui/material/Button";
22
import Tooltip from "@mui/material/Tooltip";
33
import Check from "@mui/icons-material/Check";
4+
import { css, type Interpolation, type Theme } from "@emotion/react";
5+
import { type FC, type ReactNode } from "react";
46
import { useClipboard } from "hooks/useClipboard";
5-
import { css } from "@emotion/react";
67
import { FileCopyIcon } from "../Icons/FileCopyIcon";
78

89
interface CopyButtonProps {
10+
children?: ReactNode;
911
text: string;
1012
ctaCopy?: string;
11-
wrapperClassName?: string;
12-
buttonClassName?: string;
13+
wrapperStyles?: Interpolation<Theme>;
14+
buttonStyles?: Interpolation<Theme>;
1315
tooltipTitle?: string;
1416
}
1517

@@ -21,52 +23,51 @@ export const Language = {
2123
/**
2224
* Copy button used inside the CodeBlock component internally
2325
*/
24-
export const CopyButton: React.FC<React.PropsWithChildren<CopyButtonProps>> = ({
26+
export const CopyButton: FC<CopyButtonProps> = ({
2527
text,
2628
ctaCopy,
27-
wrapperClassName = "",
28-
buttonClassName = "",
29+
wrapperStyles,
30+
buttonStyles,
2931
tooltipTitle = Language.tooltipTitle,
3032
}) => {
3133
const { isCopied, copy: copyToClipboard } = useClipboard(text);
3234

33-
const fileCopyIconStyles = css`
34-
width: 20px;
35-
height: 20px;
36-
`;
37-
3835
return (
3936
<Tooltip title={tooltipTitle} placement="top">
40-
<div
41-
className={wrapperClassName}
42-
css={{
43-
display: "flex",
44-
}}
45-
>
37+
<div css={[{ display: "flex" }, wrapperStyles]}>
4638
<IconButton
47-
className={buttonClassName}
48-
css={(theme) => css`
49-
border-radius: 8px;
50-
padding: 8px;
51-
min-width: 32px;
39+
css={[
40+
(theme) => css`
41+
border-radius: 8px;
42+
padding: 8px;
43+
min-width: 32px;
5244
53-
&:hover {
54-
background: ${theme.palette.background.paper};
55-
}
56-
`}
45+
&:hover {
46+
background: ${theme.palette.background.paper};
47+
}
48+
`,
49+
buttonStyles,
50+
]}
5751
onClick={copyToClipboard}
5852
size="small"
5953
aria-label={Language.ariaLabel}
6054
variant="text"
6155
>
6256
{isCopied ? (
63-
<Check css={fileCopyIconStyles} />
57+
<Check css={styles.copyIcon} />
6458
) : (
65-
<FileCopyIcon css={fileCopyIconStyles} />
59+
<FileCopyIcon css={styles.copyIcon} />
6660
)}
6761
{ctaCopy && <div css={{ marginLeft: 8 }}>{ctaCopy}</div>}
6862
</IconButton>
6963
</div>
7064
</Tooltip>
7165
);
7266
};
67+
68+
const styles = {
69+
copyIcon: css`
70+
width: 20px;
71+
height: 20px;
72+
`,
73+
} satisfies Record<string, Interpolation<Theme>>;

site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx

Lines changed: 86 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import type {
55
} from "api/typesGenerated";
66
import {
77
type FC,
8+
type PropsWithChildren,
89
useMemo,
910
useEffect,
1011
useState,
11-
PropsWithChildren,
1212
} from "react";
1313
import prettyBytes from "pretty-bytes";
1414
import BuildingIcon from "@mui/icons-material/Build";
@@ -23,7 +23,6 @@ import WebTerminalIcon from "@mui/icons-material/WebAsset";
2323
import CollectedIcon from "@mui/icons-material/Compare";
2424
import RefreshIcon from "@mui/icons-material/Refresh";
2525
import Button from "@mui/material/Button";
26-
import { css as className } from "@emotion/css";
2726
import {
2827
css,
2928
type CSSObject,
@@ -40,44 +39,23 @@ import { getDisplayWorkspaceStatus } from "utils/workspace";
4039
import { colors } from "theme/colors";
4140
import { HelpTooltipTitle } from "components/HelpTooltip/HelpTooltip";
4241
import { Stack } from "components/Stack/Stack";
42+
import { type ClassName, useClassName } from "hooks/useClassName";
4343

4444
export const bannerHeight = 36;
4545

46-
const styles = {
47-
group: css`
48-
display: flex;
49-
align-items: center;
50-
`,
51-
category: (theme) => ({
52-
marginRight: 16,
53-
color: theme.palette.text.primary,
54-
}),
55-
values: (theme) => ({
56-
display: "flex",
57-
gap: 8,
58-
color: theme.palette.text.secondary,
59-
}),
60-
value: css`
61-
display: flex;
62-
align-items: center;
63-
gap: 4px;
64-
65-
& svg {
66-
width: 12px;
67-
height: 12px;
68-
}
69-
`,
70-
} satisfies Record<string, Interpolation<Theme>>;
71-
7246
export interface DeploymentBannerViewProps {
7347
health?: HealthcheckReport;
7448
stats?: DeploymentStats;
7549
fetchStats?: () => void;
7650
}
7751

78-
export const DeploymentBannerView: FC<DeploymentBannerViewProps> = (props) => {
79-
const { health, stats, fetchStats } = props;
52+
export const DeploymentBannerView: FC<DeploymentBannerViewProps> = ({
53+
health,
54+
stats,
55+
fetchStats,
56+
}) => {
8057
const theme = useTheme();
58+
const summaryTooltip = useClassName(classNames.summaryTooltip, []);
8159

8260
const aggregatedMinutes = useMemo(() => {
8361
if (!stats) {
@@ -114,6 +92,7 @@ export const DeploymentBannerView: FC<DeploymentBannerViewProps> = (props) => {
11492
clearTimeout(timeout);
11593
};
11694
}, [fetchStats, stats]);
95+
11796
const lastAggregated = useMemo(() => {
11897
if (!stats) {
11998
return;
@@ -127,34 +106,6 @@ export const DeploymentBannerView: FC<DeploymentBannerViewProps> = (props) => {
127106
}, [timeUntilRefresh, stats]);
128107

129108
const unhealthy = health && !health.healthy;
130-
131-
const statusBadgeStyle = css`
132-
display: flex;
133-
align-items: center;
134-
justify-content: center;
135-
background-color: ${unhealthy ? colors.red[10] : undefined};
136-
padding: 0 12px;
137-
height: 100%;
138-
color: #fff;
139-
140-
& svg {
141-
width: 16px;
142-
height: 16px;
143-
}
144-
`;
145-
146-
const statusSummaryStyle = className`
147-
${theme.typography.body2 as CSSObject}
148-
149-
margin: 0 0 4px 12px;
150-
width: 400px;
151-
padding: 16px;
152-
color: ${theme.palette.text.primary};
153-
background-color: ${theme.palette.background.paper};
154-
border: 1px solid ${theme.palette.divider};
155-
pointer-events: none;
156-
`;
157-
158109
const displayLatency = stats?.workspaces.connection_latency_ms.P50 || -1;
159110

160111
return (
@@ -178,7 +129,7 @@ export const DeploymentBannerView: FC<DeploymentBannerViewProps> = (props) => {
178129
}}
179130
>
180131
<Tooltip
181-
classes={{ tooltip: statusSummaryStyle }}
132+
classes={{ tooltip: summaryTooltip }}
182133
title={
183134
unhealthy ? (
184135
<>
@@ -214,11 +165,15 @@ export const DeploymentBannerView: FC<DeploymentBannerViewProps> = (props) => {
214165
css={{ marginRight: -16 }}
215166
>
216167
{unhealthy ? (
217-
<Link component={RouterLink} to="/health" css={statusBadgeStyle}>
168+
<Link
169+
component={RouterLink}
170+
to="/health"
171+
css={[styles.statusBadge, styles.unhealthy]}
172+
>
218173
<ErrorIcon />
219174
</Link>
220175
) : (
221-
<div css={statusBadgeStyle}>
176+
<div css={styles.statusBadge}>
222177
<RocketIcon />
223178
</div>
224179
)}
@@ -380,19 +335,15 @@ export const DeploymentBannerView: FC<DeploymentBannerViewProps> = (props) => {
380335
);
381336
};
382337

383-
const ValueSeparator: FC = () => {
384-
const theme = useTheme();
385-
const separatorStyles = css`
386-
color: ${theme.palette.text.disabled};
387-
`;
388-
389-
return <div css={separatorStyles}>/</div>;
390-
};
391-
392-
const WorkspaceBuildValue: FC<{
338+
interface WorkspaceBuildValueProps {
393339
status: WorkspaceStatus;
394340
count?: number;
395-
}> = ({ status, count }) => {
341+
}
342+
343+
const WorkspaceBuildValue: FC<WorkspaceBuildValueProps> = ({
344+
status,
345+
count,
346+
}) => {
396347
const displayStatus = getDisplayWorkspaceStatus(status);
397348
let statusText = displayStatus.text;
398349
let icon = displayStatus.icon;
@@ -416,6 +367,10 @@ const WorkspaceBuildValue: FC<{
416367
);
417368
};
418369

370+
const ValueSeparator: FC = () => {
371+
return <div css={styles.separator}>/</div>;
372+
};
373+
419374
const HealthIssue: FC<PropsWithChildren> = ({ children }) => {
420375
return (
421376
<Stack direction="row" spacing={1} alignItems="center">
@@ -424,3 +379,62 @@ const HealthIssue: FC<PropsWithChildren> = ({ children }) => {
424379
</Stack>
425380
);
426381
};
382+
383+
const classNames = {
384+
summaryTooltip: (css, theme) => css`
385+
${theme.typography.body2 as CSSObject}
386+
387+
margin: 0 0 4px 12px;
388+
width: 400px;
389+
padding: 16px;
390+
color: ${theme.palette.text.primary};
391+
background-color: ${theme.palette.background.paper};
392+
border: 1px solid ${theme.palette.divider};
393+
pointer-events: none;
394+
`,
395+
} satisfies Record<string, ClassName>;
396+
397+
const styles = {
398+
statusBadge: css`
399+
display: flex;
400+
align-items: center;
401+
justify-content: center;
402+
padding: 0 12px;
403+
height: 100%;
404+
color: #fff;
405+
406+
& svg {
407+
width: 16px;
408+
height: 16px;
409+
}
410+
`,
411+
unhealthy: css`
412+
background-color: ${colors.red[10]};
413+
`,
414+
group: css`
415+
display: flex;
416+
align-items: center;
417+
`,
418+
category: (theme) => ({
419+
marginRight: 16,
420+
color: theme.palette.text.primary,
421+
}),
422+
values: (theme) => ({
423+
display: "flex",
424+
gap: 8,
425+
color: theme.palette.text.secondary,
426+
}),
427+
value: css`
428+
display: flex;
429+
align-items: center;
430+
gap: 4px;
431+
432+
& svg {
433+
width: 12px;
434+
height: 12px;
435+
}
436+
`,
437+
separator: (theme) => ({
438+
color: theme.palette.text.disabled,
439+
}),
440+
} satisfies Record<string, Interpolation<Theme>>;

site/src/components/ErrorBoundary/RuntimeErrorState.tsx

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ import Link from "@mui/material/Link";
33
import RefreshOutlined from "@mui/icons-material/RefreshOutlined";
44
import { type FC, useEffect, useState } from "react";
55
import { Helmet } from "react-helmet-async";
6-
import { css } from "@emotion/css";
7-
import { type Interpolation, type Theme } from "@emotion/react";
6+
import { css, type Interpolation, type Theme } from "@emotion/react";
87
import type { BuildInfoResponse } from "api/typesGenerated";
98
import { CopyButton } from "components/CopyButton/CopyButton";
109
import { CoderIcon } from "components/Icons/CoderIcon";
@@ -97,20 +96,7 @@ export const RuntimeErrorState: FC<RuntimeErrorStateProps> = ({ error }) => {
9796
<div css={styles.stackHeader}>
9897
Stacktrace
9998
<CopyButton
100-
buttonClassName={css`
101-
background-color: transparent;
102-
border: 0;
103-
border-radius: 999px;
104-
min-height: 32px;
105-
min-width: 32px;
106-
height: 32px;
107-
width: 32px;
108-
109-
& svg {
110-
width: 16px;
111-
height: 16px;
112-
}
113-
`}
99+
buttonStyles={styles.copyButton}
114100
text={error.stack}
115101
tooltipTitle="Copy stacktrace"
116102
/>
@@ -209,4 +195,19 @@ const styles = {
209195
fontSize: 12,
210196
color: theme.palette.text.secondary,
211197
}),
198+
199+
copyButton: css`
200+
background-color: transparent;
201+
border: 0;
202+
border-radius: 999px;
203+
min-height: 32px;
204+
min-width: 32px;
205+
height: 32px;
206+
width: 32px;
207+
208+
& svg {
209+
width: 16px;
210+
height: 16px;
211+
}
212+
`,
212213
} satisfies Record<string, Interpolation<Theme>>;

0 commit comments

Comments
 (0)