diff --git a/site/src/components/Alert/Alert.tsx b/site/src/components/Alert/Alert.tsx index e97b690f82833..772801132fee9 100644 --- a/site/src/components/Alert/Alert.tsx +++ b/site/src/components/Alert/Alert.tsx @@ -1,24 +1,50 @@ -import MuiAlert, { - type AlertColor as MuiAlertColor, - type AlertProps as MuiAlertProps, - // biome-ignore lint/nursery/noRestrictedImports: Used as base component -} from "@mui/material/Alert"; -import Collapse from "@mui/material/Collapse"; +import { type VariantProps, cva } from "class-variance-authority"; import { Button } from "components/Button/Button"; import { type FC, type PropsWithChildren, type ReactNode, + forwardRef, useState, } from "react"; +import { cn } from "utils/cn"; -export type AlertColor = MuiAlertColor; +const alertVariants = cva( + "relative w-full rounded-lg border border-solid p-4 text-left", + { + variants: { + variant: { + default: "border-border-default", + info: "border-highlight-sky", + success: "border-surface-green", + warning: "border-border-warning", + error: "border-border-destructive", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); -export type AlertProps = MuiAlertProps & { +// Map MUI severity to our variant +const severityToVariant = { + info: "info", + success: "success", + warning: "warning", + error: "error", +} as const; + +export type AlertColor = "info" | "success" | "warning" | "error"; + +export type AlertProps = { actions?: ReactNode; dismissible?: boolean; onDismiss?: () => void; -}; + severity?: AlertColor; + children?: ReactNode; + className?: string; +} & VariantProps; export const Alert: FC = ({ children, @@ -26,58 +52,70 @@ export const Alert: FC = ({ dismissible, severity = "info", onDismiss, - ...alertProps + className, + variant, + ...props }) => { const [open, setOpen] = useState(true); - // Can't only rely on MUI's hiding behavior inside flex layouts, because even - // though MUI will make a dismissed alert have zero height, the alert will - // still behave as a flex child and introduce extra row/column gaps if (!open) { return null; } + // Use severity to determine variant if variant is not explicitly provided + const finalVariant = + variant || + (severity in severityToVariant ? severityToVariant[severity] : "default"); + return ( - - - {/* CTAs passed in by the consumer */} - {actions} +
+
+
{children}
+
+ {/* CTAs passed in by the consumer */} + {actions} - {/* close CTA */} - {dismissible && ( - - )} - - } - > - {children} - - + {dismissible && ( + + )} +
+
+
); }; export const AlertDetail: FC = ({ children }) => { return ( - ({ color: theme.palette.text.secondary, fontSize: 13 })} - data-chromatic="ignore" - > + {children} ); }; + +// Export AlertTitle and AlertDescription for compatibility +export const AlertTitle = forwardRef< + HTMLHeadingElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); + +AlertTitle.displayName = "AlertTitle"; diff --git a/site/src/components/Alert/ErrorAlert.tsx b/site/src/components/Alert/ErrorAlert.tsx index 0198ea4e99540..210a3f032da9f 100644 --- a/site/src/components/Alert/ErrorAlert.tsx +++ b/site/src/components/Alert/ErrorAlert.tsx @@ -1,8 +1,7 @@ -import AlertTitle from "@mui/material/AlertTitle"; import { getErrorDetail, getErrorMessage, getErrorStatus } from "api/errors"; import type { FC } from "react"; import { Link } from "../Link/Link"; -import { Alert, AlertDetail, type AlertProps } from "./Alert"; +import { Alert, AlertDetail, type AlertProps, AlertTitle } from "./Alert"; export const ErrorAlert: FC< Omit & { error: unknown } diff --git a/site/src/components/GitDeviceAuth/GitDeviceAuth.tsx b/site/src/components/GitDeviceAuth/GitDeviceAuth.tsx index 7b3d8091abfeb..e8e74c1fe42a0 100644 --- a/site/src/components/GitDeviceAuth/GitDeviceAuth.tsx +++ b/site/src/components/GitDeviceAuth/GitDeviceAuth.tsx @@ -1,11 +1,11 @@ import type { Interpolation, Theme } from "@emotion/react"; -import AlertTitle from "@mui/material/AlertTitle"; + import CircularProgress from "@mui/material/CircularProgress"; import Link from "@mui/material/Link"; import type { ApiErrorResponse } from "api/errors"; import type { ExternalAuthDevice } from "api/typesGenerated"; import { isAxiosError } from "axios"; -import { Alert, AlertDetail } from "components/Alert/Alert"; +import { Alert, AlertDetail, AlertTitle } from "components/Alert/Alert"; import { CopyButton } from "components/CopyButton/CopyButton"; import { ExternalLinkIcon } from "lucide-react"; import type { FC } from "react"; diff --git a/site/src/modules/provisioners/ProvisionerAlert.tsx b/site/src/modules/provisioners/ProvisionerAlert.tsx index 2d14237b414ed..eebe4ea0bbd8c 100644 --- a/site/src/modules/provisioners/ProvisionerAlert.tsx +++ b/site/src/modules/provisioners/ProvisionerAlert.tsx @@ -1,7 +1,10 @@ import type { Theme } from "@emotion/react"; -import AlertTitle from "@mui/material/AlertTitle"; -import { Alert, type AlertColor } from "components/Alert/Alert"; -import { AlertDetail } from "components/Alert/Alert"; +import { + Alert, + type AlertColor, + AlertDetail, + AlertTitle, +} from "components/Alert/Alert"; import { ProvisionerTag } from "modules/provisioners/ProvisionerTag"; import type { FC } from "react"; diff --git a/site/src/modules/workspaces/WorkspaceMoreActions/ChangeWorkspaceVersionDialog.tsx b/site/src/modules/workspaces/WorkspaceMoreActions/ChangeWorkspaceVersionDialog.tsx index ecedc5aef6b5f..3f06933dc04d3 100644 --- a/site/src/modules/workspaces/WorkspaceMoreActions/ChangeWorkspaceVersionDialog.tsx +++ b/site/src/modules/workspaces/WorkspaceMoreActions/ChangeWorkspaceVersionDialog.tsx @@ -1,11 +1,11 @@ import { css } from "@emotion/css"; -import AlertTitle from "@mui/material/AlertTitle"; + import Autocomplete from "@mui/material/Autocomplete"; import CircularProgress from "@mui/material/CircularProgress"; import TextField from "@mui/material/TextField"; import { templateVersions } from "api/queries/templates"; import type { TemplateVersion, Workspace } from "api/typesGenerated"; -import { Alert } from "components/Alert/Alert"; +import { Alert, AlertTitle } from "components/Alert/Alert"; import { Avatar } from "components/Avatar/Avatar"; import { AvatarData } from "components/Avatar/AvatarData"; import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog"; diff --git a/site/src/pages/DeploymentSettingsPage/OverviewPage/OverviewPageView.tsx b/site/src/pages/DeploymentSettingsPage/OverviewPage/OverviewPageView.tsx index 37da47f4b8a16..0cda25199e595 100644 --- a/site/src/pages/DeploymentSettingsPage/OverviewPage/OverviewPageView.tsx +++ b/site/src/pages/DeploymentSettingsPage/OverviewPage/OverviewPageView.tsx @@ -1,4 +1,3 @@ -import AlertTitle from "@mui/material/AlertTitle"; import type { DAUsResponse, Experiment, @@ -15,7 +14,7 @@ import { Stack } from "components/Stack/Stack"; import type { FC } from "react"; import { useDeploymentOptions } from "utils/deployOptions"; import { docs } from "utils/docs"; -import { Alert } from "../../../components/Alert/Alert"; +import { Alert, AlertTitle } from "../../../components/Alert/Alert"; import OptionsTable from "../OptionsTable"; import { UserEngagementChart } from "./UserEngagementChart"; diff --git a/site/src/pages/SetupPage/SetupPageView.tsx b/site/src/pages/SetupPage/SetupPageView.tsx index 96654bdda8514..a27ebebd5f696 100644 --- a/site/src/pages/SetupPage/SetupPageView.tsx +++ b/site/src/pages/SetupPage/SetupPageView.tsx @@ -1,5 +1,5 @@ import GitHubIcon from "@mui/icons-material/GitHub"; -import AlertTitle from "@mui/material/AlertTitle"; + import Autocomplete from "@mui/material/Autocomplete"; import MuiButton from "@mui/material/Button"; import Checkbox from "@mui/material/Checkbox"; @@ -9,7 +9,7 @@ import TextField from "@mui/material/TextField"; import { countries } from "api/countriesGenerated"; import type * as TypesGen from "api/typesGenerated"; import { isAxiosError } from "axios"; -import { Alert, AlertDetail } from "components/Alert/Alert"; +import { Alert, AlertDetail, AlertTitle } from "components/Alert/Alert"; import { Button } from "components/Button/Button"; import { FormFields, VerticalForm } from "components/Form/Form"; import { CoderIcon } from "components/Icons/CoderIcon"; diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index 07c5ec26d0766..a4e6197e472da 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -2,9 +2,9 @@ import type { Interpolation, Theme } from "@emotion/react"; import { useTheme } from "@emotion/react"; import HistoryOutlined from "@mui/icons-material/HistoryOutlined"; import HubOutlined from "@mui/icons-material/HubOutlined"; -import AlertTitle from "@mui/material/AlertTitle"; + import type * as TypesGen from "api/typesGenerated"; -import { Alert, AlertDetail } from "components/Alert/Alert"; +import { Alert, AlertDetail, AlertTitle } from "components/Alert/Alert"; import { SidebarIconButton } from "components/FullPageLayout/Sidebar"; import { useSearchParamsKey } from "hooks/useSearchParamsKey"; import { ProvisionerStatusAlert } from "modules/provisioners/ProvisionerStatusAlert"; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy