diff --git a/site/src/components/Alert/Alert.tsx b/site/src/components/Alert/Alert.tsx index 6191de2c55592..8484a57d1c29c 100644 --- a/site/src/components/Alert/Alert.tsx +++ b/site/src/components/Alert/Alert.tsx @@ -21,7 +21,7 @@ export const Alert: FC = ({ children, actions, dismissible, - severity, + severity = "info", onDismiss, ...alertProps }) => { diff --git a/site/src/components/BuildAvatar/BuildAvatar.tsx b/site/src/components/BuildAvatar/BuildAvatar.tsx index dcd0351840b7e..4d0cb7097e321 100644 --- a/site/src/components/BuildAvatar/BuildAvatar.tsx +++ b/site/src/components/BuildAvatar/BuildAvatar.tsx @@ -17,9 +17,7 @@ export const BuildAvatar: FC = ({ build, size }) => { const theme = useTheme(); const { status, type } = getDisplayWorkspaceBuildStatus(theme, build); const badgeType = useClassName( - (css, theme) => css` - background-color: ${theme.palette[type].light}; - `, + (css, theme) => css({ backgroundColor: theme.palette[type].light }), [type], ); diff --git a/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx b/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx index 149488b557c10..9313a395435cd 100644 --- a/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx +++ b/site/src/components/Dialogs/DeleteDialog/DeleteDialog.tsx @@ -1,13 +1,7 @@ -import { - type FC, - type FormEvent, - type PropsWithChildren, - useId, - useState, -} from "react"; - -import { useTheme } from "@emotion/react"; import TextField from "@mui/material/TextField"; +import { type Interpolation, type Theme } from "@emotion/react"; +import { type FC, type FormEvent, useId, useState } from "react"; +import { Stack } from "../../Stack/Stack"; import { ConfirmDialog } from "../ConfirmDialog/ConfirmDialog"; export interface DeleteDialogProps { @@ -24,7 +18,7 @@ export interface DeleteDialogProps { confirmText?: string; } -export const DeleteDialog: FC> = ({ +export const DeleteDialog: FC = ({ isOpen, onCancel, onConfirm, @@ -39,7 +33,6 @@ export const DeleteDialog: FC> = ({ confirmText, }) => { const hookId = useId(); - const theme = useTheme(); const [userConfirmationText, setUserConfirmationText] = useState(""); const [isFocused, setIsFocused] = useState(false); @@ -69,19 +62,17 @@ export const DeleteDialog: FC> = ({ confirmText={confirmText} description={ <> -

- {verb ?? "Deleting"} this {entity} is irreversible! -

- - {Boolean(info) && ( -

{info}

- )} + +

+ {verb ?? "Deleting"} this {entity} is irreversible! +

-

Are you sure you want to proceed?

+ {Boolean(info) &&
{info}
} -

- Type “{name}” below to confirm. -

+

+ Type {name} below to confirm. +

+
> = ({ /> ); }; + +const styles = { + callout: (theme) => ({ + backgroundColor: theme.experimental.roles.danger.background, + border: `1px solid ${theme.experimental.roles.danger.outline}`, + borderRadius: theme.shape.borderRadius, + color: theme.experimental.roles.danger.text, + padding: "8px 16px", + }), +} satisfies Record>; diff --git a/site/src/components/Dialogs/Dialog.tsx b/site/src/components/Dialogs/Dialog.tsx index 9ed588cf7a758..04cb5411197e5 100644 --- a/site/src/components/Dialogs/Dialog.tsx +++ b/site/src/components/Dialogs/Dialog.tsx @@ -1,8 +1,8 @@ import MuiDialog, { DialogProps as MuiDialogProps } from "@mui/material/Dialog"; +import LoadingButton, { LoadingButtonProps } from "@mui/lab/LoadingButton"; +import { type Interpolation, type Theme } from "@emotion/react"; import { type FC, type ReactNode } from "react"; import { ConfirmDialogType } from "./types"; -import { type Interpolation, type Theme } from "@emotion/react"; -import LoadingButton, { LoadingButtonProps } from "@mui/lab/LoadingButton"; export interface DialogActionButtonsProps { /** Text to display in the cancel button */ diff --git a/site/src/components/InfoTooltip/InfoTooltip.tsx b/site/src/components/InfoTooltip/InfoTooltip.tsx index ebef8bc66949f..bce7d0bd5b2c8 100644 --- a/site/src/components/InfoTooltip/InfoTooltip.tsx +++ b/site/src/components/InfoTooltip/InfoTooltip.tsx @@ -7,11 +7,11 @@ import { HelpTooltipTitle, HelpTooltipTrigger, } from "components/HelpTooltip/HelpTooltip"; -import { Interpolation, Theme, css, useTheme } from "@emotion/react"; +import { css, type Interpolation, type Theme, useTheme } from "@emotion/react"; +import type { ThemeRole } from "theme/experimental"; interface InfoTooltipProps { - // TODO: use a `ThemeRole` type or something - type?: "warning" | "notice" | "info"; + type?: ThemeRole; title: ReactNode; message: ReactNode; } @@ -22,13 +22,12 @@ export const InfoTooltip: FC = ({ type = "info", }) => { const theme = useTheme(); + const iconColor = theme.experimental.roles[type].outline; return ( - + {title} diff --git a/site/src/components/ProxyStatusLatency/ProxyStatusLatency.tsx b/site/src/components/ProxyStatusLatency/ProxyStatusLatency.tsx index f139314f05748..6efb105961195 100644 --- a/site/src/components/ProxyStatusLatency/ProxyStatusLatency.tsx +++ b/site/src/components/ProxyStatusLatency/ProxyStatusLatency.tsx @@ -1,10 +1,10 @@ -import { useTheme } from "@emotion/react"; import HelpOutline from "@mui/icons-material/HelpOutline"; import Tooltip from "@mui/material/Tooltip"; -import { type FC } from "react"; -import { getLatencyColor } from "utils/latency"; import CircularProgress from "@mui/material/CircularProgress"; import { visuallyHidden } from "@mui/utils"; +import { useTheme } from "@emotion/react"; +import { type FC } from "react"; +import { getLatencyColor } from "utils/latency"; import { Abbr } from "components/Abbr/Abbr"; interface ProxyStatusLatencyProps { @@ -17,18 +17,16 @@ export const ProxyStatusLatency: FC = ({ isLoading, }) => { const theme = useTheme(); - const color = getLatencyColor(theme, latency); + // Always use the no latency color for loading. + const color = getLatencyColor(theme, isLoading ? undefined : latency); if (isLoading) { return ( ); @@ -45,8 +43,8 @@ export const ProxyStatusLatency: FC = ({ css={{ marginLeft: "auto", fontSize: "14px !important", - color, }} + style={{ color }} /> @@ -54,7 +52,7 @@ export const ProxyStatusLatency: FC = ({ } return ( -

+

Latency: {latency.toFixed(0)} ms diff --git a/site/src/pages/DeploySettingsPage/LicensesSettingsPage/LicenseCard.tsx b/site/src/pages/DeploySettingsPage/LicensesSettingsPage/LicenseCard.tsx index 39886bf18e15a..07f199a507aa4 100644 --- a/site/src/pages/DeploySettingsPage/LicensesSettingsPage/LicenseCard.tsx +++ b/site/src/pages/DeploySettingsPage/LicensesSettingsPage/LicenseCard.tsx @@ -2,7 +2,7 @@ import { type CSSObject, type Interpolation, type Theme } from "@emotion/react"; import Button from "@mui/material/Button"; import Paper from "@mui/material/Paper"; import dayjs from "dayjs"; -import { useState } from "react"; +import { type FC, useState } from "react"; import { compareAsc } from "date-fns"; import { type GetLicensesResponse } from "api/api"; import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog"; @@ -17,13 +17,13 @@ type LicenseCardProps = { isRemoving: boolean; }; -export const LicenseCard = ({ +export const LicenseCard: FC = ({ license, userLimitActual, userLimitLimit, onRemove, isRemoving, -}: LicenseCardProps) => { +}) => { const [licenseIDMarkedForRemoval, setLicenseIDMarkedForRemoval] = useState< number | undefined >(undefined); diff --git a/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx b/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx index 32ff9bb4eea9d..11b93f1188f4e 100644 --- a/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx +++ b/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx @@ -508,9 +508,9 @@ export const TemplateVersionEditor: FC = ({ ref={buildLogsRef} css={{ display: selectedTab !== "logs" ? "none" : "flex", + height: selectedTab ? 280 : 0, flexDirection: "column", overflowY: "auto", - height: selectedTab ? 280 : 0, }} > {templateVersion.job.error && ( @@ -536,33 +536,7 @@ export const TemplateVersionEditor: FC = ({ {buildLogs && buildLogs.length > 0 && ( @@ -570,25 +544,13 @@ export const TemplateVersionEditor: FC = ({

{resources && ( ({ padding: "8px 16px", position: "sticky", @@ -684,4 +647,50 @@ const styles = { borderTop: `1px solid ${theme.palette.divider}`, }, }), + + buildLogs: { + borderRadius: 0, + border: 0, + + // Hack to update logs header and lines + "& .logs-header": { + border: 0, + padding: "0 16px", + fontFamily: MONOSPACE_FONT_FAMILY, + + "&:first-child": { + paddingTop: 16, + }, + + "&:last-child": { + paddingBottom: 16, + }, + }, + + "& .logs-line": { + paddingLeft: 16, + }, + + "& .logs-container": { + border: "0 !important", + }, + }, + + resources: { + overflowY: "auto", + + // Hack to access customize resource-card from here + "& .resource-card": { + borderLeft: 0, + borderRight: 0, + + "&:first-child": { + borderTop: 0, + }, + + "&:last-child": { + borderBottom: 0, + }, + }, + }, } satisfies Record>; diff --git a/site/src/pages/UserSettingsPage/TokensPage/TokensPageView.tsx b/site/src/pages/UserSettingsPage/TokensPage/TokensPageView.tsx index f370dc846ea1f..8b3b957935744 100644 --- a/site/src/pages/UserSettingsPage/TokensPage/TokensPageView.tsx +++ b/site/src/pages/UserSettingsPage/TokensPage/TokensPageView.tsx @@ -4,18 +4,18 @@ 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 { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; -import { Stack } from "components/Stack/Stack"; -import { TableEmpty } from "components/TableEmpty/TableEmpty"; -import { TableLoader } from "components/TableLoader/TableLoader"; +import IconButton from "@mui/material/IconButton"; import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline"; import dayjs from "dayjs"; import { useTheme } from "@emotion/react"; import { type FC, type ReactNode } from "react"; -import IconButton from "@mui/material/IconButton/IconButton"; import type { APIKeyWithOwner } from "api/typesGenerated"; import relativeTime from "dayjs/plugin/relativeTime"; import { ErrorAlert } from "components/Alert/ErrorAlert"; +import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; +import { Stack } from "components/Stack/Stack"; +import { TableEmpty } from "components/TableEmpty/TableEmpty"; +import { TableLoader } from "components/TableLoader/TableLoader"; dayjs.extend(relativeTime); diff --git a/site/src/pages/UsersPage/UsersPage.test.tsx b/site/src/pages/UsersPage/UsersPage.test.tsx index bbe29a30d4992..56a1f1ac1f0a9 100644 --- a/site/src/pages/UsersPage/UsersPage.test.tsx +++ b/site/src/pages/UsersPage/UsersPage.test.tsx @@ -49,10 +49,6 @@ const deleteUser = async () => { const deleteButton = screen.getByText(/Delete/); await user.click(deleteButton); - // Check if the confirm message is displayed - const confirmDialog = await screen.findByRole("dialog"); - expect(confirmDialog).toHaveTextContent(`Are you sure you want to proceed?`); - // Confirm with text input const textField = screen.getByLabelText("Name of the user to delete"); const dialog = screen.getByRole("dialog"); diff --git a/site/src/pages/WorkspacesPage/BatchActions.tsx b/site/src/pages/WorkspacesPage/BatchActions.tsx index c3064ca35b65e..e8ee5898a66f4 100644 --- a/site/src/pages/WorkspacesPage/BatchActions.tsx +++ b/site/src/pages/WorkspacesPage/BatchActions.tsx @@ -136,6 +136,7 @@ export const BatchDeleteConfirmation: FC = ({ return ( { setStage("consequences"); @@ -146,7 +147,6 @@ export const BatchDeleteConfirmation: FC = ({ confirmLoading={isLoading} confirmText={confirmText} onConfirm={onProceed} - type="delete" description={ <> {stage === "consequences" && } diff --git a/site/src/pages/WorkspacesPage/WorkspacesEmpty.tsx b/site/src/pages/WorkspacesPage/WorkspacesEmpty.tsx index e2e621e954860..3ba4893b6a777 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesEmpty.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesEmpty.tsx @@ -1,6 +1,6 @@ import ArrowForwardOutlined from "@mui/icons-material/ArrowForwardOutlined"; import Button from "@mui/material/Button"; -import { Template } from "api/typesGenerated"; +import type { Template } from "api/typesGenerated"; import { Avatar } from "components/Avatar/Avatar"; import { TableEmpty } from "components/TableEmpty/TableEmpty"; import { Link } from "react-router-dom"; diff --git a/site/src/utils/workspace.tsx b/site/src/utils/workspace.tsx index 981a511b76fb4..55492cb0e4843 100644 --- a/site/src/utils/workspace.tsx +++ b/site/src/utils/workspace.tsx @@ -1,11 +1,11 @@ -import ErrorIcon from "@mui/icons-material/ErrorOutline"; -import StopIcon from "@mui/icons-material/StopOutlined"; -import PlayIcon from "@mui/icons-material/PlayArrowOutlined"; -import QueuedIcon from "@mui/icons-material/HourglassEmpty"; import dayjs from "dayjs"; import duration from "dayjs/plugin/duration"; import minMax from "dayjs/plugin/minMax"; import utc from "dayjs/plugin/utc"; +import ErrorIcon from "@mui/icons-material/ErrorOutline"; +import StopIcon from "@mui/icons-material/StopOutlined"; +import PlayIcon from "@mui/icons-material/PlayArrowOutlined"; +import QueuedIcon from "@mui/icons-material/HourglassEmpty"; import { type Theme } from "@emotion/react"; import semver from "semver"; import type * as TypesGen from "api/typesGenerated"; @@ -36,19 +36,19 @@ export const getDisplayWorkspaceBuildStatus = ( case "succeeded": return { type: "success", - color: theme.palette.success.light, + color: theme.experimental.roles.success.text, status: DisplayWorkspaceBuildStatusLanguage.succeeded, } as const; case "pending": return { type: "secondary", - color: theme.palette.text.secondary, + color: theme.experimental.roles.active.text, status: DisplayWorkspaceBuildStatusLanguage.pending, } as const; case "running": return { type: "info", - color: theme.palette.primary.main, + color: theme.experimental.roles.active.text, status: DisplayWorkspaceBuildStatusLanguage.running, } as const; // Just handle unknown as failed @@ -56,19 +56,19 @@ export const getDisplayWorkspaceBuildStatus = ( case "failed": return { type: "error", - color: theme.palette.text.secondary, + color: theme.experimental.roles.error.text, status: DisplayWorkspaceBuildStatusLanguage.failed, } as const; case "canceling": return { type: "warning", - color: theme.palette.warning.light, + color: theme.experimental.roles.warning.text, status: DisplayWorkspaceBuildStatusLanguage.canceling, } as const; case "canceled": return { type: "secondary", - color: theme.palette.text.secondary, + color: theme.experimental.roles.warning.text, status: DisplayWorkspaceBuildStatusLanguage.canceled, } as const; }