Skip to content

feat(site): refactor workspace header to be more slim #11327

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
84f1bc4
Extract a few components to topbar module
BrunoQuaresma Dec 14, 2023
4ed5550
Extract and refactor a few more topbar componetns
BrunoQuaresma Dec 14, 2023
ffacb9f
WIP: Refactor workspace header
BrunoQuaresma Dec 15, 2023
a9ac963
Merge branch 'main' of https://github.com/coder/coder into bq/impleme…
BrunoQuaresma Dec 19, 2023
68c13ae
Improve outdated spacing
BrunoQuaresma Dec 19, 2023
ba88521
Merge branch 'main' of https://github.com/coder/coder into bq/impleme…
BrunoQuaresma Dec 20, 2023
3796085
Add schedule controls
BrunoQuaresma Dec 20, 2023
e0dd30d
Use topbar buttons
BrunoQuaresma Dec 20, 2023
c56d2f5
Add dormant to topbar
BrunoQuaresma Dec 20, 2023
90c3fc9
Add quota and minor accessibility improvements
BrunoQuaresma Dec 21, 2023
fdda1ba
Make template navigable
BrunoQuaresma Dec 21, 2023
f37a88d
Make visual adjustments
BrunoQuaresma Dec 21, 2023
26d6c09
Refactor icon colors
BrunoQuaresma Dec 22, 2023
5fa1f8f
Merge branch 'main' of https://github.com/coder/coder into bq/impleme…
BrunoQuaresma Dec 22, 2023
651b800
Add storybook
BrunoQuaresma Dec 22, 2023
d5510b2
Refactor storybook names
BrunoQuaresma Dec 22, 2023
d48c501
Merge branch 'main' of https://github.com/coder/coder into bq/impleme…
BrunoQuaresma Jan 2, 2024
19832ee
fix pill usage
BrunoQuaresma Jan 2, 2024
b8e80d0
add data-testid to workspace badge
BrunoQuaresma Jan 2, 2024
30f2a8c
Fix workspace status helper
BrunoQuaresma Jan 2, 2024
446bb76
remove span depedency from build-status
BrunoQuaresma Jan 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
"contravariance",
"cronstrue",
"databasefake",
"dbmem",
"dbgen",
"dbmem",
"dbtype",
"DERP",
"derphttp",
Expand Down Expand Up @@ -118,13 +118,13 @@
"stretchr",
"STTY",
"stuntest",
"tanstack",
"tailbroker",
"tailcfg",
"tailexchange",
"tailnet",
"tailnettest",
"Tailscale",
"tanstack",
"tbody",
"TCGETS",
"tcpip",
Expand All @@ -141,6 +141,7 @@
"tios",
"tmpdir",
"tokenconfig",
"Topbar",
"tparallel",
"trialer",
"trimprefix",
Expand Down
41 changes: 23 additions & 18 deletions site/.storybook/preview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export const decorators = [
(Story, context) => {
const selectedTheme = DecoratorHelpers.pluckThemeFromContext(context);
const { themeOverride } = DecoratorHelpers.useThemeParameters();

const selected = themeOverride || selectedTheme || "dark";

return (
Expand All @@ -39,23 +38,7 @@ export const decorators = [
</HelmetProvider>
);
},
(Story) => {
return (
<QueryClientProvider
client={
new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
},
},
})
}
>
<Story />
</QueryClientProvider>
);
},
withQuery,
];

export const parameters = {
Expand Down Expand Up @@ -89,3 +72,25 @@ export const parameters = {
},
},
};

function withQuery(Story, { parameters }) {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
},
},
});

if (parameters.queries) {
parameters.queries.forEach((query) => {
queryClient.setQueryData(query.key, query.data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what are we doing here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are setting the default values, passed via story parameters, for the react-query queries so the stories don't need to fetch the data. It is used to make the story independent of a BE or API.

});
}

return (
<QueryClientProvider client={queryClient}>
<Story />
</QueryClientProvider>
);
}
45 changes: 15 additions & 30 deletions site/e2e/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,9 @@ export const createWorkspace = async (

await expect(page).toHaveURL("/@admin/" + name);

await page.waitForSelector(
"span[data-testid='build-status'] >> text=Running",
{
state: "visible",
},
);
await page.waitForSelector("*[data-testid='build-status'] >> text=Running", {
state: "visible",
});
return name;
};

Expand Down Expand Up @@ -197,12 +194,9 @@ export const stopWorkspace = async (page: Page, workspaceName: string) => {

await page.getByTestId("workspace-stop-button").click();

await page.waitForSelector(
"span[data-testid='build-status'] >> text=Stopped",
{
state: "visible",
},
);
await page.waitForSelector("*[data-testid='build-status'] >> text=Stopped", {
state: "visible",
});
};

export const buildWorkspaceWithParameters = async (
Expand All @@ -225,12 +219,9 @@ export const buildWorkspaceWithParameters = async (
await page.getByTestId("confirm-button").click();
}

await page.waitForSelector(
"span[data-testid='build-status'] >> text=Running",
{
state: "visible",
},
);
await page.waitForSelector("*[data-testid='build-status'] >> text=Running", {
state: "visible",
});
};

// startAgent runs the coder agent with the provided token.
Expand Down Expand Up @@ -772,12 +763,9 @@ export const updateWorkspace = async (
await fillParameters(page, richParameters, buildParameters);
await page.getByTestId("form-submit").click();

await page.waitForSelector(
"span[data-testid='build-status'] >> text=Running",
{
state: "visible",
},
);
await page.waitForSelector("*[data-testid='build-status'] >> text=Running", {
state: "visible",
});
};

export const updateWorkspaceParameters = async (
Expand All @@ -796,10 +784,7 @@ export const updateWorkspaceParameters = async (
await fillParameters(page, richParameters, buildParameters);
await page.getByTestId("form-submit").click();

await page.waitForSelector(
"span[data-testid='build-status'] >> text=Running",
{
state: "visible",
},
);
await page.waitForSelector("*[data-testid='build-status'] >> text=Running", {
state: "visible",
});
};
11 changes: 11 additions & 0 deletions site/src/@types/storybook.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as _storybook_types from "@storybook/react";
import { Experiments, FeatureName } from "api/typesGenerated";
import { QueryKey } from "react-query";

declare module "@storybook/react" {
interface Parameters {
features?: FeatureName[];
experiments?: Experiments;
queries?: { key: QueryKey; data: unknown }[];
}
}
2 changes: 1 addition & 1 deletion site/src/api/queries/workspaceQuota.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as API from "api/api";

const getWorkspaceQuotaQueryKey = (username: string) => [
export const getWorkspaceQuotaQueryKey = (username: string) => [
username,
"workspaceQuota",
];
Expand Down
127 changes: 127 additions & 0 deletions site/src/components/FullPageLayout/Topbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { css } from "@emotion/css";
import Button, { ButtonProps } from "@mui/material/Button";
import IconButton, { IconButtonProps } from "@mui/material/IconButton";
import { useTheme } from "@mui/material/styles";
import { Avatar, AvatarProps } from "components/Avatar/Avatar";
import {
ForwardedRef,
HTMLAttributes,
PropsWithChildren,
ReactElement,
cloneElement,
forwardRef,
} from "react";

export const Topbar = (props: HTMLAttributes<HTMLDivElement>) => {
const theme = useTheme();

return (
<header
{...props}
css={{
minHeight: 48,
borderBottom: `1px solid ${theme.palette.divider}`,
display: "flex",
alignItems: "center",
fontSize: 13,
lineHeight: "1.2",
}}
/>
);
};

export const TopbarIconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
(props, ref) => {
return (
<IconButton
ref={ref}
{...props}
size="small"
css={{
padding: 0,
borderRadius: 0,
height: 48,
width: 48,

"& svg": {
fontSize: 20,
},
}}
/>
);
},
) as typeof IconButton;

export const TopbarButton = forwardRef<HTMLButtonElement, ButtonProps>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:) nice

(props: ButtonProps, ref) => {
return (
<Button
ref={ref}
color="neutral"
css={{
height: 28,
fontSize: 13,
borderRadius: 4,
padding: "0 12px",
}}
{...props}
/>
);
},
);

export const TopbarData = (props: HTMLAttributes<HTMLDivElement>) => {
return (
<div
{...props}
css={{
display: "flex",
gap: 8,
alignItems: "center",
justifyContent: "center",
}}
/>
);
};

export const TopbarDivider = (props: HTMLAttributes<HTMLSpanElement>) => {
const theme = useTheme();
return (
<span {...props} css={{ color: theme.palette.divider }}>
/
</span>
);
};

export const TopbarAvatar = (props: AvatarProps) => {
return (
<Avatar
{...props}
variant="square"
fitImage
css={{ width: 16, height: 16 }}
/>
);
};

type TopbarIconProps = PropsWithChildren<HTMLAttributes<HTMLOrSVGElement>>;

export const TopbarIcon = forwardRef<HTMLOrSVGElement, TopbarIconProps>(
(props: TopbarIconProps, ref) => {
const { children, ...restProps } = props;
const theme = useTheme();

return cloneElement(
children as ReactElement<
HTMLAttributes<HTMLOrSVGElement> & {
ref: ForwardedRef<HTMLOrSVGElement>;
}
>,
{
...restProps,
ref,
className: css({ fontSize: 16, color: theme.palette.text.disabled }),
},
);
},
);
61 changes: 0 additions & 61 deletions site/src/components/WorkspaceDeletion/DormantDeletionStat.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type FC } from "react";
import type { Workspace } from "api/typesGenerated";
import { displayDormantDeletion } from "./utils";
import { displayDormantDeletion } from "utils/dormant";
import { useDashboard } from "components/Dashboard/DashboardProvider";

interface DormantDeletionTextProps {
Expand Down
1 change: 0 additions & 1 deletion site/src/components/WorkspaceDeletion/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from "./DormantDeletionStat";
export * from "./DormantDeletionText";
export * from "./DormantWorkspaceBanner";
Loading