Skip to content

Commit a8372e1

Browse files
committed
Add colors to the bars
1 parent 2ffc75a commit a8372e1

File tree

3 files changed

+60
-49
lines changed

3 files changed

+60
-49
lines changed

site/src/modules/workspaces/WorkspaceTiming/Chart/Bar.tsx

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
import type { Interpolation, Theme } from "@emotion/react";
22
import { forwardRef, type HTMLProps, type ReactNode } from "react";
33

4-
type BarColor = "default" | "green";
4+
export type BarColor = {
5+
border: string;
6+
fill: string;
7+
};
58

6-
type BarProps = Omit<HTMLProps<HTMLDivElement>, "size"> & {
9+
type BarProps = Omit<HTMLProps<HTMLDivElement>, "size" | "color"> & {
710
width: number;
811
children?: ReactNode;
12+
/**
13+
* Color scheme for the bar. If not passed the default gray color will be
14+
* used.
15+
*/
916
color?: BarColor;
1017
/**
1118
* Label to be displayed adjacent to the bar component.
@@ -18,10 +25,7 @@ type BarProps = Omit<HTMLProps<HTMLDivElement>, "size"> & {
1825
};
1926

2027
export const Bar = forwardRef<HTMLDivElement, BarProps>(
21-
(
22-
{ color = "default", width, afterLabel, children, x, ...htmlProps },
23-
ref,
24-
) => {
28+
({ color, width, afterLabel, children, x, ...htmlProps }, ref) => {
2529
return (
2630
<div
2731
ref={ref}
@@ -30,7 +34,10 @@ export const Bar = forwardRef<HTMLDivElement, BarProps>(
3034
>
3135
<button
3236
type="button"
33-
css={[styles.bar, colorStyles[color], { width }]}
37+
css={[
38+
styles.bar,
39+
{ width, backgroundColor: color?.fill, borderColor: color?.border },
40+
]}
3441
disabled={htmlProps.disabled}
3542
aria-labelledby={htmlProps["aria-labelledby"]}
3643
>
@@ -50,8 +57,10 @@ const styles = {
5057
width: "fit-content",
5158
gap: 8,
5259
},
53-
bar: {
54-
border: "1px solid transparent",
60+
bar: (theme) => ({
61+
border: "1px solid",
62+
borderColor: theme.palette.divider,
63+
backgroundColor: theme.palette.background.default,
5564
borderRadius: 8,
5665
height: 32,
5766
display: "flex",
@@ -67,17 +76,5 @@ const styles = {
6776
borderColor: "#38BDF8",
6877
},
6978
},
70-
},
71-
} satisfies Record<string, Interpolation<Theme>>;
72-
73-
const colorStyles = {
74-
default: (theme) => ({
75-
backgroundColor: theme.palette.background.default,
76-
borderColor: theme.palette.divider,
77-
}),
78-
green: (theme) => ({
79-
backgroundColor: theme.roles.success.background,
80-
borderColor: theme.roles.success.outline,
81-
color: theme.roles.success.text,
8279
}),
83-
} satisfies Record<BarColor, Interpolation<Theme>>;
80+
} satisfies Record<string, Interpolation<Theme>>;

site/src/modules/workspaces/WorkspaceTiming/Chart/Chart.tsx

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
contentSidePadding,
1818
XAxisHeight,
1919
} from "./constants";
20-
import { Bar } from "./Bar";
20+
import { Bar, type BarColor } from "./Bar";
2121

2222
// Data can be divided into sections. For example, display the provisioning
2323
// timings in one section and the scripting timings in another.
@@ -38,6 +38,7 @@ export type Timing = Duration & {
3838
* blocks.
3939
*/
4040
childrenCount: number;
41+
color?: BarColor;
4142
};
4243

4344
// Extracts the 'startedAt' and 'endedAt' date fields from the main Timing type.
@@ -84,21 +85,23 @@ export const Chart: FC<ChartProps> = ({ data, onBarClick }) => {
8485
return (
8586
<div css={styles.chart}>
8687
<YAxis>
87-
{data.map((section) => (
88-
<YAxisSection key={section.name}>
89-
<YAxisCaption>{section.name}</YAxisCaption>
90-
<YAxisLabels>
91-
{section.timings.map((t) => (
92-
<YAxisLabel
93-
key={t.label}
94-
id={`${encodeURIComponent(t.label)}-label`}
95-
>
96-
{t.label}
97-
</YAxisLabel>
98-
))}
99-
</YAxisLabels>
100-
</YAxisSection>
101-
))}
88+
{data.map((section) => {
89+
return (
90+
<YAxisSection key={section.name}>
91+
<YAxisCaption>{section.name}</YAxisCaption>
92+
<YAxisLabels>
93+
{section.timings.map((t) => (
94+
<YAxisLabel
95+
key={t.label}
96+
id={`${encodeURIComponent(t.label)}-label`}
97+
>
98+
{t.label}
99+
</YAxisLabel>
100+
))}
101+
</YAxisLabels>
102+
</YAxisSection>
103+
);
104+
})}
102105
</YAxis>
103106

104107
<div css={styles.main}>
@@ -113,6 +116,7 @@ export const Chart: FC<ChartProps> = ({ data, onBarClick }) => {
113116
const size = calcSize(durationTime(t));
114117
return (
115118
<Bar
119+
color={t.color}
116120
key={t.label}
117121
x={calcSize(offset)}
118122
width={size}

site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,23 @@ import { YAxisSidePadding, YAxisWidth } from "./Chart/YAxis";
77
import { SearchField } from "components/SearchField/SearchField";
88

99
// TODO: Export provisioning stages from the BE to the generated types.
10-
// We control the stages to be displayed in the chart so we can set the correct
11-
// colors and labels.
12-
const provisioningStages = [
13-
{ name: "init" },
14-
{ name: "plan" },
15-
{ name: "graph" },
16-
{ name: "apply" },
17-
];
10+
const provisioningStages = ["init", "plan", "graph", "apply"];
11+
12+
// TODO: Export actions from the BE to the generated types.
13+
const colorsByActions: Record<string, Timing["color"]> = {
14+
create: {
15+
fill: "#022C22",
16+
border: "#BBF7D0",
17+
},
18+
delete: {
19+
fill: "#422006",
20+
border: "#FDBA74",
21+
},
22+
read: {
23+
fill: "#082F49",
24+
border: "#38BDF8",
25+
},
26+
};
1827

1928
// The advanced view is an expanded view of the stage, allowing the user to see
2029
// which resources within a stage are taking the most time. It supports resource
@@ -97,11 +106,11 @@ export const selectChartData = (
97106
case "basic": {
98107
const groupedTimingsByStage = provisioningStages.map((stage) => {
99108
const durations = timings
100-
.filter((t) => t.stage === stage.name)
109+
.filter((t) => t.stage === stage)
101110
.map(extractDuration);
102111
const stageDuration = duration(durations);
103112
const stageTiming: Timing = {
104-
label: stage.name,
113+
label: stage,
105114
childrenCount: durations.length,
106115
...stageDuration,
107116
};
@@ -124,7 +133,8 @@ export const selectChartData = (
124133
)
125134
.map((t) => {
126135
return {
127-
label: t.resource,
136+
label: `${t.resource}.${t.action}`,
137+
color: colorsByActions[t.action],
128138
childrenCount: 0, // Resource timings don't have inner timings
129139
...extractDuration(t),
130140
} as Timing;

0 commit comments

Comments
 (0)