site: new dark theme (#10331)

This commit is contained in:
Kayla Washburn
2023-11-15 16:39:26 -05:00
committed by GitHub
parent bd17290ff4
commit 8ddc8b3447
50 changed files with 338 additions and 559 deletions

View File

@ -7,14 +7,21 @@ import { ThemeProvider as EmotionThemeProvider } from "@emotion/react";
import { withRouter } from "storybook-addon-react-router-v6";
import { HelmetProvider } from "react-helmet-async";
import { dark } from "theme/mui";
import { dark as experimental } from "theme/experimental";
import colors from "theme/tailwind";
import "theme/globalFonts";
import { QueryClient, QueryClientProvider } from "react-query";
const theme = {
...dark,
experimental,
};
export const decorators = [
(Story) => (
<StyledEngineProvider injectFirst>
<MuiThemeProvider theme={dark}>
<EmotionThemeProvider theme={dark}>
<MuiThemeProvider theme={theme}>
<EmotionThemeProvider theme={theme}>
<CssBaseline />
<Story />
</EmotionThemeProvider>
@ -39,6 +46,19 @@ export const decorators = [
];
export const parameters = {
backgrounds: {
default: "dark",
values: [
{
name: "dark",
value: colors.gray[950],
},
{
name: "light",
value: colors.gray[50],
},
],
},
actions: {
argTypesRegex: "^(on|handler)[A-Z].*",
},

View File

@ -1,7 +1,7 @@
import CssBaseline from "@mui/material/CssBaseline";
import { QueryClient, QueryClientProvider } from "react-query";
import { AuthProvider } from "components/AuthProvider/AuthProvider";
import { FC, PropsWithChildren, ReactNode } from "react";
import type { FC, PropsWithChildren, ReactNode } from "react";
import { HelmetProvider } from "react-helmet-async";
import { AppRouter } from "./AppRouter";
import { ErrorBoundary } from "./components/ErrorBoundary/ErrorBoundary";

View File

@ -10,62 +10,50 @@ const meta: Meta<typeof Avatar> = {
export default meta;
type Story = StoryObj<typeof Avatar>;
export const Letter: Story = {
export const WithLetter: Story = {
args: {
children: "Coder",
},
};
export const LetterXL = {
export const WithLetterXL = {
args: {
children: "Coder",
size: "xl",
},
};
export const LetterDarken = {
args: {
children: "Coder",
colorScheme: "darken",
},
};
export const Image = {
export const WithImage = {
args: {
src: "https://avatars.githubusercontent.com/u/95932066?s=200&v=4",
},
};
export const ImageXL = {
export const WithImageXL = {
args: {
src: "https://avatars.githubusercontent.com/u/95932066?s=200&v=4",
size: "xl",
},
};
export const MuiIcon = {
export const WithMuiIcon = {
args: {
background: true,
children: <PauseIcon />,
},
};
export const MuiIconDarken = {
args: {
children: <PauseIcon />,
colorScheme: "darken",
},
};
export const MuiIconXL = {
export const WithMuiIconXL = {
args: {
background: true,
children: <PauseIcon />,
size: "xl",
},
};
export const AvatarIconDarken = {
export const WithAvatarIcon = {
args: {
background: true,
children: <AvatarIcon src="/icon/database.svg" alt="Database" />,
colorScheme: "darken",
},
};

View File

@ -8,7 +8,7 @@ import { visuallyHidden } from "@mui/utils";
export type AvatarProps = MuiAvatarProps & {
size?: "xs" | "sm" | "md" | "xl";
colorScheme?: "light" | "darken";
background?: boolean;
fitImage?: boolean;
};
@ -33,14 +33,6 @@ const sizeStyles = {
},
} satisfies Record<string, Interpolation<Theme>>;
const colorStyles = {
light: {},
darken: (theme) => ({
background: theme.palette.divider,
color: theme.palette.text.primary,
}),
} satisfies Record<string, Interpolation<Theme>>;
const fitImageStyles = css`
& .MuiAvatar-img {
object-fit: contain;
@ -49,18 +41,24 @@ const fitImageStyles = css`
export const Avatar: FC<AvatarProps> = ({
size = "md",
colorScheme = "light",
fitImage,
children,
background,
...muiProps
}) => {
const fromName = !muiProps.src && typeof children === "string";
return (
<MuiAvatar
{...muiProps}
css={[
sizeStyles[size],
colorStyles[colorScheme],
fitImage && fitImageStyles,
(theme) => ({
background:
background || fromName ? theme.palette.divider : undefined,
color: theme.palette.text.primary,
}),
]}
>
{typeof children === "string" ? firstLetter(children) : children}

View File

@ -1,12 +1,12 @@
import { type ReactNode } from "react";
import { Avatar } from "components/Avatar/Avatar";
import { type CSSObject, useTheme } from "@emotion/react";
import { colors } from "theme/colors";
type AvatarCardProps = {
header: string;
imgUrl: string;
altText: string;
background?: boolean;
subtitle?: ReactNode;
maxWidth?: number | "none";
@ -16,6 +16,7 @@ export function AvatarCard({
header,
imgUrl,
altText,
background,
subtitle,
maxWidth = "none",
}: AvatarCardProps) {
@ -71,12 +72,7 @@ export function AvatarCard({
)}
</div>
<Avatar
src={imgUrl}
alt={altText}
size="md"
css={{ backgroundColor: colors.gray[7] }}
>
<Avatar background={background} src={imgUrl} alt={altText} size="md">
{header}
</Avatar>
</div>

View File

@ -0,0 +1,38 @@
import type { Meta, StoryObj } from "@storybook/react";
import {
Badges,
AlphaBadge,
EnabledBadge,
EntitledBadge,
EnterpriseBadge,
} from "./Badges";
const meta: Meta<typeof Badges> = {
title: "components/Badges",
component: Badges,
args: {},
};
export default meta;
type Story = StoryObj<typeof Badges>;
export const Enabled: Story = {
args: {
children: <EnabledBadge />,
},
};
export const Entitled: Story = {
args: {
children: <EntitledBadge />,
},
};
export const Enterprise: Story = {
args: {
children: <EnterpriseBadge />,
},
};
export const Alpha: Story = {
args: {
children: <AlphaBadge />,
},
};

View File

@ -2,7 +2,7 @@ import type { PropsWithChildren, FC } from "react";
import Tooltip from "@mui/material/Tooltip";
import { type Interpolation, type Theme } from "@emotion/react";
import { Stack } from "components/Stack/Stack";
import { colors } from "theme/colors";
import colors from "theme/tailwind";
const styles = {
badge: {
@ -20,16 +20,16 @@ const styles = {
},
enabledBadge: (theme) => ({
border: `1px solid ${theme.palette.success.light}`,
backgroundColor: theme.palette.success.dark,
border: `1px solid ${theme.experimental.roles.success.outline}`,
backgroundColor: theme.experimental.roles.success.background,
}),
errorBadge: (theme) => ({
border: `1px solid ${theme.palette.error.light}`,
backgroundColor: theme.palette.error.dark,
border: `1px solid ${theme.experimental.roles.error.outline}`,
backgroundColor: theme.experimental.roles.error.background,
}),
warnBadge: (theme) => ({
border: `1px solid ${theme.palette.warning.light}`,
backgroundColor: theme.palette.warning.dark,
border: `1px solid ${theme.experimental.roles.warning.outline}`,
backgroundColor: theme.experimental.roles.warning.background,
}),
} satisfies Record<string, Interpolation<Theme>>;
@ -111,9 +111,9 @@ export const AlphaBadge: FC = () => {
css={[
styles.badge,
{
border: `1px solid ${colors.violet[10]}`,
backgroundColor: colors.violet[14],
color: colors.violet[1],
border: `1px solid ${colors.violet[600]}`,
backgroundColor: colors.violet[950],
color: colors.violet[50],
},
]}
>

View File

@ -46,7 +46,7 @@ export const BuildAvatar: FC<BuildAvatarProps> = ({ build, size }) => {
}}
badgeContent={<div></div>}
>
<Avatar size={size} colorScheme="darken">
<Avatar background size={size}>
<BuildIcon transition={build.transition} />
</Avatar>
</StyledBadge>

View File

@ -48,15 +48,13 @@ export const LicenseBannerView: React.FC<LicenseBannerViewProps> = ({
display: flex;
align-items: center;
padding: 12px;
background-color: ${type === "error"
? colors.red[12]
: theme.palette.warning.main};
background-color: ${type === "error" ? colors.red[10] : colors.orange[10]};
`;
if (messages.length === 1) {
return (
<div css={containerStyles}>
<Pill text={Language.licenseIssue} type={type} lightBorder />
<Pill text={Language.licenseIssue} type={type} />
<div css={styles.leftContent}>
<span>{messages[0]}</span>
&nbsp;
@ -70,11 +68,7 @@ export const LicenseBannerView: React.FC<LicenseBannerViewProps> = ({
return (
<div css={containerStyles}>
<Pill
text={Language.licenseIssues(messages.length)}
type={type}
lightBorder
/>
<Pill text={Language.licenseIssues(messages.length)} type={type} />
<div css={styles.leftContent}>
<div>
{Language.exceeded}

View File

@ -1,8 +1,7 @@
import { Pill } from "components/Pill/Pill";
import ReactMarkdown from "react-markdown";
import { colors } from "theme/colors";
import { useTheme } from "@mui/system";
import { css } from "@emotion/react";
import { css, useTheme } from "@emotion/react";
import { readableForegroundColor } from "utils/colors";
export interface ServiceBannerViewProps {
@ -43,7 +42,7 @@ export const ServiceBannerView: React.FC<ServiceBannerViewProps> = ({
}
`}
>
{isPreview && <Pill text="Preview" type="info" lightBorder />}
{isPreview && <Pill text="Preview" type="info" />}
<div
css={css`
margin-right: auto;

View File

@ -3,20 +3,12 @@ import CheckCircleOutlined from "@mui/icons-material/CheckCircleOutlined";
import { css, useTheme } from "@emotion/react";
import type { PropsWithChildren, FC } from "react";
import { MONOSPACE_FONT_FAMILY } from "theme/constants";
import { DisabledBadge, EnabledBadge } from "./Badges";
import { DisabledBadge, EnabledBadge } from "../Badges/Badges";
export const OptionName: FC<PropsWithChildren> = (props) => {
const { children } = props;
return (
<span
css={{
display: "block",
}}
>
{children}
</span>
);
return <span css={{ display: "block" }}>{children}</span>;
};
export const OptionDescription: FC<PropsWithChildren> = (props) => {

View File

@ -12,8 +12,8 @@ import { Stack } from "components/Stack/Stack";
import type { ElementType, FC, PropsWithChildren, ReactNode } from "react";
import { NavLink } from "react-router-dom";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { useTheme } from "@mui/system";
import { css } from "@emotion/css";
import { useTheme } from "@emotion/react";
const SidebarNavItem: FC<
PropsWithChildren<{ href: string; icon: ReactNode }>
@ -74,11 +74,7 @@ export const Sidebar: React.FC = () => {
const dashboard = useDashboard();
return (
<nav
css={{
width: 245,
}}
>
<nav css={{ width: 245 }}>
<SidebarNavItem
href="general"
icon={<SidebarNavItemIcon icon={LaunchOutlined} />}

View File

@ -97,14 +97,14 @@ const styles = {
}),
successButton: (theme) => ({
"&.MuiButton-contained": {
backgroundColor: theme.palette.success.main,
backgroundColor: theme.palette.success.dark,
"&:not(.MuiLoadingButton-loading)": {
color: theme.palette.primary.contrastText,
},
"&:hover": {
backgroundColor: theme.palette.success.dark,
backgroundColor: theme.palette.success.main,
"@media (hover: none)": {
backgroundColor: "transparent",

View File

@ -6,7 +6,7 @@ import {
type PropsWithChildren,
useContext,
} from "react";
import { AlphaBadge } from "components/DeploySettingsLayout/Badges";
import { AlphaBadge } from "components/Badges/Badges";
import { Stack } from "components/Stack/Stack";
import {
FormFooter as BaseFormFooter,

View File

@ -37,7 +37,9 @@ export const GroupAvatar: FC<GroupAvatarProps> = ({ name, avatarURL }) => {
}}
badgeContent={<Group />}
>
<Avatar src={avatarURL}>{name}</Avatar>
<Avatar src={avatarURL} background>
{name}
</Avatar>
</StyledBadge>
);
};

View File

@ -15,6 +15,14 @@ export default meta;
type Story = StoryObj<typeof InfoTooltip>;
export const Example: Story = {};
export const Notice: Story = {
args: {
type: "notice",
message: "Unfortunately, there's a radio connected to my brain",
},
};
export const Warning: Story = {
args: {
type: "warning",

View File

@ -6,10 +6,11 @@ import {
} from "components/HelpTooltip/HelpTooltip";
import InfoIcon from "@mui/icons-material/InfoOutlined";
import { css } from "@emotion/css";
import { colors } from "theme/colors";
import { useTheme } from "@emotion/react";
interface InfoTooltipProps {
type?: "warning" | "info";
// TODO: use a `ThemeRole` type or something
type?: "warning" | "notice" | "info";
title: ReactNode;
message: ReactNode;
}
@ -17,12 +18,15 @@ interface InfoTooltipProps {
export const InfoTooltip: FC<InfoTooltipProps> = (props) => {
const { title, message, type = "info" } = props;
const theme = useTheme();
const iconColor = theme.experimental.roles[type].outline;
return (
<HelpTooltip
size="small"
icon={InfoIcon}
iconClassName={css`
color: ${type === "info" ? colors.blue[5] : colors.yellow[5]};
color: ${iconColor};
`}
buttonClassName={css`
opacity: 1;

View File

@ -11,7 +11,7 @@ import { type FC, memo } from "react";
import ReactMarkdown, { type Options } from "react-markdown";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import gfm from "remark-gfm";
import { colors } from "theme/colors";
import colors from "theme/tailwind";
import { darcula } from "react-syntax-highlighter/dist/cjs/styles/prism";
interface MarkdownProps {
@ -227,7 +227,7 @@ const markdownStyles: Interpolation<Theme> = (theme: Theme) => ({
},
"& .key, & .property, & .inserted, .keyword": {
color: colors.turquoise[7],
color: colors.teal[300],
},
"& .deleted": {

View File

@ -1,8 +1,8 @@
import Box from "@mui/material/Box";
import Chip from "@mui/material/Chip";
import Typography from "@mui/material/Typography";
import { type FC, type ReactNode } from "react";
import { type Interpolation, type Theme } from "@emotion/react";
import { EnterpriseBadge } from "components/Badges/Badges";
import { Stack } from "components/Stack/Stack";
export interface PaywallProps {
@ -21,12 +21,7 @@ export const Paywall: FC<React.PropsWithChildren<PaywallProps>> = (props) => {
<Typography variant="h5" css={styles.title}>
{message}
</Typography>
<Chip
css={styles.enterpriseChip}
label="Enterprise"
size="small"
color="primary"
/>
<EnterpriseBadge />
</Stack>
{description && (

View File

@ -9,38 +9,16 @@ const meta: Meta<typeof Pill> = {
export default meta;
type Story = StoryObj<typeof Pill>;
export const Primary: Story = {
export const Default: Story = {
args: {
text: "Primary",
type: "primary",
text: "Default",
},
};
export const Secondary: Story = {
export const Danger: Story = {
args: {
text: "Secondary",
type: "secondary",
},
};
export const Success: Story = {
args: {
text: "Success",
type: "success",
},
};
export const Info: Story = {
args: {
text: "Information",
type: "info",
},
};
export const Warning: Story = {
args: {
text: "Warning",
type: "warning",
text: "Danger",
type: "danger",
},
};
@ -51,16 +29,37 @@ export const Error: Story = {
},
};
export const Default: Story = {
args: {
text: "Default",
},
};
export const WarningLight: Story = {
export const Warning: Story = {
args: {
text: "Warning",
type: "warning",
lightBorder: true,
},
};
export const Notice: Story = {
args: {
text: "Notice",
type: "notice",
},
};
export const Info: Story = {
args: {
text: "Information",
type: "info",
},
};
export const Success: Story = {
args: {
text: "Success",
type: "success",
},
};
export const Active: Story = {
args: {
text: "Active",
type: "active",
},
};

View File

@ -1,65 +1,43 @@
import { type FC, type ReactNode, useMemo, forwardRef } from "react";
import { css, type Interpolation, type Theme } from "@emotion/react";
import { colors } from "theme/colors";
import type { ThemeRole } from "theme/experimental";
export type PillType =
| "primary"
| "secondary"
| "error"
| "warning"
| "info"
| "success"
| "neutral";
export type PillType = ThemeRole | keyof typeof themeOverrides;
export interface PillProps {
className?: string;
icon?: ReactNode;
text: ReactNode;
type?: PillType;
lightBorder?: boolean;
title?: string;
}
const themeOverrides = {
primary: (lightBorder) => ({
backgroundColor: colors.blue[13],
borderColor: lightBorder ? colors.blue[5] : colors.blue[7],
}),
secondary: (lightBorder) => ({
backgroundColor: colors.indigo[13],
borderColor: lightBorder ? colors.indigo[6] : colors.indigo[8],
}),
neutral: (lightBorder) => ({
neutral: {
backgroundColor: colors.gray[13],
borderColor: lightBorder ? colors.gray[6] : colors.gray[8],
}),
} satisfies Record<string, (lightBorder?: boolean) => Interpolation<Theme>>;
borderColor: colors.gray[6],
},
} satisfies Record<string, Interpolation<Theme>>;
const themeStyles =
(type: PillType, lightBorder?: boolean) => (theme: Theme) => {
const palette = theme.palette[type];
return {
backgroundColor: palette.dark,
borderColor: lightBorder ? palette.light : palette.main,
};
const themeStyles = (type: ThemeRole) => (theme: Theme) => {
const palette = theme.experimental.roles[type];
return {
backgroundColor: palette.background,
borderColor: palette.outline,
};
};
export const Pill: FC<PillProps> = forwardRef<HTMLDivElement, PillProps>(
(props, ref) => {
const {
lightBorder,
icon,
text = null,
type = "neutral",
...attrs
} = props;
const { icon, text = null, type = "neutral", ...attrs } = props;
const typeStyles = useMemo(() => {
if (type in themeOverrides) {
return themeOverrides[type as keyof typeof themeOverrides](lightBorder);
return themeOverrides[type as keyof typeof themeOverrides];
}
return themeStyles(type, lightBorder);
}, [type, lightBorder]);
return themeStyles(type as ThemeRole);
}, [type]);
return (
<div

View File

@ -39,7 +39,7 @@ export const ResourceAvatar: FC<ResourceAvatarProps> = ({ resource }) => {
: getIconPathResource(resource.type);
return (
<Avatar colorScheme="darken">
<Avatar background>
<AvatarIcon src={avatarSrc} alt={resource.name} />
</Avatar>
);

View File

@ -9,7 +9,6 @@ import { type FC } from "react";
import { TemplateVersionParameter } from "api/typesGenerated";
import { MemoizedMarkdown } from "components/Markdown/Markdown";
import { Stack } from "components/Stack/Stack";
import { colors } from "theme/colors";
import { MultiTextField } from "./MultiTextField";
const isBoolean = (parameter: TemplateVersionParameter) => {
@ -43,11 +42,6 @@ const styles = {
fontSize: 14,
},
}),
labelImmutable: {
marginTop: 4,
marginBottom: 4,
color: colors.yellow[7],
},
textField: {
".small & .MuiInputBase-root": {
height: 36,

View File

@ -1,9 +1,7 @@
import { useTheme } from "@mui/styles";
import { useMonaco } from "@monaco-editor/react";
import { useEffect, useState } from "react";
import { hslToHex } from "utils/colors";
import { editor } from "monaco-editor";
import { Theme } from "@mui/material/styles";
import { type Theme, useTheme } from "@emotion/react";
// Theme based on https://github.com/brijeshb42/monaco-themes/blob/master/themes/Dracula.json
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- The theme is not typed
@ -208,12 +206,11 @@ export const coderTheme = (theme: Theme): editor.IStandaloneThemeData => ({
},
],
colors: {
"editor.foreground": hslToHex(theme.palette.text.primary),
"editor.background": hslToHex(theme.palette.background.paper),
"editor.selectionBackground": hslToHex(theme.palette.action.hover),
"editor.lineHighlightBackground": hslToHex(
theme.palette.background.paperLight,
),
"editor.foreground": theme.palette.text.primary,
"editor.background": theme.palette.background.paper,
"editor.selectionBackground": theme.palette.action.hover,
"editor.lineHighlightBackground": theme.palette.background.paperLight,
"editorCursor.foreground": "#f8f8f0",
"editorWhitespace.foreground": "#3B3A32",
"editorIndentGuide.activeBackground": "#9D550FB0",
@ -224,7 +221,7 @@ export const coderTheme = (theme: Theme): editor.IStandaloneThemeData => ({
export const useCoderTheme = (): { isLoading: boolean; name: string } => {
const [isLoading, setIsLoading] = useState(true);
const monaco = useMonaco();
const theme = useTheme<Theme>();
const theme = useTheme();
const name = "coder";
useEffect(() => {

View File

@ -3,7 +3,7 @@ import { NavLink, NavLinkProps } from "react-router-dom";
import { combineClasses } from "utils/combineClasses";
import { Margins } from "components/Margins/Margins";
import { css } from "@emotion/css";
import { useTheme } from "@mui/material/styles";
import { useTheme } from "@emotion/react";
export const Tabs = ({ children }: { children: ReactNode }) => {
return (

View File

@ -1,5 +1,5 @@
import { Avatar, AvatarProps } from "components/Avatar/Avatar";
import { FC } from "react";
import { Avatar, type AvatarProps } from "components/Avatar/Avatar";
import { type FC } from "react";
export type UserAvatarProps = {
username: string;
@ -12,7 +12,7 @@ export const UserAvatar: FC<UserAvatarProps> = ({
...avatarProps
}) => {
return (
<Avatar title={username} src={avatarURL} {...avatarProps}>
<Avatar background title={username} src={avatarURL} {...avatarProps}>
{username}
</Avatar>
);

View File

@ -1,11 +1,12 @@
import RefreshIcon from "@mui/icons-material/Refresh";
import { type FC } from "react";
import InfoIcon from "@mui/icons-material/InfoOutlined";
import { useQuery } from "react-query";
import Box from "@mui/material/Box";
import Skeleton from "@mui/material/Skeleton";
import Link from "@mui/material/Link";
import { type FC } from "react";
import { useQuery } from "react-query";
import { css } from "@emotion/css";
import { useTheme } from "@emotion/react";
import { templateVersion } from "api/queries/templates";
import {
HelpTooltip,
@ -14,7 +15,6 @@ import {
HelpTooltipText,
HelpTooltipTitle,
} from "components/HelpTooltip/HelpTooltip";
import { colors } from "theme/colors";
export const Language = {
outdatedLabel: "Outdated",
@ -37,13 +37,14 @@ export const WorkspaceOutdatedTooltip: FC<TooltipProps> = ({
templateName,
}) => {
const { data: activeVersion } = useQuery(templateVersion(latestVersionId));
const theme = useTheme();
return (
<HelpTooltip
size="small"
icon={InfoIcon}
iconClassName={css`
color: ${colors.yellow[5]};
color: ${theme.experimental.roles.notice.outline};
`}
buttonClassName={css`
opacity: 1;

View File

@ -73,7 +73,14 @@ export const WorkspaceStatusText: FC<
role="status"
data-testid="build-status"
className={className}
css={[styles.root, styles[`type-${type}`]]}
css={[
styles.root,
(theme) => ({
color: type
? theme.experimental.roles[type].fill
: theme.experimental.l1.text,
}),
]}
>
{text}
</span>

View File

@ -1,7 +1,7 @@
import { type Interpolation, type Theme } from "@emotion/react";
import { type FC } from "react";
import type { AuditLog } from "api/typesGenerated";
import { colors } from "theme/colors";
import colors from "theme/tailwind";
import { MONOSPACE_FONT_FAMILY } from "theme/constants";
const getDiffValue = (value: unknown): string => {
@ -79,10 +79,10 @@ const styles = {
overflowWrap: "anywhere",
},
diffOld: (theme) => ({
backgroundColor: theme.palette.error.dark,
color: theme.palette.error.contrastText,
}),
diffOld: {
backgroundColor: colors.red[950],
color: colors.red[50],
},
diffRow: {
display: "flex",
@ -103,10 +103,10 @@ const styles = {
flexShrink: 0,
}),
diffNew: (theme) => ({
backgroundColor: theme.palette.success.dark,
color: theme.palette.success.contrastText,
}),
diffNew: {
backgroundColor: colors.green[950],
color: colors.green[50],
},
diffValue: {
padding: 1,
@ -114,10 +114,10 @@ const styles = {
},
diffValueOld: {
backgroundColor: colors.red[12],
backgroundColor: colors.red[800],
},
diffValueNew: {
backgroundColor: colors.green[12],
backgroundColor: colors.green[800],
},
} satisfies Record<string, Interpolation<Theme>>;

View File

@ -10,7 +10,7 @@ export const AuditPaywall: FC = () => {
return (
<Paywall
message="Audit logs"
description="Audit Logs allows Auditors to monitor user operations in their deployment. To use this feature, you have to upgrade your account."
description="Audit Logs allows Auditors to monitor user operations in their deployment. To use this feature, you need an Enterprise license."
cta={
<Stack direction="row" alignItems="center">
<Link href={docs("/admin/upgrade")} target="_blank" rel="noreferrer">

View File

@ -1,26 +1,25 @@
import InputAdornment from "@mui/material/InputAdornment";
import Button from "@mui/material/Button";
import FormControlLabel from "@mui/material/FormControlLabel";
import Switch from "@mui/material/Switch";
import TextField from "@mui/material/TextField";
import Link from "@mui/material/Link";
import { useTheme } from "@emotion/react";
import { useState } from "react";
import { BlockPicker } from "react-color";
import { useFormik } from "formik";
import type { UpdateAppearanceConfig } from "api/typesGenerated";
import { Header } from "components/DeploySettingsLayout/Header";
import {
Badges,
DisabledBadge,
EnterpriseBadge,
EntitledBadge,
} from "components/DeploySettingsLayout/Badges";
import InputAdornment from "@mui/material/InputAdornment";
} from "components/Badges/Badges";
import { Fieldset } from "components/DeploySettingsLayout/Fieldset";
import { getFormHelpers } from "utils/formUtils";
import Button from "@mui/material/Button";
import FormControlLabel from "@mui/material/FormControlLabel";
import { BlockPicker } from "react-color";
import Switch from "@mui/material/Switch";
import TextField from "@mui/material/TextField";
import type { UpdateAppearanceConfig } from "api/typesGenerated";
import { Stack } from "components/Stack/Stack";
import { useFormik } from "formik";
import Link from "@mui/material/Link";
import { getFormHelpers } from "utils/formUtils";
import { colors } from "theme/colors";
import { hslToHex } from "utils/colors";
import { useTheme } from "@emotion/react";
export type AppearanceSettingsPageViewProps = {
appearance: UpdateAppearanceConfig;
@ -31,7 +30,7 @@ export type AppearanceSettingsPageViewProps = {
) => void;
};
const fallbackBgColor = hslToHex(colors.blue[7]);
const fallbackBgColor = colors.blue[7];
export const AppearanceSettingsPageView = ({
appearance,

View File

@ -7,7 +7,7 @@ import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import type { DeploymentValues, ExternalAuthConfig } from "api/typesGenerated";
import { Alert } from "components/Alert/Alert";
import { EnterpriseBadge } from "components/DeploySettingsLayout/Badges";
import { EnterpriseBadge } from "components/Badges/Badges";
import { Header } from "components/DeploySettingsLayout/Header";
import { docs } from "utils/docs";

View File

@ -1,6 +1,5 @@
import { type Interpolation, type Theme } from "@emotion/react";
import { type Interpolation, type Theme, useTheme } from "@emotion/react";
import Button from "@mui/material/Button";
import { useTheme } from "@mui/styles";
import Skeleton from "@mui/material/Skeleton";
import AddIcon from "@mui/icons-material/AddOutlined";
import RefreshIcon from "@mui/icons-material/Refresh";

View File

@ -1,9 +1,5 @@
import { ClibaseOption } from "api/typesGenerated";
import {
Badges,
EnabledBadge,
DisabledBadge,
} from "components/DeploySettingsLayout/Badges";
import type { ClibaseOption } from "api/typesGenerated";
import { Badges, EnabledBadge, DisabledBadge } from "components/Badges/Badges";
import { Header } from "components/DeploySettingsLayout/Header";
import OptionsTable from "components/DeploySettingsLayout/OptionsTable";
import { Stack } from "components/Stack/Stack";

View File

@ -1,10 +1,10 @@
import { ClibaseOption } from "api/typesGenerated";
import type { ClibaseOption } from "api/typesGenerated";
import {
Badges,
DisabledBadge,
EnabledBadge,
EnterpriseBadge,
} from "components/DeploySettingsLayout/Badges";
} from "components/Badges/Badges";
import { Header } from "components/DeploySettingsLayout/Header";
import OptionsTable from "components/DeploySettingsLayout/OptionsTable";
import { Stack } from "components/Stack/Stack";

View File

@ -1,10 +1,10 @@
import { ClibaseOption } from "api/typesGenerated";
import type { ClibaseOption } from "api/typesGenerated";
import {
Badges,
DisabledBadge,
EnabledBadge,
EnterpriseBadge,
} from "components/DeploySettingsLayout/Badges";
} from "components/Badges/Badges";
import { Header } from "components/DeploySettingsLayout/Header";
import OptionsTable from "components/DeploySettingsLayout/OptionsTable";
import { Stack } from "components/Stack/Stack";

View File

@ -1,9 +1,5 @@
import { ClibaseOption } from "api/typesGenerated";
import {
Badges,
DisabledBadge,
EnabledBadge,
} from "components/DeploySettingsLayout/Badges";
import type { ClibaseOption } from "api/typesGenerated";
import { Badges, DisabledBadge, EnabledBadge } from "components/Badges/Badges";
import { Header } from "components/DeploySettingsLayout/Header";
import OptionsTable from "components/DeploySettingsLayout/OptionsTable";
import { Stack } from "components/Stack/Stack";

View File

@ -86,11 +86,7 @@ const ExternalAuthPageView: FC<ExternalAuthPageViewProps> = ({
target="_blank"
rel="noreferrer"
>
<Avatar
size="sm"
src={install.account.avatar_url}
colorScheme="darken"
>
<Avatar size="sm" src={install.account.avatar_url}>
{install.account.login}
</Avatar>
</Link>

View File

@ -1,6 +1,6 @@
import LinearProgress from "@mui/material/LinearProgress";
import Box from "@mui/material/Box";
import { styled, useTheme } from "@mui/material/styles";
import { styled } from "@mui/material/styles";
import { BoxProps } from "@mui/system";
import { useQuery } from "react-query";
import {
@ -20,7 +20,7 @@ import { colors } from "theme/colors";
import { Helmet } from "react-helmet-async";
import { getTemplatePageTitle } from "../utils";
import { Loader } from "components/Loader/Loader";
import {
import type {
Entitlements,
Template,
TemplateAppUsage,
@ -30,7 +30,8 @@ import {
UserActivityInsightsResponse,
UserLatencyInsightsResponse,
} from "api/typesGenerated";
import { ComponentProps, ReactNode } from "react";
import { useTheme } from "@emotion/react";
import { type ComponentProps, type ReactNode } from "react";
import { subDays, addWeeks, format } from "date-fns";
import "react-date-range/dist/styles.css";
import "react-date-range/dist/theme/default.css";

View File

@ -80,13 +80,13 @@ export const VersionRow: React.FC<VersionRowProps> = ({
{isLatest && <Pill text="Newest" type="info" />}
{jobStatus === "pending" && (
<Pill text={<>Pending&hellip;</>} type="warning" lightBorder />
<Pill text={<>Pending&hellip;</>} type="warning" />
)}
{jobStatus === "running" && (
<Pill text={<>Building&hellip;</>} type="warning" lightBorder />
<Pill text={<>Building&hellip;</>} type="warning" />
)}
{(jobStatus === "canceling" || jobStatus === "canceled") && (
<Pill text="Canceled" type="neutral" lightBorder />
<Pill text="Canceled" type="neutral" />
)}
{jobStatus === "failed" && <Pill text="Failed" type="error" />}

View File

@ -1,9 +1,8 @@
import { useTheme } from "@mui/styles";
import { useTheme } from "@emotion/react";
import Editor, { loader } from "@monaco-editor/react";
import * as monaco from "monaco-editor";
import { FC, useLayoutEffect, useMemo, useState } from "react";
import { MONOSPACE_FONT_FAMILY } from "theme/constants";
import { hslToHex } from "utils/colors";
import type { editor } from "monaco-editor";
loader.config({ monaco });
@ -124,8 +123,8 @@ export const MonacoEditor: FC<{
},
],
colors: {
"editor.foreground": hslToHex(theme.palette.text.primary),
"editor.background": hslToHex(theme.palette.background.default),
"editor.foreground": theme.palette.text.primary,
"editor.background": theme.palette.background.default,
},
});
editor.updateOptions({

View File

@ -39,9 +39,9 @@ export const getStatus = (
};
case "pending":
return {
type: "info",
text: "Pending",
icon: <LoadingIcon />,
type: "info",
};
case "canceling":
return {

View File

@ -51,6 +51,7 @@ export function AccountUserGroups({
{groups.map((group) => (
<Grid item key={group.id} xs={1}>
<AvatarCard
background
imgUrl={group.avatar_url}
altText={group.display_name || group.name}
header={group.display_name || group.name}

View File

@ -1,16 +1,16 @@
import { Region, WorkspaceProxy } from "api/typesGenerated";
import type { Region, WorkspaceProxy } from "api/typesGenerated";
import { AvatarData } from "components/AvatarData/AvatarData";
import { Avatar } from "components/Avatar/Avatar";
import TableCell from "@mui/material/TableCell";
import TableRow from "@mui/material/TableRow";
import { FC, ReactNode } from "react";
import type { FC, ReactNode } from "react";
import {
HealthyBadge,
NotHealthyBadge,
NotReachableBadge,
NotRegisteredBadge,
} from "components/DeploySettingsLayout/Badges";
import { ProxyLatencyReport } from "contexts/useProxyLatency";
} from "components/Badges/Badges";
import type { ProxyLatencyReport } from "contexts/useProxyLatency";
import { getLatencyColor } from "utils/latency";
import Box from "@mui/material/Box";

View File

@ -15,7 +15,7 @@ import {
TableLoaderSkeleton,
TableRowSkeleton,
} from "components/TableLoader/TableLoader";
import { EnterpriseBadge } from "components/DeploySettingsLayout/Badges";
import { EnterpriseBadge } from "components/Badges/Badges";
import HideSourceOutlined from "@mui/icons-material/HideSourceOutlined";
import KeyOutlined from "@mui/icons-material/KeyOutlined";
import GitHub from "@mui/icons-material/GitHub";

View File

@ -8,12 +8,7 @@ import {
import ScheduleIcon from "@mui/icons-material/TimerOutlined";
import type { Workspace } from "api/typesGenerated";
import { Stack } from "components/Stack/Stack";
import {
type FC,
type ComponentType,
type PropsWithChildren,
type ReactNode,
} from "react";
import { type FC, type PropsWithChildren, type ReactNode } from "react";
import { Link, NavLink } from "react-router-dom";
import { combineClasses } from "utils/combineClasses";
import GeneralIcon from "@mui/icons-material/SettingsOutlined";
@ -74,13 +69,7 @@ const SidebarNavItem: FC<
);
};
const SidebarNavItemIcon: FC<{
icon: ComponentType<{ className?: string }>;
}> = ({ icon: Icon }) => {
return <Icon css={{ width: 16, height: 16 }} />;
};
export const Sidebar: React.FC<{ username: string; workspace: Workspace }> = ({
export const Sidebar: FC<{ username: string; workspace: Workspace }> = ({
username,
workspace,
}) => {
@ -98,18 +87,21 @@ export const Sidebar: React.FC<{ username: string; workspace: Workspace }> = ({
</Stack>
</Stack>
<SidebarNavItem href="" icon={<SidebarNavItemIcon icon={GeneralIcon} />}>
<SidebarNavItem
href=""
icon={<GeneralIcon css={styles.sidebarItemIcon} />}
>
General
</SidebarNavItem>
<SidebarNavItem
href="parameters"
icon={<SidebarNavItemIcon icon={ParameterIcon} />}
icon={<ParameterIcon css={styles.sidebarItemIcon} />}
>
Parameters
</SidebarNavItem>
<SidebarNavItem
href="schedule"
icon={<SidebarNavItemIcon icon={ScheduleIcon} />}
icon={<ScheduleIcon css={styles.sidebarItemIcon} />}
>
Schedule
</SidebarNavItem>
@ -122,6 +114,10 @@ const styles = {
width: 245,
flexShrink: 0,
},
sidebarItemIcon: {
width: 16,
height: 16,
},
workspaceInfo: (theme) => ({
...(theme.typography.body2 as CSSObject),
marginBottom: 16,

View File

@ -1,274 +1,62 @@
// Based on https://codepen.io/hkfoster/pen/YzeYRwR
import { getMetadataAsJSON } from "utils/metadata";
// When in development mode the experiments meta tag won't exist,
// so you can just set this to true.
export const experimentalTheme =
typeof document !== "undefined" &&
(getMetadataAsJSON<string[]>("experiments")?.includes("dashboard_theme") ??
false);
import tw from "./tailwind";
export const colors = {
white: "hsl(0, 0%, 100%)",
white: "#fff",
gray: experimentalTheme
? {
17: "hsl(0, 0%, 4%)",
16: "hsl(0, 0%, 7%)",
15: "hsl(0, 0%, 10%)",
14: "hsl(0, 0%, 14%)",
13: "hsl(0, 0%, 17%)",
12: "hsl(0, 0%, 20%)",
11: "hsl(0, 0%, 23%)",
10: "hsl(0, 0%, 27%)",
9: "hsl(0, 0%, 31%)",
8: "hsl(0, 0%, 35%)",
7: "hsl(0, 0%, 62%)",
6: "hsl(0, 0%, 69%)",
5: "hsl(0, 0%, 75%)",
4: "hsl(0, 0%, 82%)",
3: "hsl(0, 0%, 90%)",
2: "hsl(0, 0%, 93%)",
1: "hsl(0, 0%, 96%)",
}
: {
17: "hsl(220, 50%, 3%)",
16: "hsl(223, 44%, 9%)",
15: "hsl(222, 38%, 14%)",
14: "hsl(222, 32%, 19%)",
13: "hsl(222, 31%, 25%)",
12: "hsl(222, 30%, 31%)",
11: "hsl(219, 29%, 38%)",
10: "hsl(219, 28%, 45%)",
9: "hsl(219, 28%, 52%)",
8: "hsl(218, 29%, 58%)",
7: "hsl(219, 30%, 64%)",
6: "hsl(219, 31%, 71%)",
5: "hsl(218, 32%, 77%)",
4: "hsl(223, 38%, 84%)",
3: "hsl(218, 44%, 92%)",
2: "hsl(220, 50%, 95%)",
1: "hsl(220, 55%, 98%)",
},
gray: {
17: tw.gray[950],
16: tw.gray[900],
14: tw.gray[800],
13: tw.gray[700],
12: tw.gray[600],
11: tw.gray[500],
9: tw.gray[400],
6: tw.gray[300],
4: tw.gray[200],
2: tw.gray[100],
1: tw.gray[50],
},
red: experimentalTheme
? {
17: "hsl(355, 95%, 3%)",
16: "hsl(355, 88%, 8%)",
15: "hsl(355, 86%, 13%)",
14: "hsl(355, 84%, 18%)",
13: "hsl(355, 82%, 23%)",
12: "hsl(355, 74%, 28%)",
11: "hsl(355, 70%, 33%)",
10: "hsl(355, 66%, 38%)",
9: "hsl(355, 69%, 43%)",
8: "hsl(355, 73%, 48%)",
7: "hsl(355, 76%, 53%)",
6: "hsl(355, 78%, 58%)",
5: "hsl(355, 79%, 63%)",
4: "hsl(355, 85%, 68%)",
3: "hsl(355, 88%, 73%)",
2: "hsl(355, 95%, 78%)",
1: "hsl(355, 100%, 83%) ",
}
: {
17: "hsl(355, 95%, 3%)",
16: "hsl(355, 88%, 9%)",
15: "hsl(355, 86%, 14%)",
14: "hsl(355, 84%, 19%)",
13: "hsl(355, 82%, 25%)",
12: "hsl(355, 74%, 31%)",
11: "hsl(355, 70%, 38%)",
10: "hsl(355, 66%, 45%)",
9: "hsl(355, 69%, 52%)",
8: "hsl(355, 73%, 58%)",
7: "hsl(355, 76%, 64%)",
6: "hsl(355, 78%, 71%)",
5: "hsl(355, 79%, 77%)",
4: "hsl(355, 85%, 84%)",
3: "hsl(355, 88%, 92%)",
2: "hsl(355, 95%, 96%)",
1: "hsl(355, 100%, 98%) ",
},
red: {
15: tw.red[950],
12: tw.red[800],
10: tw.red[700],
9: tw.red[600],
8: tw.red[500],
6: tw.red[400],
2: tw.red[50],
},
orange: {
17: "hsl(20, 100%, 3%)",
16: "hsl(20, 98%, 9%)",
15: "hsl(20, 97%, 14%)",
14: "hsl(20, 93%, 19%)",
13: "hsl(20, 88%, 25%)",
12: "hsl(20, 84%, 32%)",
11: "hsl(20, 80%, 38%)",
10: "hsl(20, 76%, 46%)",
9: "hsl(20, 79%, 53%)",
8: "hsl(20, 83%, 59%)",
7: "hsl(20, 86%, 65%)",
6: "hsl(20, 88%, 72%)",
5: "hsl(20, 93%, 78%)",
4: "hsl(20, 97%, 84%)",
3: "hsl(20, 98%, 91%)",
2: "hsl(20, 99%, 96%)",
1: "hsl(20, 100%, 98%)",
15: tw.amber[950],
14: tw.amber[900],
12: tw.amber[800],
11: tw.amber[700],
10: tw.amber[600],
9: tw.amber[500],
7: tw.amber[400],
},
yellow: {
17: "hsl(48, 100%, 3%)",
16: "hsl(48, 87%, 9%)",
15: "hsl(48, 83%, 14%)",
14: "hsl(48, 88%, 19%)",
13: "hsl(48, 82%, 25%)",
12: "hsl(48, 74%, 32%)",
11: "hsl(48, 70%, 38%)",
10: "hsl(48, 66%, 46%)",
9: "hsl(48, 69%, 53%)",
8: "hsl(48, 73%, 59%)",
7: "hsl(48, 76%, 65%)",
6: "hsl(48, 78%, 72%)",
5: "hsl(48, 79%, 78%)",
4: "hsl(48, 85%, 84%)",
3: "hsl(48, 90%, 89%)",
2: "hsl(46, 95%, 93%)",
1: "hsl(46, 100%, 97%)",
5: tw.yellow[300],
},
green: {
17: "hsl(132, 98%, 3%)",
16: "hsl(140, 94%, 8%)",
15: "hsl(144, 93%, 12%)",
14: "hsl(145, 99%, 16%)",
13: "hsl(143, 83%, 22%)",
12: "hsl(143, 74%, 27%)",
11: "hsl(142, 64%, 34%)",
10: "hsl(141, 57%, 41%)",
9: "hsl(140, 50%, 49%)",
8: "hsl(140, 51%, 54%)",
7: "hsl(138, 54%, 61%)",
6: "hsl(137, 56%, 68%)",
5: "hsl(137, 55%, 75%)",
4: "hsl(137, 60%, 82%)",
3: "hsl(136, 74%, 91%)",
2: "hsl(136, 82%, 95%)",
1: "hsl(136, 100%, 97%)",
},
turquoise: {
17: "hsl(162, 88%, 3%)",
16: "hsl(164, 84%, 8%)",
15: "hsl(165, 76%, 14%)",
14: "hsl(167, 85%, 18%)",
13: "hsl(166, 74%, 25%)",
12: "hsl(166, 65%, 32%)",
11: "hsl(165, 61%, 38%)",
10: "hsl(165, 56%, 46%)",
9: "hsl(165, 56%, 53%)",
8: "hsl(165, 60%, 57%)",
7: "hsl(164, 65%, 64%)",
6: "hsl(163, 66%, 70%)",
5: "hsl(163, 66%, 77%)",
4: "hsl(162, 74%, 83%)",
3: "hsl(162, 97%, 91%)",
2: "hsl(163, 93%, 94%)",
1: "hsl(163, 100%, 97%)",
},
cyan: {
17: "hsl(186, 100%, 3%)",
16: "hsl(185, 86%, 8%)",
15: "hsl(186, 80%, 14%)",
14: "hsl(185, 83%, 18%)",
13: "hsl(185, 76%, 25%)",
12: "hsl(185, 68%, 31%)",
11: "hsl(185, 64%, 37%)",
10: "hsl(185, 59%, 45%)",
9: "hsl(185, 57%, 52%)",
8: "hsl(185, 61%, 57%)",
7: "hsl(185, 64%, 63%)",
6: "hsl(185, 66%, 70%)",
5: "hsl(185, 66%, 77%)",
4: "hsl(185, 72%, 83%)",
3: "hsl(185, 91%, 91%)",
2: "hsl(182, 96%, 94%)",
1: "hsl(182, 100%, 97%)",
15: tw.green[950],
13: tw.green[700],
12: tw.green[600],
11: tw.green[500],
9: tw.green[400],
8: tw.green[300],
},
blue: {
17: "hsl(215, 100%, 3%)",
16: "hsl(215, 92%, 7%)",
15: "hsl(215, 88%, 12%)",
14: "hsl(215, 93%, 17%)",
13: "hsl(215, 87%, 23%)",
12: "hsl(215, 79%, 30%)",
11: "hsl(215, 75%, 36%)",
10: "hsl(215, 71%, 44%)",
9: "hsl(215, 74%, 51%)",
8: "hsl(215, 78%, 57%)",
7: "hsl(215, 81%, 63%)",
6: "hsl(215, 83%, 70%)",
5: "hsl(215, 84%, 76%)",
4: "hsl(215, 90%, 82%)",
3: "hsl(215, 93%, 89%)",
2: "hsl(215, 97%, 95%)",
1: "hsl(215, 100%, 98%)",
},
indigo: {
17: "hsl(256, 100%, 3%)",
16: "hsl(254, 87%, 9%)",
15: "hsl(252, 83%, 14%)",
14: "hsl(250, 88%, 19%)",
13: "hsl(248, 82%, 25%)",
12: "hsl(246, 74%, 32%)",
11: "hsl(244, 70%, 38%)",
10: "hsl(242, 66%, 44%)",
9: "hsl(240, 67%, 53%)",
8: "hsl(238, 70%, 59%)",
7: "hsl(232, 74%, 63%)",
6: "hsl(236, 78%, 72%)",
5: "hsl(234, 79%, 78%)",
4: "hsl(232, 85%, 84%)",
3: "hsl(230, 90%, 91%)",
2: "hsl(228, 95%, 96%)",
1: "hsl(226, 100%, 98%)",
},
violet: {
17: "hsl(264, 100%, 3%)",
16: "hsl(265, 87%, 9%)",
15: "hsl(265, 83%, 14%)",
14: "hsl(265, 88%, 19%)",
13: "hsl(265, 82%, 25%)",
12: "hsl(265, 74%, 32%)",
11: "hsl(265, 70%, 38%)",
10: "hsl(265, 66%, 46%)",
9: "hsl(265, 69%, 53%)",
8: "hsl(265, 73%, 59%)",
7: "hsl(265, 76%, 65%)",
6: "hsl(265, 78%, 72%)",
5: "hsl(265, 79%, 78%)",
4: "hsl(264, 85%, 84%)",
3: "hsl(265, 90%, 91%)",
2: "hsl(265, 95%, 96%)",
1: "hsl(265, 100%, 98%)",
},
magenta: {
17: "hsl(316, 100%, 3%)",
16: "hsl(316, 86%, 9%)",
15: "hsl(314, 83%, 14%)",
14: "hsl(315, 85%, 19%)",
13: "hsl(315, 80%, 25%)",
12: "hsl(315, 71%, 31%)",
11: "hsl(315, 68%, 38%)",
10: "hsl(315, 62%, 45%)",
9: "hsl(315, 63%, 52%)",
8: "hsl(315, 67%, 58%)",
7: "hsl(315, 70%, 64%)",
6: "hsl(315, 71%, 71%)",
5: "hsl(315, 72%, 77%)",
4: "hsl(315, 79%, 84%)",
3: "hsl(316, 88%, 92%)",
2: "hsl(315, 95%, 96%)",
1: "hsl(315, 100%, 98%)",
14: tw.blue[950],
9: tw.blue[600],
8: tw.blue[500],
7: tw.blue[400],
6: tw.blue[300],
3: tw.blue[200],
1: tw.blue[50],
},
};

View File

@ -1,5 +1,7 @@
import colors from "./tailwind";
export type ThemeRole = keyof NewTheme["roles"];
export interface NewTheme {
l1: Role; // page background, things which sit at the "root level"
l2: InteractiveRole; // sidebars, table headers, navigation
@ -34,7 +36,7 @@ export const dark: NewTheme = {
l1: {
background: colors.gray[950],
outline: colors.gray[700],
fill: "#f00",
fill: colors.gray[600],
text: colors.white,
},
@ -60,7 +62,7 @@ export const dark: NewTheme = {
l3: {
background: colors.gray[800],
outline: colors.gray[700],
fill: "#f00",
fill: colors.gray[600],
text: colors.white,
disabled: {
background: "#f00",
@ -117,7 +119,7 @@ export const dark: NewTheme = {
notice: {
background: colors.yellow[950],
outline: colors.yellow[200],
fill: "#f00",
fill: colors.yellow[500],
text: colors.yellow[50],
},
info: {
@ -147,7 +149,7 @@ export const dark: NewTheme = {
active: {
background: colors.sky[950],
outline: colors.sky[500],
fill: "#f00",
fill: colors.sky[600],
text: colors.sky[50],
},
},

View File

@ -1,4 +1,4 @@
import { colors, experimentalTheme } from "./colors";
import { colors } from "./colors";
import { createTheme, type ThemeOptions } from "@mui/material/styles";
import {
BODY_FONT_FAMILY,
@ -32,27 +32,27 @@ export let dark = createTheme({
secondary: {
main: colors.gray[11],
contrastText: colors.gray[4],
dark: colors.indigo[7],
dark: colors.gray[9],
},
background: {
default: colors.gray[17],
paper: colors.gray[16],
paperLight: colors.gray[15],
paperLight: colors.gray[14],
},
text: {
primary: colors.gray[1],
secondary: colors.gray[5],
disabled: colors.gray[7],
secondary: colors.gray[4],
disabled: colors.gray[9],
},
divider: colors.gray[13],
warning: {
light: experimentalTheme ? colors.orange[9] : colors.orange[7],
main: experimentalTheme ? colors.orange[11] : colors.orange[9],
light: colors.orange[9],
main: colors.orange[12],
dark: colors.orange[15],
},
success: {
main: colors.green[11],
dark: colors.green[15],
dark: colors.green[12],
},
info: {
light: colors.blue[7],
@ -172,7 +172,7 @@ dark = createTheme(dark, {
},
outlined: {
":hover": {
border: `1px solid ${colors.gray[10]}`,
border: `1px solid ${colors.gray[11]}`,
},
},
outlinedNeutral: {
@ -214,7 +214,7 @@ dark = createTheme(dark, {
root: {
">button:hover+button": {
// The !important is unfortunate, but necessary for the border.
borderLeftColor: `${colors.gray[10]} !important`,
borderLeftColor: `${colors.gray[11]} !important`,
},
},
},
@ -407,7 +407,7 @@ dark = createTheme(dark, {
// The default outlined input color is white, which seemed jarring.
"&:hover:not(.Mui-error):not(.Mui-focused) .MuiOutlinedInput-notchedOutline":
{
borderColor: colors.gray[10],
borderColor: colors.gray[11],
},
},
},

View File

@ -173,43 +173,43 @@ export const getDisplayWorkspaceStatus = (
} as const;
case "starting":
return {
type: "success",
type: "active",
text: "Starting",
icon: <LoadingIcon />,
} as const;
case "stopping":
return {
type: "warning",
type: "notice",
text: "Stopping",
icon: <LoadingIcon />,
} as const;
case "stopped":
return {
type: "warning",
type: "notice",
text: "Stopped",
icon: <StopIcon />,
} as const;
case "deleting":
return {
type: "warning",
type: "danger",
text: "Deleting",
icon: <LoadingIcon />,
} as const;
case "deleted":
return {
type: "error",
type: "danger",
text: "Deleted",
icon: <ErrorIcon />,
} as const;
case "canceling":
return {
type: "warning",
type: "notice",
text: "Canceling",
icon: <LoadingIcon />,
} as const;
case "canceled":
return {
type: "warning",
type: "notice",
text: "Canceled",
icon: <ErrorIcon />,
} as const;
@ -221,7 +221,7 @@ export const getDisplayWorkspaceStatus = (
} as const;
case "pending":
return {
type: "info",
type: undefined,
text: getPendingWorkspaceStatusText(provisionerJob),
icon: <QueuedIcon />,
} as const;