From 0092d9332cd021597cdfa8adcc9ad1c665acbd33 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Mon, 18 Dec 2023 16:46:47 +0000 Subject: [PATCH 01/19] add light theme --- site/.storybook/main.js | 8 +- site/.storybook/preview.jsx | 53 +- site/package.json | 1 + site/pnpm-lock.yaml | 9 + .../ActiveUserChart/ActiveUserChart.tsx | 10 +- site/src/components/Badges/Badges.stories.tsx | 23 + site/src/components/Badges/Badges.tsx | 28 +- .../CodeExample/CodeExample.stories.tsx | 12 +- .../components/CodeExample/CodeExample.tsx | 68 +-- .../components/ExternalIcon/ExternalIcon.tsx | 37 ++ site/src/components/Pill/Pill.tsx | 9 +- .../components/Resources/ResourceAvatar.tsx | 28 +- .../AuditLogDescription.tsx | 10 +- site/src/pages/AuditPage/AuditPaywall.tsx | 8 +- .../ExternalAuth.stories.tsx | 26 +- .../CreateWorkspacePage/ExternalAuth.tsx | 122 ++-- site/src/pages/GroupsPage/GroupsPageView.tsx | 3 +- .../StarterTemplatePageView.tsx | 17 +- .../TemplateInsightsPage.tsx | 4 +- .../TemplatePermissionsPage.tsx | 2 +- .../AppearancePage/AppearanceForm.stories.tsx | 1 - .../AppearancePage/AppearanceForm.tsx | 26 +- .../ExternalAuthPageView.stories.tsx | 12 +- .../ExternalAuthPage/ExternalAuthPageView.tsx | 25 +- .../SSHKeysPage/SSHKeysPageView.stories.tsx | 3 +- site/src/pages/WorkspaceBuildPage/Sidebar.tsx | 2 +- site/src/testHelpers/entities.ts | 16 +- site/src/theme/dark/experimental.ts | 6 + site/src/theme/dark/mui.ts | 16 +- site/src/theme/darkBlue/experimental.ts | 6 + site/src/theme/darkBlue/mui.ts | 1 + site/src/theme/experimental.ts | 1 + site/src/theme/index.ts | 3 +- site/src/theme/light/colors.ts | 62 ++ site/src/theme/light/experimental.ts | 136 +++++ site/src/theme/light/index.ts | 9 + site/src/theme/light/mui.ts | 576 ++++++++++++++++++ site/src/utils/latency.ts | 6 +- 38 files changed, 1146 insertions(+), 239 deletions(-) create mode 100644 site/src/components/ExternalIcon/ExternalIcon.tsx create mode 100644 site/src/theme/light/colors.ts create mode 100644 site/src/theme/light/experimental.ts create mode 100644 site/src/theme/light/index.ts create mode 100644 site/src/theme/light/mui.ts diff --git a/site/.storybook/main.js b/site/.storybook/main.js index f955a9a2d9011..e5ede7b46b2f8 100644 --- a/site/.storybook/main.js +++ b/site/.storybook/main.js @@ -3,10 +3,16 @@ import turbosnap from "vite-plugin-turbosnap"; module.exports = { stories: ["../src/**/*.stories.tsx"], addons: [ + { + name: "@storybook/addon-essentials", + options: { + backgrounds: false, + }, + }, "@storybook/addon-links", - "@storybook/addon-essentials", "@storybook/addon-mdx-gfm", "@storybook/addon-actions", + "@storybook/addon-themes", ], staticDirs: ["../static"], framework: { diff --git a/site/.storybook/preview.jsx b/site/.storybook/preview.jsx index 2a687e27cdb01..65ee5242b6c1d 100644 --- a/site/.storybook/preview.jsx +++ b/site/.storybook/preview.jsx @@ -4,24 +4,33 @@ import { ThemeProvider as MuiThemeProvider, } from "@mui/material/styles"; import { ThemeProvider as EmotionThemeProvider } from "@emotion/react"; +import { DecoratorHelpers } from "@storybook/addon-themes"; import { withRouter } from "storybook-addon-react-router-v6"; +import { QueryClient, QueryClientProvider } from "react-query"; import { HelmetProvider } from "react-helmet-async"; -import theme from "theme"; -import colors from "theme/tailwind"; +import themes from "theme"; import "theme/globalFonts"; -import { QueryClient, QueryClientProvider } from "react-query"; + +DecoratorHelpers.initializeThemeState(Object.keys(themes), "dark"); export const decorators = [ - (Story) => ( - - - - - - - - - ), + (Story, context) => { + const selectedTheme = DecoratorHelpers.pluckThemeFromContext(context); + const { themeOverride } = DecoratorHelpers.useThemeParameters(); + + const selected = themeOverride || selectedTheme || "dark"; + + return ( + + + + + + + + + ); + }, withRouter, (Story) => { return ( @@ -50,18 +59,12 @@ export const decorators = [ ]; export const parameters = { - backgrounds: { - default: "dark", - values: [ - { - name: "dark", - value: colors.gray[950], - }, - { - name: "light", - value: colors.gray[50], - }, - ], + options: { + storySort: { + method: "alphabetical", + order: ["design", "pages", "components"], + locales: "en-US", + }, }, actions: { argTypesRegex: "^(on|handler)[A-Z].*", diff --git a/site/package.json b/site/package.json index 95614f5cc0606..b952d7ae6d3c1 100644 --- a/site/package.json +++ b/site/package.json @@ -104,6 +104,7 @@ "@storybook/addon-essentials": "7.5.2", "@storybook/addon-links": "7.5.2", "@storybook/addon-mdx-gfm": "7.5.2", + "@storybook/addon-themes": "^7.6.4", "@storybook/react": "7.5.2", "@storybook/react-vite": "7.5.2", "@swc/core": "1.3.38", diff --git a/site/pnpm-lock.yaml b/site/pnpm-lock.yaml index 23c835d6f0ea5..c04f20a40e515 100644 --- a/site/pnpm-lock.yaml +++ b/site/pnpm-lock.yaml @@ -233,6 +233,9 @@ devDependencies: '@storybook/addon-mdx-gfm': specifier: 7.5.2 version: 7.5.2 + '@storybook/addon-themes': + specifier: ^7.6.4 + version: 7.6.5 '@storybook/react': specifier: 7.5.2 version: 7.5.2(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2) @@ -4087,6 +4090,12 @@ packages: - '@types/react-dom' dev: true + /@storybook/addon-themes@7.6.5: + resolution: {integrity: sha512-TzGCxwdYAAlgeYuTYhMnL5KLutLVHrAXjVtWsYCYV+SVx+JklqCTk4zNUod64Z+sIYRMYd+YVC1KsWF2LHirow==} + dependencies: + ts-dedent: 2.2.0 + dev: true + /@storybook/addon-toolbars@7.5.2(@types/react-dom@18.2.4)(@types/react@18.2.6)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-BXzb5NOpILFOM7EOBxcF2Qj/q6BicWZ1AvAddORWGmqSa/MxMIa4X52oKXFUTHKBkrTO1X0XqHmoF88qm3TUFg==} peerDependencies: diff --git a/site/src/components/ActiveUserChart/ActiveUserChart.tsx b/site/src/components/ActiveUserChart/ActiveUserChart.tsx index 8541297819b99..b6f27d4be2906 100644 --- a/site/src/components/ActiveUserChart/ActiveUserChart.tsx +++ b/site/src/components/ActiveUserChart/ActiveUserChart.tsx @@ -94,6 +94,7 @@ export const ActiveUserChart: FC = ({ }, scales: { y: { + grid: { color: theme.palette.divider }, suggestedMin: 0, ticks: { precision: 0, @@ -101,6 +102,7 @@ export const ActiveUserChart: FC = ({ }, x: { + grid: { color: theme.palette.divider }, ticks: { stepSize: data.length > 10 ? 2 : undefined, }, @@ -122,11 +124,9 @@ export const ActiveUserChart: FC = ({ { label: `${interval === "day" ? "Daily" : "Weekly"} Active Users`, data: chartData, - pointBackgroundColor: theme.palette.info.light, - pointBorderColor: theme.palette.info.light, - borderColor: theme.palette.info.light, - backgroundColor: theme.palette.info.dark, - fill: "origin", + pointBackgroundColor: theme.experimental.roles.active.outline, + pointBorderColor: theme.experimental.roles.active.outline, + borderColor: theme.experimental.roles.active.outline, }, ], }} diff --git a/site/src/components/Badges/Badges.stories.tsx b/site/src/components/Badges/Badges.stories.tsx index e699b6317f0e7..ed7e88ea1b6e7 100644 --- a/site/src/components/Badges/Badges.stories.tsx +++ b/site/src/components/Badges/Badges.stories.tsx @@ -2,9 +2,14 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Badges, AlphaBadge, + DisabledBadge, EnabledBadge, EntitledBadge, EnterpriseBadge, + HealthyBadge, + NotHealthyBadge, + NotRegisteredBadge, + NotReachableBadge, } from "./Badges"; const meta: Meta = { @@ -26,6 +31,24 @@ export const Entitled: Story = { children: , }, }; +export const ProxyStatus: Story = { + args: { + children: ( + <> + + + + + + + ), + }, +}; +export const Disabled: Story = { + args: { + children: , + }, +}; export const Enterprise: Story = { args: { children: , diff --git a/site/src/components/Badges/Badges.tsx b/site/src/components/Badges/Badges.tsx index e1ca731f749bf..b8e6b9ae330cd 100644 --- a/site/src/components/Badges/Badges.tsx +++ b/site/src/components/Badges/Badges.tsx @@ -22,14 +22,17 @@ const styles = { enabledBadge: (theme) => ({ border: `1px solid ${theme.experimental.roles.success.outline}`, backgroundColor: theme.experimental.roles.success.background, + color: theme.experimental.roles.success.text, }), errorBadge: (theme) => ({ border: `1px solid ${theme.experimental.roles.error.outline}`, backgroundColor: theme.experimental.roles.error.background, + color: theme.experimental.roles.error.text, }), warnBadge: (theme) => ({ border: `1px solid ${theme.experimental.roles.warning.outline}`, backgroundColor: theme.experimental.roles.warning.background, + color: theme.experimental.roles.warning.text, }), } satisfies Record>; @@ -42,10 +45,9 @@ export const EntitledBadge: FC = () => { }; interface HealthyBadge { - derpOnly: boolean; + derpOnly?: boolean; } -export const HealthyBadge: FC = (props) => { - const { derpOnly } = props; +export const HealthyBadge: FC = ({ derpOnly }) => { return ( {derpOnly ? "Healthy (DERP only)" : "Healthy"} @@ -79,8 +81,9 @@ export const DisabledBadge: FC = () => { css={[ styles.badge, (theme) => ({ - border: `1px solid ${theme.palette.divider}`, - backgroundColor: theme.palette.background.paper, + border: `1px solid ${theme.experimental.l1.outline}`, + backgroundColor: theme.experimental.l1.background, + color: theme.experimental.l1.text, }), ]} > @@ -95,8 +98,9 @@ export const EnterpriseBadge: FC = () => { css={[ styles.badge, (theme) => ({ - backgroundColor: theme.palette.info.dark, - border: `1px solid ${theme.palette.info.light}`, + backgroundColor: theme.experimental.roles.info.background, + border: `1px solid ${theme.experimental.roles.info.outline}`, + color: theme.experimental.roles.info.text, }), ]} > @@ -110,11 +114,11 @@ export const AlphaBadge: FC = () => { ({ + border: `1px solid ${theme.experimental.roles.preview.outline}`, + backgroundColor: theme.experimental.roles.preview.background, + color: theme.experimental.roles.preview.text, + }), ]} > Alpha diff --git a/site/src/components/CodeExample/CodeExample.stories.tsx b/site/src/components/CodeExample/CodeExample.stories.tsx index 35c3da065f467..1af88cd98dafd 100644 --- a/site/src/components/CodeExample/CodeExample.stories.tsx +++ b/site/src/components/CodeExample/CodeExample.stories.tsx @@ -1,22 +1,22 @@ import type { Meta, StoryObj } from "@storybook/react"; import { CodeExample } from "./CodeExample"; -const sampleCode = `echo "Hello, world"`; - const meta: Meta = { title: "components/CodeExample", component: CodeExample, - argTypes: { - code: { control: "string", defaultValue: sampleCode }, + args: { + code: `echo "hello, friend!"`, }, }; export default meta; type Story = StoryObj; -export const Example: Story = { +export const Example: Story = {}; + +export const Secret: Story = { args: { - code: sampleCode, + secret: true, }, }; diff --git a/site/src/components/CodeExample/CodeExample.tsx b/site/src/components/CodeExample/CodeExample.tsx index 7f6dfc62cefbf..9014f04a58ce5 100644 --- a/site/src/components/CodeExample/CodeExample.tsx +++ b/site/src/components/CodeExample/CodeExample.tsx @@ -1,51 +1,51 @@ import { type FC } from "react"; -import { useTheme } from "@emotion/react"; +import { type Interpolation, type Theme } from "@emotion/react"; import { MONOSPACE_FONT_FAMILY } from "theme/constants"; import { CopyButton } from "../CopyButton/CopyButton"; export interface CodeExampleProps { code: string; - password?: boolean; + secret?: boolean; className?: string; } /** * Component to show single-line code examples, with a copy button */ -export const CodeExample: FC = (props) => { - const { code, password, className } = props; - const theme = useTheme(); - +export const CodeExample: FC = ({ + code, + secret, + className, +}) => { return ( -
- - {code} - +
+ {code}
); }; + +const styles = { + container: (theme) => ({ + display: "flex", + flexDirection: "row", + alignItems: "center", + color: theme.experimental.l1.text, + fontFamily: MONOSPACE_FONT_FAMILY, + fontSize: 14, + borderRadius: 8, + padding: 8, + lineHeight: "150%", + border: `1px solid ${theme.experimental.l1.outline}`, + }), + + code: { + padding: "0 8px", + flexGrow: 1, + wordBreak: "break-all", + }, + + secret: { + "-webkit-text-security": "disc", // also supported by firefox + }, +} satisfies Record>; diff --git a/site/src/components/ExternalIcon/ExternalIcon.tsx b/site/src/components/ExternalIcon/ExternalIcon.tsx new file mode 100644 index 0000000000000..527847511343e --- /dev/null +++ b/site/src/components/ExternalIcon/ExternalIcon.tsx @@ -0,0 +1,37 @@ +import { type Interpolation, type Theme } from "@emotion/react"; +import { type FC, type ImgHTMLAttributes } from "react"; +import colors from "theme/tailwind"; + +interface ExternalIconProps extends ImgHTMLAttributes { + size?: number; +} + +export const ExternalIcon: FC = ({ + size = 36, + ...attrs +}) => { + return ( +
+ +
+ ); +}; + +const styles = { + container: { + borderRadius: 9999, + overflow: "clip", + }, + icon: { + backgroundColor: "#000", + objectFit: "contain", + }, +} satisfies Record>; diff --git a/site/src/components/Pill/Pill.tsx b/site/src/components/Pill/Pill.tsx index 132955363c0af..edfc88c0a5490 100644 --- a/site/src/components/Pill/Pill.tsx +++ b/site/src/components/Pill/Pill.tsx @@ -1,5 +1,5 @@ import { type FC, type ReactNode, useMemo, forwardRef } from "react"; -import { css, type Interpolation, type Theme } from "@emotion/react"; +import { css, useTheme, type Interpolation, type Theme } from "@emotion/react"; import type { ThemeRole } from "theme/experimental"; export type PillType = ThemeRole | keyof typeof themeOverrides; @@ -14,8 +14,8 @@ export interface PillProps { const themeOverrides = { neutral: (theme) => ({ - backgroundColor: theme.colors.gray[13], - borderColor: theme.colors.gray[6], + backgroundColor: theme.experimental.l1.background, + borderColor: theme.experimental.l1.outline, }), } satisfies Record>; @@ -30,6 +30,7 @@ const themeStyles = (type: ThemeRole) => (theme: Theme) => { export const Pill: FC = forwardRef( (props, ref) => { const { icon, text = null, type = "neutral", ...attrs } = props; + const theme = useTheme(); const typeStyles = useMemo(() => { if (type in themeOverrides) { @@ -50,7 +51,7 @@ export const Pill: FC = forwardRef( borderStyle: "solid", borderRadius: 99999, fontSize: 12, - color: "#FFF", + color: theme.experimental.l1.text, height: 24, paddingLeft: icon ? 6 : 12, paddingRight: 12, diff --git a/site/src/components/Resources/ResourceAvatar.tsx b/site/src/components/Resources/ResourceAvatar.tsx index b74a75b754c80..0ce16cb2f441f 100644 --- a/site/src/components/Resources/ResourceAvatar.tsx +++ b/site/src/components/Resources/ResourceAvatar.tsx @@ -1,15 +1,13 @@ -import { Avatar, AvatarIcon } from "components/Avatar/Avatar"; -import { FC } from "react"; -import { WorkspaceResource } from "api/typesGenerated"; +import { type FC } from "react"; +import type { WorkspaceResource } from "api/typesGenerated"; +import { ExternalIcon } from "components/ExternalIcon/ExternalIcon"; const FALLBACK_ICON = "/icon/widgets.svg"; // These resources (i.e. docker_image, kubernetes_deployment) map to Terraform // resource types. These are the most used ones and are based on user usage. // We may want to update from time-to-time. -const BUILT_IN_ICON_PATHS: { - [resourceType: WorkspaceResource["type"]]: string; -} = { +const BUILT_IN_ICON_PATHS: Record = { docker_volume: "/icon/database.svg", docker_container: "/icon/memory.svg", docker_image: "/icon/container.svg", @@ -19,28 +17,16 @@ const BUILT_IN_ICON_PATHS: { google_compute_instance: "/icon/memory.svg", aws_instance: "/icon/memory.svg", kubernetes_deployment: "/icon/memory.svg", - null_resource: FALLBACK_ICON, }; export const getIconPathResource = (resourceType: string): string => { - if (resourceType in BUILT_IN_ICON_PATHS) { - return BUILT_IN_ICON_PATHS[resourceType]; - } - - return FALLBACK_ICON; + return BUILT_IN_ICON_PATHS[resourceType] ?? FALLBACK_ICON; }; export type ResourceAvatarProps = { resource: WorkspaceResource }; export const ResourceAvatar: FC = ({ resource }) => { - const hasIcon = resource.icon && resource.icon !== ""; - const avatarSrc = hasIcon - ? resource.icon - : getIconPathResource(resource.type); + const avatarSrc = resource.icon || getIconPathResource(resource.type); - return ( - - - - ); + return ; }; diff --git a/site/src/pages/AuditPage/AuditLogRow/AuditLogDescription/AuditLogDescription.tsx b/site/src/pages/AuditPage/AuditLogRow/AuditLogDescription/AuditLogDescription.tsx index f583bd694aa2e..9e59cceb4e3df 100644 --- a/site/src/pages/AuditPage/AuditLogRow/AuditLogDescription/AuditLogDescription.tsx +++ b/site/src/pages/AuditPage/AuditLogRow/AuditLogDescription/AuditLogDescription.tsx @@ -1,12 +1,16 @@ -import { FC } from "react"; +import { type FC } from "react"; import { AuditLog } from "api/typesGenerated"; import { Link as RouterLink } from "react-router-dom"; import Link from "@mui/material/Link"; import { BuildAuditDescription } from "./BuildAuditDescription"; -export const AuditLogDescription: FC<{ auditLog: AuditLog }> = ({ +interface AuditLogDescriptionProps { + auditLog: AuditLog; +} + +export const AuditLogDescription: FC = ({ auditLog, -}): JSX.Element => { +}) => { let target = auditLog.resource_target.trim(); const user = auditLog.user?.username.trim(); diff --git a/site/src/pages/AuditPage/AuditPaywall.tsx b/site/src/pages/AuditPage/AuditPaywall.tsx index 9fab0c4899156..8de74dbdc251c 100644 --- a/site/src/pages/AuditPage/AuditPaywall.tsx +++ b/site/src/pages/AuditPage/AuditPaywall.tsx @@ -13,8 +13,12 @@ export const AuditPaywall: FC = () => { description="Audit Logs allows Auditors to monitor user operations in their deployment. To use this feature, you need an Enterprise license." cta={ - - diff --git a/site/src/pages/CreateWorkspacePage/ExternalAuth.stories.tsx b/site/src/pages/CreateWorkspacePage/ExternalAuth.stories.tsx index 87e7607282068..72e313968c688 100644 --- a/site/src/pages/CreateWorkspacePage/ExternalAuth.stories.tsx +++ b/site/src/pages/CreateWorkspacePage/ExternalAuth.stories.tsx @@ -9,7 +9,7 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const GithubNotAuthenticated: Story = { +export const Github: Story = { args: { displayIcon: "/icon/github.svg", displayName: "GitHub", @@ -17,6 +17,24 @@ export const GithubNotAuthenticated: Story = { }, }; +export const GithubTimeout: Story = { + args: { + displayIcon: "/icon/github.svg", + displayName: "GitHub", + authenticated: false, + externalAuthPollingState: "abandoned", + }, +}; + +export const GithubFailed: Story = { + args: { + displayIcon: "/icon/github.svg", + displayName: "GitHub", + authenticated: false, + error: "Github doesn't like you", + }, +}; + export const GithubAuthenticated: Story = { args: { displayIcon: "/icon/github.svg", @@ -25,7 +43,7 @@ export const GithubAuthenticated: Story = { }, }; -export const GitlabNotAuthenticated: Story = { +export const Gitlab: Story = { args: { displayIcon: "/icon/gitlab.svg", displayName: "GitLab", @@ -41,7 +59,7 @@ export const GitlabAuthenticated: Story = { }, }; -export const AzureDevOpsNotAuthenticated: Story = { +export const AzureDevOps: Story = { args: { displayIcon: "/icon/azure-devops.svg", displayName: "Azure DevOps", @@ -57,7 +75,7 @@ export const AzureDevOpsAuthenticated: Story = { }, }; -export const BitbucketNotAuthenticated: Story = { +export const Bitbucket: Story = { args: { displayIcon: "/icon/bitbucket.svg", displayName: "Bitbucket", diff --git a/site/src/pages/CreateWorkspacePage/ExternalAuth.tsx b/site/src/pages/CreateWorkspacePage/ExternalAuth.tsx index 691b6681afddb..b85d2bcb3145b 100644 --- a/site/src/pages/CreateWorkspacePage/ExternalAuth.tsx +++ b/site/src/pages/CreateWorkspacePage/ExternalAuth.tsx @@ -16,70 +16,82 @@ export interface ExternalAuthProps { startPollingExternalAuth: () => void; error?: string; message?: string; + fullWidth?: boolean; } -export const ExternalAuth: FC = (props) => { - const { - displayName, - displayIcon, - authenticated, - authenticateURL, - externalAuthPollingState, - startPollingExternalAuth, - error, - message, - } = props; - +export const ExternalAuth: FC = ({ + displayName, + displayIcon, + authenticated, + authenticateURL, + externalAuthPollingState, + startPollingExternalAuth, + error, + message, + fullWidth = true, +}) => { const messageContent = message ?? (authenticated ? `Authenticated with ${displayName}` : `Login with ${displayName}`); + return ( - - - - ) - } - disabled={authenticated} - css={{ height: 52 }} - color={error ? "error" : undefined} - fullWidth - onClick={(event) => { - event.preventDefault(); - // If the user is already authenticated, we don't want to redirect them - if (authenticated || authenticateURL === "") { - return; - } - window.open(authenticateURL, "_blank", "width=900,height=600"); - startPollingExternalAuth(); - }} + <> + + - {messageContent} - + + ) + } + disabled={authenticated} + css={{ height: 42 }} + fullWidth={fullWidth} + onClick={(event) => { + event.preventDefault(); + // If the user is already authenticated, we don't want to redirect them + if (authenticated || authenticateURL === "") { + return; + } + window.open(authenticateURL, "_blank", "width=900,height=600"); + startPollingExternalAuth(); + }} + > + {messageContent} + - {externalAuthPollingState === "abandoned" && ( - - )} - {error && {error}} - - + {externalAuthPollingState === "abandoned" && ( + + )} + + + {error && ( + ({ color: theme.experimental.roles.error.text })} + > + {error} + + )} + ); }; diff --git a/site/src/pages/GroupsPage/GroupsPageView.tsx b/site/src/pages/GroupsPage/GroupsPageView.tsx index 510200819eb15..faaafafb9df7d 100644 --- a/site/src/pages/GroupsPage/GroupsPageView.tsx +++ b/site/src/pages/GroupsPage/GroupsPageView.tsx @@ -59,6 +59,7 @@ export const GroupsPageView: FC = ({ rel="noreferrer" startIcon={} variant="contained" + color="primary" > Learn about Enterprise @@ -68,7 +69,7 @@ export const GroupsPageView: FC = ({ target="_blank" rel="noreferrer" > - Read the docs + Read the documentation } diff --git a/site/src/pages/StarterTemplatePage/StarterTemplatePageView.tsx b/site/src/pages/StarterTemplatePage/StarterTemplatePageView.tsx index 91a0c446146ed..4b204f5e5e003 100644 --- a/site/src/pages/StarterTemplatePage/StarterTemplatePageView.tsx +++ b/site/src/pages/StarterTemplatePage/StarterTemplatePageView.tsx @@ -15,6 +15,7 @@ import { Stack } from "components/Stack/Stack"; import { Link } from "react-router-dom"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import type { TemplateExample } from "api/typesGenerated"; +import { ExternalIcon } from "components/ExternalIcon/ExternalIcon"; export interface StarterTemplatePageViewProps { starterTemplate?: TemplateExample; @@ -65,21 +66,7 @@ export const StarterTemplatePageView: FC = ({ } > -
- -
+
{starterTemplate.name} diff --git a/site/src/pages/TemplatePage/TemplateInsightsPage/TemplateInsightsPage.tsx b/site/src/pages/TemplatePage/TemplateInsightsPage/TemplateInsightsPage.tsx index a2300cb06161d..1b8f80975c76b 100644 --- a/site/src/pages/TemplatePage/TemplateInsightsPage/TemplateInsightsPage.tsx +++ b/site/src/pages/TemplatePage/TemplateInsightsPage/TemplateInsightsPage.tsx @@ -18,10 +18,10 @@ import type { } from "api/typesGenerated"; import { useTheme } from "@emotion/react"; import { - PropsWithChildren, type FC, + type HTMLAttributes, + type PropsWithChildren, type ReactNode, - HTMLAttributes, useId, } from "react"; import chroma from "chroma-js"; diff --git a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx index 6cf11ec1faf62..5b4bee3deee2a 100644 --- a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx @@ -56,7 +56,7 @@ export const TemplatePermissionsPage: FC< - Read the docs + Read the documentation } diff --git a/site/src/pages/UserSettingsPage/AppearancePage/AppearanceForm.stories.tsx b/site/src/pages/UserSettingsPage/AppearancePage/AppearanceForm.stories.tsx index fdb401d2b6a63..67e1308b02939 100644 --- a/site/src/pages/UserSettingsPage/AppearancePage/AppearanceForm.stories.tsx +++ b/site/src/pages/UserSettingsPage/AppearancePage/AppearanceForm.stories.tsx @@ -18,7 +18,6 @@ type Story = StoryObj; export const Example: Story = { args: { - enableAuto: true, initialValues: { theme_preference: "" }, }, }; diff --git a/site/src/pages/UserSettingsPage/AppearancePage/AppearanceForm.tsx b/site/src/pages/UserSettingsPage/AppearancePage/AppearanceForm.tsx index b2c8e97b23201..982c2a0b7df90 100644 --- a/site/src/pages/UserSettingsPage/AppearancePage/AppearanceForm.tsx +++ b/site/src/pages/UserSettingsPage/AppearancePage/AppearanceForm.tsx @@ -11,10 +11,6 @@ export interface AppearanceFormProps { error?: unknown; initialValues: UpdateUserAppearanceSettingsRequest; onSubmit: (values: UpdateUserAppearanceSettingsRequest) => Promise; - - // temporary, so that storybook can test the right thing without showing - // a semi-broken auto theme to users. will be removed when light mode is done. - enableAuto?: boolean; } export const AppearanceForm: FC = ({ @@ -22,7 +18,6 @@ export const AppearanceForm: FC = ({ error, onSubmit, initialValues, - enableAuto, }) => { const currentTheme = initialValues.theme_preference || DEFAULT_THEME; @@ -39,14 +34,13 @@ export const AppearanceForm: FC = ({ {Boolean(error) && } - {enableAuto && ( - onChangeTheme("auto")} - /> - )} + onChangeTheme("auto")} + /> + = ({ theme={themes.darkBlue} onSelect={() => onChangeTheme("darkBlue")} /> + onChangeTheme("light")} + /> ); diff --git a/site/src/pages/UserSettingsPage/ExternalAuthPage/ExternalAuthPageView.stories.tsx b/site/src/pages/UserSettingsPage/ExternalAuthPage/ExternalAuthPageView.stories.tsx index b65a86774c144..abdd999f6abf0 100644 --- a/site/src/pages/UserSettingsPage/ExternalAuthPage/ExternalAuthPageView.stories.tsx +++ b/site/src/pages/UserSettingsPage/ExternalAuthPage/ExternalAuthPageView.stories.tsx @@ -26,6 +26,16 @@ type Story = StoryObj; export const NoProviders: Story = {}; +export const NoIcon: Story = { + args: { + ...meta.args, + auths: { + providers: [{ ...MockGithubExternalProvider, display_icon: "" }], + links: [MockGithubAuthLink], + }, + }, +}; + export const Authenticated: Story = { args: { ...meta.args, @@ -36,7 +46,7 @@ export const Authenticated: Story = { }, }; -export const UnAuthenticated: Story = { +export const Unauthenticated: Story = { args: { ...meta.args, auths: { diff --git a/site/src/pages/UserSettingsPage/ExternalAuthPage/ExternalAuthPageView.tsx b/site/src/pages/UserSettingsPage/ExternalAuthPage/ExternalAuthPageView.tsx index b789101fbc5ec..f0554952b8d44 100644 --- a/site/src/pages/UserSettingsPage/ExternalAuthPage/ExternalAuthPageView.tsx +++ b/site/src/pages/UserSettingsPage/ExternalAuthPage/ExternalAuthPageView.tsx @@ -14,9 +14,8 @@ import type { ExternalAuthLink, } from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; -import { Avatar } from "components/Avatar/Avatar"; -import { AvatarData } from "components/AvatarData/AvatarData"; import { FullScreenLoader } from "components/Loader/FullScreenLoader"; +import { Stack } from "components/Stack/Stack"; import { MoreMenu, MoreMenuContent, @@ -25,7 +24,10 @@ import { ThreeDotsButton, } from "components/MoreMenu/MoreMenu"; import { ExternalAuth } from "pages/CreateWorkspacePage/ExternalAuth"; -import { ExternalAuthPollingState } from "pages/CreateWorkspacePage/CreateWorkspacePage"; +import type { ExternalAuthPollingState } from "pages/CreateWorkspacePage/CreateWorkspacePage"; +import { ExternalIcon } from "components/ExternalIcon/ExternalIcon"; + +const FALLBACK_ICON = "/icon/widgets.svg"; export type ExternalAuthPageViewProps = { isLoading: boolean; @@ -129,15 +131,13 @@ const ExternalAuthRow: FC = ({ return ( - - ) - } - /> + + + {app.display_name} + = ({ message={authenticated ? "Authenticated" : "Click to Login"} externalAuthPollingState={externalAuthPollingState} startPollingExternalAuth={startPollingExternalAuth} + fullWidth={false} /> diff --git a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.stories.tsx b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.stories.tsx index 1986c7ef0cbdd..a8736defdcf46 100644 --- a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.stories.tsx +++ b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.stories.tsx @@ -11,7 +11,8 @@ const meta: Meta = { user_id: "test-user-id", created_at: "2022-07-28T07:45:50.795918897Z", updated_at: "2022-07-28T07:45:50.795919142Z", - public_key: "SSH-Key", + public_key: + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICnKzATuWwmmt5+CKTPuRGN0R1PBemA+6/SStpLiyX+L", }, }, }; diff --git a/site/src/pages/WorkspaceBuildPage/Sidebar.tsx b/site/src/pages/WorkspaceBuildPage/Sidebar.tsx index 869f3d4be9e08..370d51cdf6777 100644 --- a/site/src/pages/WorkspaceBuildPage/Sidebar.tsx +++ b/site/src/pages/WorkspaceBuildPage/Sidebar.tsx @@ -32,7 +32,7 @@ export const SidebarItem: FC = ({ return ( - ) : ( - - )} +
+
)} @@ -673,10 +659,6 @@ const styles = { borderTop: `1px solid ${theme.palette.divider}`, }), - logsPanelButtons: { - display: "flex", - }, - logsPanelButton: (theme) => ({ textAlign: "left", background: "transparent", @@ -689,10 +671,11 @@ const styles = { alignItems: "center", gap: 8, whiteSpace: "nowrap", + width: "100%", "&:hover": { color: theme.palette.text.primary, - backgroundColor: theme.colors.gray[14], + backgroundColor: theme.experimental.l2.hover.background, }, "& svg": { @@ -700,10 +683,6 @@ const styles = { }, }), - toggleLogsButton: { - width: "100%", - }, - buttonSkeleton: { borderRadius: 4, }, diff --git a/site/src/components/Resources/PortForwardButton.stories.tsx b/site/src/components/Resources/PortForwardButton.stories.tsx index 1f4c710e711a1..b2fc7ccfe704d 100644 --- a/site/src/components/Resources/PortForwardButton.stories.tsx +++ b/site/src/components/Resources/PortForwardButton.stories.tsx @@ -1,43 +1,31 @@ -import { PortForwardPopoverView } from "./PortForwardButton"; +import { PortForwardButton } from "./PortForwardButton"; import type { Meta, StoryObj } from "@storybook/react"; import { MockListeningPortsResponse, MockWorkspaceAgent, } from "testHelpers/entities"; -const meta: Meta = { - title: "components/PortForwardPopoverView", - component: PortForwardPopoverView, - decorators: [ - (Story) => ( -
({ - width: 304, - border: `1px solid ${theme.palette.divider}`, - borderRadius: 8, - backgroundColor: theme.palette.background.paper, - })} - > - -
- ), - ], +const meta: Meta = { + title: "components/PortForwardButton", + component: PortForwardButton, args: { agent: MockWorkspaceAgent, }, }; export default meta; -type Story = StoryObj; +type Story = StoryObj; -export const WithPorts: Story = { +export const Example: Story = { args: { - ports: MockListeningPortsResponse.ports, + storybook: { + portsQueryData: MockListeningPortsResponse, + }, }, }; -export const Empty: Story = { +export const Loading: Story = { args: { - ports: [], + storybook: {}, }, }; diff --git a/site/src/components/Resources/PortForwardButton.tsx b/site/src/components/Resources/PortForwardButton.tsx index a1935d282c56f..2b284586eaf45 100644 --- a/site/src/components/Resources/PortForwardButton.tsx +++ b/site/src/components/Resources/PortForwardButton.tsx @@ -10,6 +10,7 @@ import { getAgentListeningPorts } from "api/api"; import type { WorkspaceAgent, WorkspaceAgentListeningPort, + WorkspaceAgentListeningPortsResponse, } from "api/typesGenerated"; import { portForwardURL } from "utils/portForward"; import { type ClassName, useClassName } from "hooks/useClassName"; @@ -32,34 +33,43 @@ export interface PortForwardButtonProps { username: string; workspaceName: string; agent: WorkspaceAgent; + + /** + * Only for use in Storybook + */ + storybook?: { + portsQueryData?: WorkspaceAgentListeningPortsResponse; + }; } export const PortForwardButton: FC = (props) => { - const { agent } = props; + const { agent, storybook } = props; const paper = useClassName(classNames.paper, []); const portsQuery = useQuery({ queryKey: ["portForward", agent.id], queryFn: () => getAgentListeningPorts(agent.id), - enabled: agent.status === "connected", + enabled: !storybook && agent.status === "connected", refetchInterval: 5_000, }); + const data = storybook ? storybook.portsQueryData : portsQuery.data; + return ( - + {DisplayAppNameMap["port_forwarding_helper"]} - {portsQuery.data ? ( -
{portsQuery.data.ports.length}
+ {data ? ( +
{data.ports.length}
) : ( )}
- +
); @@ -204,7 +214,7 @@ const styles = { display: "flex", alignItems: "center", justifyContent: "center", - backgroundColor: theme.colors.gray[11], + backgroundColor: theme.experimental.l2.background, marginLeft: 8, }), diff --git a/site/src/components/Resources/PortForwardPopoverView.stories.tsx b/site/src/components/Resources/PortForwardPopoverView.stories.tsx new file mode 100644 index 0000000000000..1f4c710e711a1 --- /dev/null +++ b/site/src/components/Resources/PortForwardPopoverView.stories.tsx @@ -0,0 +1,43 @@ +import { PortForwardPopoverView } from "./PortForwardButton"; +import type { Meta, StoryObj } from "@storybook/react"; +import { + MockListeningPortsResponse, + MockWorkspaceAgent, +} from "testHelpers/entities"; + +const meta: Meta = { + title: "components/PortForwardPopoverView", + component: PortForwardPopoverView, + decorators: [ + (Story) => ( +
({ + width: 304, + border: `1px solid ${theme.palette.divider}`, + borderRadius: 8, + backgroundColor: theme.palette.background.paper, + })} + > + +
+ ), + ], + args: { + agent: MockWorkspaceAgent, + }, +}; + +export default meta; +type Story = StoryObj; + +export const WithPorts: Story = { + args: { + ports: MockListeningPortsResponse.ports, + }, +}; + +export const Empty: Story = { + args: { + ports: [], + }, +}; diff --git a/site/src/components/WorkspaceBuildLogs/Logs.tsx b/site/src/components/WorkspaceBuildLogs/Logs.tsx index 585adf0f9788b..40c419b600dc8 100644 --- a/site/src/components/WorkspaceBuildLogs/Logs.tsx +++ b/site/src/components/WorkspaceBuildLogs/Logs.tsx @@ -5,6 +5,8 @@ import { type FC, type ReactNode, useMemo } from "react"; import AnsiToHTML from "ansi-to-html"; import { MONOSPACE_FONT_FAMILY } from "theme/constants"; +const convert = new AnsiToHTML(); + export interface Line { time: string; output: string; @@ -16,9 +18,10 @@ export interface LogsProps { lines: Line[]; hideTimestamps?: boolean; className?: string; + children?: ReactNode; } -export const Logs: FC> = ({ +export const Logs: FC = ({ hideTimestamps, lines, className = "", @@ -50,16 +53,23 @@ export const Logs: FC> = ({ export const logLineHeight = 20; -const convert = new AnsiToHTML(); - -export const LogLine: FC<{ +interface LogLineProps { line: Line; hideTimestamp?: boolean; number?: number; style?: React.CSSProperties; sourceIcon?: ReactNode; maxNumber?: number; -}> = ({ line, hideTimestamp, number, maxNumber, sourceIcon, style }) => { +} + +export const LogLine: FC = ({ + line, + hideTimestamp, + number, + maxNumber, + sourceIcon, + style, +}) => { const output = useMemo(() => { return convert.toHtml(line.output.split(/\r/g).pop() as string); }, [line.output]); @@ -120,15 +130,15 @@ const styles = { padding: "0 32px", "&.error": { - backgroundColor: theme.palette.error.dark, + backgroundColor: theme.experimental.roles.error.background, }, "&.debug": { - backgroundColor: theme.palette.background.paper, + backgroundColor: theme.experimental.roles.info.background, }, "&.warn": { - backgroundColor: theme.palette.warning.dark, + backgroundColor: theme.experimental.roles.warning.background, }, }), space: { diff --git a/site/src/components/WorkspaceBuildLogs/WorkspaceBuildLogs.stories.tsx b/site/src/components/WorkspaceBuildLogs/WorkspaceBuildLogs.stories.tsx index 5044a9c4e07bd..39d966b890fa7 100644 --- a/site/src/components/WorkspaceBuildLogs/WorkspaceBuildLogs.stories.tsx +++ b/site/src/components/WorkspaceBuildLogs/WorkspaceBuildLogs.stories.tsx @@ -1,9 +1,11 @@ -import { Meta, StoryObj } from "@storybook/react"; -import { WorkspaceBuildLogs } from "./WorkspaceBuildLogs"; +import type { Meta, StoryObj } from "@storybook/react"; +import { chromatic } from "testHelpers/chromatic"; import { MockWorkspaceBuildLogs } from "testHelpers/entities"; +import { WorkspaceBuildLogs } from "./WorkspaceBuildLogs"; const meta: Meta = { title: "components/WorkspaceBuildLogs", + parameters: { chromatic }, component: WorkspaceBuildLogs, }; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx index dfb43f5c31a9b..002b6c678a857 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx @@ -1,4 +1,5 @@ import { Meta, StoryObj } from "@storybook/react"; +import { chromatic } from "testHelpers/chromatic"; import { mockApiError, MockTemplate, @@ -11,6 +12,7 @@ import { CreateWorkspacePageView } from "./CreateWorkspacePageView"; const meta: Meta = { title: "pages/CreateWorkspacePage", + parameters: { chromatic }, component: CreateWorkspacePageView, args: { defaultName: "", diff --git a/site/src/pages/SetupPage/SetupPageView.stories.tsx b/site/src/pages/SetupPage/SetupPageView.stories.tsx index 98f388043efed..239fb10cab930 100644 --- a/site/src/pages/SetupPage/SetupPageView.stories.tsx +++ b/site/src/pages/SetupPage/SetupPageView.stories.tsx @@ -1,9 +1,11 @@ -import { SetupPageView } from "./SetupPageView"; -import { mockApiError } from "testHelpers/entities"; import type { Meta, StoryObj } from "@storybook/react"; +import { chromatic } from "testHelpers/chromatic"; +import { mockApiError } from "testHelpers/entities"; +import { SetupPageView } from "./SetupPageView"; const meta: Meta = { title: "pages/SetupPage", + parameters: { chromatic }, component: SetupPageView, }; diff --git a/site/src/testHelpers/chromatic.ts b/site/src/testHelpers/chromatic.ts new file mode 100644 index 0000000000000..1617287b9e885 --- /dev/null +++ b/site/src/testHelpers/chromatic.ts @@ -0,0 +1,6 @@ +export const chromatic = { + modes: { + dark: { theme: "dark" }, + light: { theme: "light" }, + }, +}; diff --git a/site/src/theme/dark/experimental.ts b/site/src/theme/dark/experimental.ts index 9e1aaf383c379..dfa82cce3be94 100644 --- a/site/src/theme/dark/experimental.ts +++ b/site/src/theme/dark/experimental.ts @@ -3,25 +3,25 @@ import colors from "../tailwind"; export default { l1: { - background: colors.gray[950], - outline: colors.gray[700], - fill: colors.gray[600], + background: colors.zinc[950], + outline: colors.zinc[700], + fill: colors.zinc[600], text: colors.white, }, l2: { - background: colors.gray[900], - outline: colors.gray[700], + background: colors.zinc[900], + outline: colors.zinc[700], fill: "#f00", text: colors.white, disabled: { background: "#f00", outline: "#f00", fill: "#f00", - text: colors.gray[200], + text: colors.zinc[200], }, hover: { - background: "#f00", + background: colors.zinc[800], outline: "#f00", fill: "#f00", text: colors.white, @@ -29,15 +29,15 @@ export default { }, l3: { - background: colors.gray[800], - outline: colors.gray[700], - fill: colors.gray[600], + background: colors.zinc[800], + outline: colors.zinc[700], + fill: colors.zinc[600], text: colors.white, disabled: { background: "#f00", outline: "#f00", fill: "#f00", - text: colors.gray[200], + text: colors.zinc[200], }, hover: { background: "#f00", diff --git a/site/src/theme/light/experimental.ts b/site/src/theme/light/experimental.ts index 33d97e34df010..3c29de3b8ad23 100644 --- a/site/src/theme/light/experimental.ts +++ b/site/src/theme/light/experimental.ts @@ -21,7 +21,7 @@ export default { text: colors.gray[200], }, hover: { - background: "#f00", + background: colors.gray[200], outline: "#f00", fill: "#f00", text: colors.black, @@ -80,7 +80,7 @@ export default { }, notice: { background: colors.yellow[50], - outline: colors.yellow[200], + outline: colors.yellow[600], fill: colors.yellow[500], text: colors.yellow[950], }, From d86c20e8049cac6f2abdb56a5e3639b1edf8b604 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Mon, 18 Dec 2023 21:07:33 +0000 Subject: [PATCH 04/19] fix the editor --- .../FileTreeView.tsx | 11 +-- .../MonacoEditor.tsx | 76 ++++++------------- .../TemplateVersionEditor.stories.tsx | 12 +-- site/src/theme/dark/index.ts | 2 + site/src/theme/dark/monaco.ts | 37 +++++++++ site/src/theme/darkBlue/index.ts | 2 + site/src/theme/darkBlue/monaco.ts | 37 +++++++++ site/src/theme/index.ts | 2 + site/src/theme/light/experimental.ts | 2 +- site/src/theme/light/index.ts | 2 + site/src/theme/light/monaco.ts | 37 +++++++++ 11 files changed, 156 insertions(+), 64 deletions(-) create mode 100644 site/src/theme/dark/monaco.ts create mode 100644 site/src/theme/darkBlue/monaco.ts create mode 100644 site/src/theme/light/monaco.ts diff --git a/site/src/pages/TemplateVersionEditorPage/FileTreeView.tsx b/site/src/pages/TemplateVersionEditorPage/FileTreeView.tsx index c2e753cdb2bc6..a9924a1104781 100644 --- a/site/src/pages/TemplateVersionEditorPage/FileTreeView.tsx +++ b/site/src/pages/TemplateVersionEditorPage/FileTreeView.tsx @@ -92,8 +92,8 @@ export const FileTreeView: FC = ({ } &.Mui-selected { - color: ${theme.palette.text.primary}; - background: ${theme.colors.gray[14]}; + color: ${theme.experimental.roles.active.text}; + background: ${theme.experimental.roles.active.background}; } &.Mui-focused { @@ -133,16 +133,13 @@ export const FileTreeView: FC = ({ } as CSSProperties } > - {isFolder ? ( + {isFolder && Object.keys(content) .sort(sortFileTree(content)) .map((filename) => { const child = content[filename]; return buildTreeItems(filename, child, currentPath); - }) - ) : ( - <> - )} + })} ); }; diff --git a/site/src/pages/TemplateVersionEditorPage/MonacoEditor.tsx b/site/src/pages/TemplateVersionEditorPage/MonacoEditor.tsx index 7b3ed9ab29d2a..7667afc4431b7 100644 --- a/site/src/pages/TemplateVersionEditorPage/MonacoEditor.tsx +++ b/site/src/pages/TemplateVersionEditorPage/MonacoEditor.tsx @@ -1,16 +1,22 @@ import { useTheme } from "@emotion/react"; import Editor, { loader } from "@monaco-editor/react"; import * as monaco from "monaco-editor"; -import { FC, useMemo } from "react"; +import { type FC, useEffect, useMemo } from "react"; import { MONOSPACE_FONT_FAMILY } from "theme/constants"; loader.config({ monaco }); -export const MonacoEditor: FC<{ +interface MonacoEditorProps { value?: string; path?: string; onChange?: (value: string) => void; -}> = ({ onChange, value, path }) => { +} + +export const MonacoEditor: FC = ({ + onChange, + value, + path, +}) => { const theme = useTheme(); const language = useMemo(() => { @@ -31,6 +37,20 @@ export const MonacoEditor: FC<{ } }, [path]); + useEffect(() => { + document.fonts.ready + .then(() => { + // Ensures that all text is measured properly. + // If this isn't done, there can be weird selection issues. + monaco.editor.remeasureFonts(); + }) + .catch(() => { + // Not a biggie! + }); + + monaco.editor.defineTheme("min", theme.monaco); + }, [theme]); + return ( { + onMount={(editor) => { // This jank allows for Ctrl + Enter to work outside the editor. // We use this keybind to trigger a build. // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Private type in Monaco! (editor as any)._standaloneKeybindingService.addDynamicKeybinding( `-editor.action.insertLineAfter`, monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, - () => { - // - }, + () => {}, ); - document.fonts.ready - .then(() => { - // Ensures that all text is measured properly. - // If this isn't done, there can be weird selection issues. - monaco.editor.remeasureFonts(); - }) - .catch(() => { - // Not a biggie! - }); - - monaco.editor.defineTheme("min", { - base: "vs-dark", - inherit: true, - rules: [ - { - token: "comment", - foreground: "6B737C", - }, - { - token: "type", - foreground: "B392F0", - }, - { - token: "string", - foreground: "9DB1C5", - }, - { - token: "variable", - foreground: "BBBBBB", - }, - { - token: "identifier", - foreground: "B392F0", - }, - { - token: "delimiter.curly", - foreground: "EBB325", - }, - ], - colors: { - "editor.foreground": theme.palette.text.primary, - "editor.background": theme.palette.background.paper, - }, - }); editor.updateOptions({ theme: "min", }); diff --git a/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.stories.tsx b/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.stories.tsx index bcd60352568ae..a2fe510d2badf 100644 --- a/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.stories.tsx +++ b/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.stories.tsx @@ -1,3 +1,5 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { chromatic } from "testHelpers/chromatic"; import { MockFailedProvisionerJob, MockRunningProvisionerJob, @@ -14,19 +16,19 @@ import { MockWorkspaceVolumeResource, } from "testHelpers/entities"; import { TemplateVersionEditor } from "./TemplateVersionEditor"; -import type { Meta, StoryObj } from "@storybook/react"; const meta: Meta = { - title: "pages/TemplateVersionEditorPage", + title: "pages/TemplateVersionEditor", + parameters: { + chromatic, + layout: "fullscreen", + }, component: TemplateVersionEditor, args: { template: MockTemplate, templateVersion: MockTemplateVersion, defaultFileTree: MockTemplateVersionFileTree, }, - parameters: { - layout: "fullscreen", - }, }; export default meta; diff --git a/site/src/theme/dark/index.ts b/site/src/theme/dark/index.ts index 19a84fc4b2c0a..4a1d9094c6bc2 100644 --- a/site/src/theme/dark/index.ts +++ b/site/src/theme/dark/index.ts @@ -1,9 +1,11 @@ import colors from "./colors"; import experimental from "./experimental"; +import monaco from "./monaco"; import muiTheme from "./mui"; export default { ...muiTheme, colors, experimental, + monaco, }; diff --git a/site/src/theme/dark/monaco.ts b/site/src/theme/dark/monaco.ts new file mode 100644 index 0000000000000..727c481b7f3a2 --- /dev/null +++ b/site/src/theme/dark/monaco.ts @@ -0,0 +1,37 @@ +import muiTheme from "./mui"; +import type * as monaco from "monaco-editor"; + +export default { + base: "vs-dark", + inherit: true, + rules: [ + { + token: "comment", + foreground: "6B737C", + }, + { + token: "type", + foreground: "B392F0", + }, + { + token: "string", + foreground: "9DB1C5", + }, + { + token: "variable", + foreground: "DDDDDD", + }, + { + token: "identifier", + foreground: "B392F0", + }, + { + token: "delimiter.curly", + foreground: "EBB325", + }, + ], + colors: { + "editor.foreground": muiTheme.palette.text.primary, + "editor.background": muiTheme.palette.background.paper, + }, +} satisfies monaco.editor.IStandaloneThemeData; diff --git a/site/src/theme/darkBlue/index.ts b/site/src/theme/darkBlue/index.ts index 19a84fc4b2c0a..4a1d9094c6bc2 100644 --- a/site/src/theme/darkBlue/index.ts +++ b/site/src/theme/darkBlue/index.ts @@ -1,9 +1,11 @@ import colors from "./colors"; import experimental from "./experimental"; +import monaco from "./monaco"; import muiTheme from "./mui"; export default { ...muiTheme, colors, experimental, + monaco, }; diff --git a/site/src/theme/darkBlue/monaco.ts b/site/src/theme/darkBlue/monaco.ts new file mode 100644 index 0000000000000..727c481b7f3a2 --- /dev/null +++ b/site/src/theme/darkBlue/monaco.ts @@ -0,0 +1,37 @@ +import muiTheme from "./mui"; +import type * as monaco from "monaco-editor"; + +export default { + base: "vs-dark", + inherit: true, + rules: [ + { + token: "comment", + foreground: "6B737C", + }, + { + token: "type", + foreground: "B392F0", + }, + { + token: "string", + foreground: "9DB1C5", + }, + { + token: "variable", + foreground: "DDDDDD", + }, + { + token: "identifier", + foreground: "B392F0", + }, + { + token: "delimiter.curly", + foreground: "EBB325", + }, + ], + colors: { + "editor.foreground": muiTheme.palette.text.primary, + "editor.background": muiTheme.palette.background.paper, + }, +} satisfies monaco.editor.IStandaloneThemeData; diff --git a/site/src/theme/index.ts b/site/src/theme/index.ts index 2622b58c4a2a4..6920f5662baa0 100644 --- a/site/src/theme/index.ts +++ b/site/src/theme/index.ts @@ -1,4 +1,5 @@ import type { Theme as MuiTheme } from "@mui/material/styles"; +import type * as monaco from "monaco-editor"; import dark from "./dark"; import darkBlue from "./darkBlue"; import light from "./light"; @@ -8,6 +9,7 @@ import type { Colors } from "./colors"; export interface Theme extends MuiTheme { colors: Colors; experimental: NewTheme; + monaco: monaco.editor.IStandaloneThemeData; } export const DEFAULT_THEME = "auto"; diff --git a/site/src/theme/light/experimental.ts b/site/src/theme/light/experimental.ts index 3c29de3b8ad23..9750c9abd4e57 100644 --- a/site/src/theme/light/experimental.ts +++ b/site/src/theme/light/experimental.ts @@ -109,7 +109,7 @@ export default { }, }, active: { - background: colors.sky[50], + background: colors.sky[100], outline: colors.sky[500], fill: colors.sky[600], text: colors.sky[950], diff --git a/site/src/theme/light/index.ts b/site/src/theme/light/index.ts index 19a84fc4b2c0a..4a1d9094c6bc2 100644 --- a/site/src/theme/light/index.ts +++ b/site/src/theme/light/index.ts @@ -1,9 +1,11 @@ import colors from "./colors"; import experimental from "./experimental"; +import monaco from "./monaco"; import muiTheme from "./mui"; export default { ...muiTheme, colors, experimental, + monaco, }; diff --git a/site/src/theme/light/monaco.ts b/site/src/theme/light/monaco.ts new file mode 100644 index 0000000000000..500a84858dda3 --- /dev/null +++ b/site/src/theme/light/monaco.ts @@ -0,0 +1,37 @@ +import muiTheme from "./mui"; +import type * as monaco from "monaco-editor"; + +export default { + base: "vs", + inherit: true, + rules: [ + { + token: "comment", + foreground: "6B737C", + }, + { + token: "type", + foreground: "682CD7", + }, + { + token: "string", + foreground: "1766B4", + }, + { + token: "variable", + foreground: "444444", + }, + { + token: "identifier", + foreground: "682CD7", + }, + { + token: "delimiter.curly", + foreground: "EBB325", + }, + ], + colors: { + "editor.foreground": muiTheme.palette.text.primary, + "editor.background": muiTheme.palette.background.paper, + }, +} satisfies monaco.editor.IStandaloneThemeData; From 3eeb8d0ef6324eba34cde7ca6992ea261a6722e9 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Mon, 18 Dec 2023 21:19:43 +0000 Subject: [PATCH 05/19] tweak story parameters --- site/.storybook/preview.jsx | 12 ++++++++++++ .../Dashboard/Navbar/NavbarView.stories.tsx | 13 ++----------- site/src/testHelpers/chromatic.ts | 7 +++++++ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/site/.storybook/preview.jsx b/site/.storybook/preview.jsx index 65ee5242b6c1d..05d5a340747c5 100644 --- a/site/.storybook/preview.jsx +++ b/site/.storybook/preview.jsx @@ -76,4 +76,16 @@ export const parameters = { date: /Date$/, }, }, + viewport: { + viewports: { + ipad: { + name: "iPad Mini", + styles: { + height: "1024px", + width: "768px", + }, + type: "tablet", + }, + }, + }, }; diff --git a/site/src/components/Dashboard/Navbar/NavbarView.stories.tsx b/site/src/components/Dashboard/Navbar/NavbarView.stories.tsx index 7a59ab19d0067..fa9dcc4cfbe36 100644 --- a/site/src/components/Dashboard/Navbar/NavbarView.stories.tsx +++ b/site/src/components/Dashboard/Navbar/NavbarView.stories.tsx @@ -1,11 +1,11 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { chromatic } from "testHelpers/chromatic"; +import { chromaticWithTablet } from "testHelpers/chromatic"; import { MockUser, MockUser2 } from "testHelpers/entities"; import { NavbarView } from "./NavbarView"; const meta: Meta = { title: "components/NavbarView", - parameters: { chromatic }, + parameters: { chromatic: chromaticWithTablet }, component: NavbarView, args: { user: MockUser, @@ -25,12 +25,3 @@ export const ForMember: Story = { canViewAllUsers: false, }, }; - -export const SmallViewport: Story = { - parameters: { - viewport: { - defaultViewport: "tablet", - }, - chromatic: { viewports: [420] }, - }, -}; diff --git a/site/src/testHelpers/chromatic.ts b/site/src/testHelpers/chromatic.ts index 1617287b9e885..a3282f2178c97 100644 --- a/site/src/testHelpers/chromatic.ts +++ b/site/src/testHelpers/chromatic.ts @@ -4,3 +4,10 @@ export const chromatic = { light: { theme: "light" }, }, }; + +export const chromaticWithTablet = { + modes: { + "dark desktop": { theme: "dark" }, + "light tablet": { theme: "light", viewport: "ipad" }, + }, +}; From 405d0f3497e99609137fc48619975fd90ebd3a0e Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Mon, 18 Dec 2023 21:36:00 +0000 Subject: [PATCH 06/19] oh boy --- site/src/@types/mui.d.ts | 4 --- .../ProxyStatusLatency/ProxyStatusLatency.tsx | 2 +- .../src/components/Resources/AgentLatency.tsx | 9 ++++-- site/src/pages/HealthPage/DERPRegionPage.tsx | 31 ++++++++++--------- site/src/theme/dark/monaco.ts | 2 +- site/src/theme/darkBlue/monaco.ts | 2 +- site/src/theme/light/monaco.ts | 2 +- site/src/utils/latency.ts | 2 +- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/site/src/@types/mui.d.ts b/site/src/@types/mui.d.ts index 4017af0f1b6e8..02b3c1ae4517e 100644 --- a/site/src/@types/mui.d.ts +++ b/site/src/@types/mui.d.ts @@ -2,10 +2,6 @@ import type { PaletteColor, PaletteColorOptions } from "@mui/material/styles"; import type { NewTheme } from "theme/experimental"; declare module "@mui/material/styles" { - interface Theme { - experimental: NewTheme; - } - interface Palette { neutral: PaletteColor; } diff --git a/site/src/components/ProxyStatusLatency/ProxyStatusLatency.tsx b/site/src/components/ProxyStatusLatency/ProxyStatusLatency.tsx index 330aaa542eeb5..6776cf06e1f55 100644 --- a/site/src/components/ProxyStatusLatency/ProxyStatusLatency.tsx +++ b/site/src/components/ProxyStatusLatency/ProxyStatusLatency.tsx @@ -1,4 +1,4 @@ -import { useTheme } from "@mui/material/styles"; +import { useTheme } from "@emotion/react"; import HelpOutline from "@mui/icons-material/HelpOutline"; import Tooltip from "@mui/material/Tooltip"; import { type FC } from "react"; diff --git a/site/src/components/Resources/AgentLatency.tsx b/site/src/components/Resources/AgentLatency.tsx index a6ee1757f67e6..e30400465e9e3 100644 --- a/site/src/components/Resources/AgentLatency.tsx +++ b/site/src/components/Resources/AgentLatency.tsx @@ -1,6 +1,5 @@ import { type FC, useRef, useState } from "react"; -import { useTheme } from "@emotion/react"; -import { Theme } from "@mui/material/styles"; +import { type Theme, useTheme } from "@emotion/react"; import type { WorkspaceAgent, DERPRegion } from "api/typesGenerated"; import { HelpTooltipText, @@ -29,7 +28,11 @@ const getDisplayLatency = (theme: Theme, agent: WorkspaceAgent) => { }; }; -export const AgentLatency: FC<{ agent: WorkspaceAgent }> = ({ agent }) => { +interface AgentLatencyProps { + agent: WorkspaceAgent; +} + +export const AgentLatency: FC = ({ agent }) => { const theme = useTheme(); const anchorRef = useRef(null); const [isOpen, setIsOpen] = useState(false); diff --git a/site/src/pages/HealthPage/DERPRegionPage.tsx b/site/src/pages/HealthPage/DERPRegionPage.tsx index 3dfb1cea2a7b0..35503c3f39388 100644 --- a/site/src/pages/HealthPage/DERPRegionPage.tsx +++ b/site/src/pages/HealthPage/DERPRegionPage.tsx @@ -1,4 +1,19 @@ +import Tooltip from "@mui/material/Tooltip"; +import CodeOutlined from "@mui/icons-material/CodeOutlined"; +import TagOutlined from "@mui/icons-material/TagOutlined"; +import ArrowBackOutlined from "@mui/icons-material/ArrowBackOutlined"; +import { useTheme } from "@emotion/react"; +import { type FC } from "react"; +import { Helmet } from "react-helmet-async"; import { Link, useOutletContext, useParams } from "react-router-dom"; +import type { + HealthMessage, + HealthSeverity, + HealthcheckReport, +} from "api/typesGenerated"; +import { getLatencyColor } from "utils/latency"; +import { Alert } from "components/Alert/Alert"; +import { pageTitle } from "utils/page"; import { Header, HeaderTitle, @@ -8,22 +23,8 @@ import { Logs, HealthyDot, } from "./Content"; -import { - HealthMessage, - HealthSeverity, - HealthcheckReport, -} from "api/typesGenerated"; -import CodeOutlined from "@mui/icons-material/CodeOutlined"; -import TagOutlined from "@mui/icons-material/TagOutlined"; -import Tooltip from "@mui/material/Tooltip"; -import { useTheme } from "@mui/material/styles"; -import ArrowBackOutlined from "@mui/icons-material/ArrowBackOutlined"; -import { getLatencyColor } from "utils/latency"; -import { Alert } from "components/Alert/Alert"; -import { Helmet } from "react-helmet-async"; -import { pageTitle } from "utils/page"; -export const DERPRegionPage = () => { +export const DERPRegionPage: FC = () => { const theme = useTheme(); const healthStatus = useOutletContext(); const params = useParams() as { regionId: string }; diff --git a/site/src/theme/dark/monaco.ts b/site/src/theme/dark/monaco.ts index 727c481b7f3a2..ae020bdd1ba33 100644 --- a/site/src/theme/dark/monaco.ts +++ b/site/src/theme/dark/monaco.ts @@ -34,4 +34,4 @@ export default { "editor.foreground": muiTheme.palette.text.primary, "editor.background": muiTheme.palette.background.paper, }, -} satisfies monaco.editor.IStandaloneThemeData; +} satisfies monaco.editor.IStandaloneThemeData as monaco.editor.IStandaloneThemeData; diff --git a/site/src/theme/darkBlue/monaco.ts b/site/src/theme/darkBlue/monaco.ts index 727c481b7f3a2..ae020bdd1ba33 100644 --- a/site/src/theme/darkBlue/monaco.ts +++ b/site/src/theme/darkBlue/monaco.ts @@ -34,4 +34,4 @@ export default { "editor.foreground": muiTheme.palette.text.primary, "editor.background": muiTheme.palette.background.paper, }, -} satisfies monaco.editor.IStandaloneThemeData; +} satisfies monaco.editor.IStandaloneThemeData as monaco.editor.IStandaloneThemeData; diff --git a/site/src/theme/light/monaco.ts b/site/src/theme/light/monaco.ts index 500a84858dda3..6dc38d2be7c36 100644 --- a/site/src/theme/light/monaco.ts +++ b/site/src/theme/light/monaco.ts @@ -34,4 +34,4 @@ export default { "editor.foreground": muiTheme.palette.text.primary, "editor.background": muiTheme.palette.background.paper, }, -} satisfies monaco.editor.IStandaloneThemeData; +} satisfies monaco.editor.IStandaloneThemeData as monaco.editor.IStandaloneThemeData; diff --git a/site/src/utils/latency.ts b/site/src/utils/latency.ts index 3bb891a20ee84..4281fa17e990f 100644 --- a/site/src/utils/latency.ts +++ b/site/src/utils/latency.ts @@ -1,4 +1,4 @@ -import { Theme } from "@mui/material/styles"; +import type { Theme } from "@emotion/react"; export const getLatencyColor = (theme: Theme, latency?: number) => { if (!latency) { From d407ccf3ad8c12a355d01452c91c149a76d0ee9a Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Mon, 18 Dec 2023 21:51:17 +0000 Subject: [PATCH 07/19] =?UTF-8?q?=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site/src/@types/mui.d.ts | 1 - site/src/components/Dashboard/Navbar/NavbarView.stories.tsx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/site/src/@types/mui.d.ts b/site/src/@types/mui.d.ts index 02b3c1ae4517e..255981fdf60fc 100644 --- a/site/src/@types/mui.d.ts +++ b/site/src/@types/mui.d.ts @@ -1,5 +1,4 @@ import type { PaletteColor, PaletteColorOptions } from "@mui/material/styles"; -import type { NewTheme } from "theme/experimental"; declare module "@mui/material/styles" { interface Palette { diff --git a/site/src/components/Dashboard/Navbar/NavbarView.stories.tsx b/site/src/components/Dashboard/Navbar/NavbarView.stories.tsx index fa9dcc4cfbe36..93afc9c618622 100644 --- a/site/src/components/Dashboard/Navbar/NavbarView.stories.tsx +++ b/site/src/components/Dashboard/Navbar/NavbarView.stories.tsx @@ -5,7 +5,7 @@ import { NavbarView } from "./NavbarView"; const meta: Meta = { title: "components/NavbarView", - parameters: { chromatic: chromaticWithTablet }, + parameters: { chromatic: chromaticWithTablet, layout: "fullscreen" }, component: NavbarView, args: { user: MockUser, From e81f23a86f0183dc50f7950dbb2bb5ce37e4c43e Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Mon, 18 Dec 2023 22:08:16 +0000 Subject: [PATCH 08/19] add some ignore attributes for chromatic --- site/src/components/Loader/Loader.tsx | 1 + site/src/pages/HealthPage/HealthLayout.tsx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/site/src/components/Loader/Loader.tsx b/site/src/components/Loader/Loader.tsx index d225b5dc2621f..5b7142bef4ae9 100644 --- a/site/src/components/Loader/Loader.tsx +++ b/site/src/components/Loader/Loader.tsx @@ -16,6 +16,7 @@ export const Loader: FC = ({ size = 26, ...attrs }) => { justifyContent: "center", }} data-testid="loader" + data-chromatic="ignore" {...attrs} > diff --git a/site/src/pages/HealthPage/HealthLayout.tsx b/site/src/pages/HealthPage/HealthLayout.tsx index 448de1665f4a3..c45825507c763 100644 --- a/site/src/pages/HealthPage/HealthLayout.tsx +++ b/site/src/pages/HealthPage/HealthLayout.tsx @@ -126,6 +126,7 @@ export function HealthLayout() {
Last check Version Date: Mon, 18 Dec 2023 23:10:51 +0000 Subject: [PATCH 09/19] next round --- .../src/components/Resources/AgentRow.stories.tsx | 4 +++- .../RichParameterInput.stories.tsx | 6 ++++-- .../AuditPage/AuditLogRow/AuditLogRow.stories.tsx | 5 ++++- .../src/pages/AuditPage/AuditPageView.stories.tsx | 15 ++++----------- .../WorkspaceScheduleForm.tsx | 7 ++++--- site/src/theme/dark/experimental.ts | 2 +- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/site/src/components/Resources/AgentRow.stories.tsx b/site/src/components/Resources/AgentRow.stories.tsx index f4a08edbed846..b760899683304 100644 --- a/site/src/components/Resources/AgentRow.stories.tsx +++ b/site/src/components/Resources/AgentRow.stories.tsx @@ -1,3 +1,5 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { chromatic } from "testHelpers/chromatic"; import { MockPrimaryWorkspaceProxy, MockWorkspaceProxies, @@ -21,7 +23,6 @@ import { } from "testHelpers/entities"; import { AgentRow, LineWithID } from "./AgentRow"; import { ProxyContext, getPreferredProxy } from "contexts/ProxyContext"; -import type { Meta, StoryObj } from "@storybook/react"; const defaultAgentMetadata = [ { @@ -102,6 +103,7 @@ const storybookLogs: LineWithID[] = [ const meta: Meta = { title: "components/AgentRow", + parameters: { chromatic }, component: AgentRow, args: { storybookLogs, diff --git a/site/src/components/RichParameterInput/RichParameterInput.stories.tsx b/site/src/components/RichParameterInput/RichParameterInput.stories.tsx index cd654ba7f2abc..8d1d5212fa59a 100644 --- a/site/src/components/RichParameterInput/RichParameterInput.stories.tsx +++ b/site/src/components/RichParameterInput/RichParameterInput.stories.tsx @@ -1,9 +1,11 @@ -import { TemplateVersionParameter } from "api/typesGenerated"; -import { RichParameterInput } from "./RichParameterInput"; import type { Meta, StoryObj } from "@storybook/react"; +import type { TemplateVersionParameter } from "api/typesGenerated"; +import { chromatic } from "testHelpers/chromatic"; +import { RichParameterInput } from "./RichParameterInput"; const meta: Meta = { title: "components/RichParameterInput", + parameters: { chromatic }, component: RichParameterInput, }; diff --git a/site/src/pages/AuditPage/AuditLogRow/AuditLogRow.stories.tsx b/site/src/pages/AuditPage/AuditLogRow/AuditLogRow.stories.tsx index 9c7c681d4e59a..352b6b8d578aa 100644 --- a/site/src/pages/AuditPage/AuditLogRow/AuditLogRow.stories.tsx +++ b/site/src/pages/AuditPage/AuditLogRow/AuditLogRow.stories.tsx @@ -4,6 +4,8 @@ import TableCell from "@mui/material/TableCell"; import TableContainer from "@mui/material/TableContainer"; import TableHead from "@mui/material/TableHead"; import TableRow from "@mui/material/TableRow"; +import type { Meta, StoryObj } from "@storybook/react"; +import { chromatic } from "testHelpers/chromatic"; import { MockAuditLog, MockAuditLog2, @@ -12,7 +14,6 @@ import { MockAuditLogGitSSH, } from "testHelpers/entities"; import { AuditLogRow } from "./AuditLogRow"; -import type { Meta, StoryObj } from "@storybook/react"; const meta: Meta = { title: "pages/AuditPage/AuditLogRow", @@ -48,6 +49,7 @@ export const NoDiff: Story = { }; export const WithDiff: Story = { + parameters: { chromatic }, args: { auditLog: MockAuditLog2, defaultIsDiffOpen: true, @@ -55,6 +57,7 @@ export const WithDiff: Story = { }; export const WithLongDiffRow: Story = { + parameters: { chromatic }, args: { auditLog: { ...MockAuditLog2, diff --git a/site/src/pages/AuditPage/AuditPageView.stories.tsx b/site/src/pages/AuditPage/AuditPageView.stories.tsx index e64e54b48699d..69aa64977e92a 100644 --- a/site/src/pages/AuditPage/AuditPageView.stories.tsx +++ b/site/src/pages/AuditPage/AuditPageView.stories.tsx @@ -1,12 +1,13 @@ import { Meta, StoryObj } from "@storybook/react"; +import { type ComponentProps } from "react"; +import { chromaticWithTablet } from "testHelpers/chromatic"; import { MockAuditLog, MockAuditLog2, MockUser } from "testHelpers/entities"; -import { AuditPageView } from "./AuditPageView"; -import { ComponentProps } from "react"; import { mockInitialRenderResult, mockSuccessResult, } from "components/PaginationWidget/PaginationContainer.mocks"; import { type UsePaginatedQueryResult } from "hooks/usePaginatedQuery"; +import { AuditPageView } from "./AuditPageView"; import { MockMenu, @@ -43,6 +44,7 @@ export default meta; type Story = StoryObj; export const AuditPage: Story = { + parameters: { chromatic: chromaticWithTablet }, args: { auditsQuery: mockSuccessResult, }, @@ -84,12 +86,3 @@ export const NotVisible: Story = { auditsQuery: mockInitialRenderResult, }, }; - -export const AuditPageSmallViewport: Story = { - args: { - auditsQuery: mockSuccessResult, - }, - parameters: { - chromatic: { viewports: [600] }, - }, -}; diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.tsx index f72ee49fefcfa..e4c51bd8a91b2 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceScheduleForm.tsx @@ -25,13 +25,14 @@ import { defaultSchedule, emptySchedule, } from "pages/WorkspaceSettingsPage/WorkspaceSchedulePage/schedule"; -import { ChangeEvent, FC } from "react"; +import { type ChangeEvent, type FC } from "react"; import * as Yup from "yup"; import { getFormHelpers } from "utils/formUtils"; import { timeZones } from "utils/timeZones"; import { Pill } from "components/Pill/Pill"; import Tooltip from "@mui/material/Tooltip"; import { formatDuration, intervalToDuration } from "date-fns"; +import { DisabledBadge } from "components/Badges/Badges"; // REMARK: some plugins depend on utc, so it's listed first. Otherwise they're // sorted alphabetically. @@ -290,7 +291,7 @@ export const WorkspaceScheduleForm: FC<
{!enableAutoStart && ( - + )} @@ -378,7 +379,7 @@ export const WorkspaceScheduleForm: FC<
{!enableAutoStop && ( - + )} diff --git a/site/src/theme/dark/experimental.ts b/site/src/theme/dark/experimental.ts index dfa82cce3be94..f715327c41367 100644 --- a/site/src/theme/dark/experimental.ts +++ b/site/src/theme/dark/experimental.ts @@ -69,7 +69,7 @@ export default { error: { background: colors.red[950], outline: colors.red[500], - fill: colors.red[600], + fill: colors.red[400], text: colors.red[50], }, warning: { From 058991f1a88b70ec8fd4bff1fbabab5d80484f89 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Tue, 19 Dec 2023 00:26:14 +0000 Subject: [PATCH 10/19] bunch of polish --- site/src/components/Badges/Badges.tsx | 10 +-- .../DeploymentBanner/DeploymentBannerView.tsx | 2 +- .../LicenseBannerView.stories.tsx | 2 + .../LicenseBanner/LicenseBannerView.tsx | 18 +++-- .../Navbar/UserDropdown/UserDropdown.tsx | 2 +- .../ServiceBanner/ServiceBannerView.tsx | 72 +++++++------------ site/src/components/Markdown/Markdown.tsx | 23 ++++-- .../AppearanceSettingsPageView.tsx | 4 +- .../TemplateVersionsPage/VersionRow.tsx | 11 --- .../TemplatesPageView.stories.tsx | 13 +--- .../pages/TemplatesPage/TemplatesPageView.tsx | 16 ++--- site/src/theme/dark/experimental.ts | 10 +-- site/src/theme/darkBlue/experimental.ts | 8 +-- site/src/theme/light/experimental.ts | 12 ++-- 14 files changed, 97 insertions(+), 106 deletions(-) diff --git a/site/src/components/Badges/Badges.tsx b/site/src/components/Badges/Badges.tsx index b8e6b9ae330cd..cd230156551ee 100644 --- a/site/src/components/Badges/Badges.tsx +++ b/site/src/components/Badges/Badges.tsx @@ -131,11 +131,11 @@ export const DeprecatedBadge: FC = () => { ({ + border: `1px solid ${theme.experimental.roles.danger.outline}`, + backgroundColor: theme.experimental.roles.danger.background, + color: theme.experimental.roles.danger.text, + }), ]} > Deprecated diff --git a/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx b/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx index 1cb105118ebf8..191187449fbe5 100644 --- a/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx +++ b/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx @@ -378,7 +378,7 @@ const HealthIssue: FC = ({ children }) => { {children} diff --git a/site/src/components/Dashboard/LicenseBanner/LicenseBannerView.stories.tsx b/site/src/components/Dashboard/LicenseBanner/LicenseBannerView.stories.tsx index cc37d18488085..ffd396bb0fba6 100644 --- a/site/src/components/Dashboard/LicenseBanner/LicenseBannerView.stories.tsx +++ b/site/src/components/Dashboard/LicenseBanner/LicenseBannerView.stories.tsx @@ -1,8 +1,10 @@ import type { Meta, StoryObj } from "@storybook/react"; +import { chromatic } from "testHelpers/chromatic"; import { LicenseBannerView } from "./LicenseBannerView"; const meta: Meta = { title: "components/LicenseBannerView", + parameters: { chromatic }, component: LicenseBannerView, }; diff --git a/site/src/components/Dashboard/LicenseBanner/LicenseBannerView.tsx b/site/src/components/Dashboard/LicenseBanner/LicenseBannerView.tsx index 7e3889fcebdd8..31c9f4269e48d 100644 --- a/site/src/components/Dashboard/LicenseBanner/LicenseBannerView.tsx +++ b/site/src/components/Dashboard/LicenseBanner/LicenseBannerView.tsx @@ -47,11 +47,11 @@ export const LicenseBannerView: FC = ({ display: flex; align-items: center; padding: 12px; - background-color: ${type === "error" - ? theme.colors.red[10] - : theme.colors.orange[10]}; + background-color: ${theme.experimental.roles[type].background}; `; + const textColor = theme.experimental.roles[type].text; + if (messages.length === 1) { return (
@@ -59,7 +59,11 @@ export const LicenseBannerView: FC = ({
{messages[0]}   - + {Language.upgrade}
@@ -74,7 +78,11 @@ export const LicenseBannerView: FC = ({
{Language.exceeded}   - + {Language.upgrade}
diff --git a/site/src/components/Dashboard/Navbar/UserDropdown/UserDropdown.tsx b/site/src/components/Dashboard/Navbar/UserDropdown/UserDropdown.tsx index 3f5661e8df5e5..a5e83c0d50f1b 100644 --- a/site/src/components/Dashboard/Navbar/UserDropdown/UserDropdown.tsx +++ b/site/src/components/Dashboard/Navbar/UserDropdown/UserDropdown.tsx @@ -45,7 +45,7 @@ export const UserDropdown: FC = ({ />
diff --git a/site/src/components/Dashboard/ServiceBanner/ServiceBannerView.tsx b/site/src/components/Dashboard/ServiceBanner/ServiceBannerView.tsx index cc389f191ff09..b2b30ecb46d70 100644 --- a/site/src/components/Dashboard/ServiceBanner/ServiceBannerView.tsx +++ b/site/src/components/Dashboard/ServiceBanner/ServiceBannerView.tsx @@ -1,6 +1,7 @@ +import { css, type Interpolation, type Theme } from "@emotion/react"; +import { type FC } from "react"; +import { InlineMarkdown } from "components/Markdown/Markdown"; import { Pill } from "components/Pill/Pill"; -import ReactMarkdown from "react-markdown"; -import { css, useTheme } from "@emotion/react"; import { readableForegroundColor } from "utils/colors"; export interface ServiceBannerViewProps { @@ -9,58 +10,39 @@ export interface ServiceBannerViewProps { isPreview: boolean; } -export const ServiceBannerView: React.FC = ({ +export const ServiceBannerView: FC = ({ message, backgroundColor, isPreview, }) => { - const theme = useTheme(); - // We don't want anything funky like an image or a heading in the service - // banner. - const markdownElementsAllowed = [ - "text", - "a", - "pre", - "ul", - "strong", - "emphasis", - "italic", - "link", - "em", - ]; return ( -
+
{isPreview && }
- - {message} - + {message}
); }; + +const styles = { + banner: css` + padding: 12px; + display: flex; + align-items: center; + `, + wrapper: css` + margin-right: auto; + margin-left: auto; + font-weight: 400; + + & a { + color: inherit; + } + `, +} satisfies Record>; diff --git a/site/src/components/Markdown/Markdown.tsx b/site/src/components/Markdown/Markdown.tsx index a3a54f0dd6241..e6defa3733288 100644 --- a/site/src/components/Markdown/Markdown.tsx +++ b/site/src/components/Markdown/Markdown.tsx @@ -121,12 +121,19 @@ export const Markdown: FC = (props) => { ); }; -interface MarkdownInlineProps { +interface InlineMarkdownProps { /** * The Markdown text to parse and render */ children: string; + /** + * Additional element types to allow. + * Allows italic, bold, links, and inline code snippets by default. + * eg. `["ol", "ul", "li"]` to support lists. + */ + allowedElements?: readonly string[]; + className?: string; /** @@ -138,13 +145,21 @@ interface MarkdownInlineProps { /** * Supports a strict subset of Markdown that behaves well as inline/confined content. */ -export const InlineMarkdown: FC = (props) => { - const { children, className, components = {} } = props; +export const InlineMarkdown: FC = (props) => { + const { children, allowedElements = [], className, components = {} } = props; return ( <>{children}, diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx index e4ae30c846757..be6092f0b0b88 100644 --- a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx @@ -19,6 +19,7 @@ import { import { Fieldset } from "components/DeploySettingsLayout/Fieldset"; import { Stack } from "components/Stack/Stack"; import { getFormHelpers } from "utils/formUtils"; +import colors from "theme/tailwind"; export type AppearanceSettingsPageViewProps = { appearance: UpdateAppearanceConfig; @@ -29,11 +30,12 @@ export type AppearanceSettingsPageViewProps = { ) => void; }; +const fallbackBgColor = colors.neutral[500]; + export const AppearanceSettingsPageView: FC< AppearanceSettingsPageViewProps > = ({ appearance, isEntitled, onSaveAppearance }) => { const theme = useTheme(); - const fallbackBgColor = theme.colors.blue[7]; const applicationNameForm = useFormik<{ application_name: string; diff --git a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx index 2f1ecffeeb1ac..af8110c7ad5b9 100644 --- a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx +++ b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx @@ -39,7 +39,6 @@ export const VersionRow: FC = ({ @@ -127,16 +126,6 @@ export const VersionRow: FC = ({ }; const styles = { - row: (theme) => ({ - "&:hover $promoteButton": { - color: theme.palette.text.primary, - borderColor: theme.colors.gray[11], - "&:hover": { - borderColor: theme.palette.text.primary, - }, - }, - }), - promoteButton: (theme) => ({ color: theme.palette.text.secondary, transition: "none", diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.stories.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.stories.tsx index 93c13c55cd794..07aecdb173ae9 100644 --- a/site/src/pages/TemplatesPage/TemplatesPageView.stories.tsx +++ b/site/src/pages/TemplatesPage/TemplatesPageView.stories.tsx @@ -1,3 +1,5 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { chromaticWithTablet } from "testHelpers/chromatic"; import { mockApiError, MockTemplate, @@ -5,10 +7,10 @@ import { MockTemplateExample2, } from "testHelpers/entities"; import { TemplatesPageView } from "./TemplatesPageView"; -import type { Meta, StoryObj } from "@storybook/react"; const meta: Meta = { title: "pages/TemplatesPage", + parameters: { chromatic: chromaticWithTablet }, component: TemplatesPageView, }; @@ -65,15 +67,6 @@ export const WithTemplates: Story = { }, }; -export const WithTemplatesSmallViewPort: Story = { - args: { - ...WithTemplates.args, - }, - parameters: { - chromatic: { viewports: [600] }, - }, -}; - export const EmptyCanCreate: Story = { args: { canCreateTemplates: true, diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.tsx index e9aef584fc0fa..7004e3d86c934 100644 --- a/site/src/pages/TemplatesPage/TemplatesPageView.tsx +++ b/site/src/pages/TemplatesPage/TemplatesPageView.tsx @@ -42,7 +42,7 @@ import { ErrorAlert } from "components/Alert/ErrorAlert"; import { docs } from "utils/docs"; import Skeleton from "@mui/material/Skeleton"; import { AvatarDataSkeleton } from "components/AvatarData/AvatarDataSkeleton"; -import { Pill } from "components/Pill/Pill"; +import { DeprecatedBadge } from "components/Badges/Badges"; export const Language = { developerCount: (activeCount: number): string => { @@ -122,7 +122,7 @@ const TemplateRow: FC = ({ template }) => { {template.deprecated ? ( - + ) : (