From 40d74185bfa097651d6c1f8d0b9c5f048eb6027d Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Tue, 7 Oct 2025 16:59:24 +0000 Subject: [PATCH 1/7] chore: replace remaining MUI buttons --- site/src/@types/mui.d.ts | 10 -- .../InputGroup/InputGroup.stories.tsx | 4 +- .../DeploymentBanner/DeploymentBannerView.tsx | 6 +- site/src/modules/resources/Resources.tsx | 5 +- .../UpdateBuildParametersDialog.tsx | 11 ++- .../WorkspaceTiming/WorkspaceTimings.tsx | 4 +- .../CreateTemplatePage/BuildLogsDrawer.tsx | 6 +- .../LicensesSettingsPage/LicenseCard.tsx | 13 +-- .../LicensesSettingsPageView.tsx | 14 ++- .../NotificationsPage/NotificationEvents.tsx | 36 ++++--- .../OAuth2AppsSettingsPageView.tsx | 13 ++- .../ExternalAuthPage/ExternalAuthPage.tsx | 3 +- site/src/pages/GroupsPage/GroupPage.tsx | 28 ++---- site/src/pages/HealthPage/DERPPage.tsx | 15 +-- site/src/pages/LoginPage/OAuthSignInForm.tsx | 52 +++++----- .../CustomRolesPage/CustomRolesPageView.tsx | 26 +++-- .../ResetPasswordPage/ChangePasswordPage.tsx | 13 +-- site/src/pages/SetupPage/SetupPageView.tsx | 18 ++-- .../pages/TemplatePage/TemplatePageHeader.tsx | 15 ++- site/src/theme/constants.ts | 2 - site/src/theme/light/mui.ts | 51 ---------- site/src/theme/mui.ts | 98 ------------------- 22 files changed, 123 insertions(+), 320 deletions(-) diff --git a/site/src/@types/mui.d.ts b/site/src/@types/mui.d.ts index 49804d33f8971..daad165f7d335 100644 --- a/site/src/@types/mui.d.ts +++ b/site/src/@types/mui.d.ts @@ -13,16 +13,6 @@ declare module "@mui/material/styles" { } } -declare module "@mui/material/Button" { - interface ButtonPropsColorOverrides { - neutral: true; - } - - interface ButtonPropsSizeOverrides { - xlarge: true; - } -} - declare module "@mui/material/Checkbox" { interface CheckboxPropsSizeOverrides { xsmall: true; diff --git a/site/src/components/InputGroup/InputGroup.stories.tsx b/site/src/components/InputGroup/InputGroup.stories.tsx index 77c86e52344ae..2f048c8a8f41e 100644 --- a/site/src/components/InputGroup/InputGroup.stories.tsx +++ b/site/src/components/InputGroup/InputGroup.stories.tsx @@ -1,6 +1,6 @@ -import Button from "@mui/material/Button"; import TextField from "@mui/material/TextField"; import type { Meta, StoryObj } from "@storybook/react-vite"; +import { Button } from "components/Button/Button"; import { InputGroup } from "./InputGroup"; const meta: Meta = { @@ -70,7 +70,7 @@ export const WithThreeElements: Story = { args: { children: ( <> - + diff --git a/site/src/modules/dashboard/DeploymentBanner/DeploymentBannerView.tsx b/site/src/modules/dashboard/DeploymentBanner/DeploymentBannerView.tsx index 4f9838e0255da..eccd9ad6b62bb 100644 --- a/site/src/modules/dashboard/DeploymentBanner/DeploymentBannerView.tsx +++ b/site/src/modules/dashboard/DeploymentBanner/DeploymentBannerView.tsx @@ -1,5 +1,4 @@ import { css, type Interpolation, type Theme, useTheme } from "@emotion/react"; -import Button from "@mui/material/Button"; import Link from "@mui/material/Link"; import Tooltip from "@mui/material/Tooltip"; import type { @@ -7,6 +6,7 @@ import type { HealthcheckReport, WorkspaceStatus, } from "api/typesGenerated"; +import { Button } from "components/Button/Button"; import { HelpTooltipTitle } from "components/HelpTooltip/HelpTooltip"; import { JetBrainsIcon } from "components/Icons/JetBrainsIcon"; import { RocketIcon } from "components/Icons/RocketIcon"; @@ -323,9 +323,9 @@ export const DeploymentBannerView: FC = ({ fetchStats(); } }} - variant="text" + variant="subtle" > - + {timeUntilRefresh}s diff --git a/site/src/modules/resources/Resources.tsx b/site/src/modules/resources/Resources.tsx index 094092619347b..13e1bbf835252 100644 --- a/site/src/modules/resources/Resources.tsx +++ b/site/src/modules/resources/Resources.tsx @@ -1,5 +1,5 @@ -import Button from "@mui/material/Button"; import type { WorkspaceAgent, WorkspaceResource } from "api/typesGenerated"; +import { Button } from "components/Button/Button"; import { DropdownArrow } from "components/DropdownArrow/DropdownArrow"; import { Stack } from "components/Stack/Stack"; import { type FC, type JSX, useState } from "react"; @@ -37,8 +37,9 @@ export const Resources: FC = ({ resources, agentRow }) => { {hasHideResources && (
- diff --git a/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx b/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx index 847b531949c00..7614013c9bfbf 100644 --- a/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx +++ b/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx @@ -1,5 +1,4 @@ import type { Interpolation, Theme } from "@emotion/react"; -import Button from "@mui/material/Button"; import Collapse from "@mui/material/Collapse"; import Skeleton from "@mui/material/Skeleton"; import type { @@ -7,6 +6,7 @@ import type { AgentScriptTiming, ProvisionerTiming, } from "api/typesGenerated"; +import { Button } from "components/Button/Button"; import sortBy from "lodash/sortBy"; import uniqBy from "lodash/uniqBy"; import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"; @@ -96,7 +96,7 @@ export const WorkspaceTimings: FC = ({
} > @@ -86,15 +85,14 @@ export const NotificationEvents: FC = ({ - Read the docs + } > diff --git a/site/src/pages/DeploymentSettingsPage/OAuth2AppsSettingsPage/OAuth2AppsSettingsPageView.tsx b/site/src/pages/DeploymentSettingsPage/OAuth2AppsSettingsPage/OAuth2AppsSettingsPageView.tsx index 55ee649353158..4b42f946758b8 100644 --- a/site/src/pages/DeploymentSettingsPage/OAuth2AppsSettingsPage/OAuth2AppsSettingsPageView.tsx +++ b/site/src/pages/DeploymentSettingsPage/OAuth2AppsSettingsPage/OAuth2AppsSettingsPageView.tsx @@ -1,5 +1,4 @@ import { useTheme } from "@emotion/react"; -import Button from "@mui/material/Button"; import Table from "@mui/material/Table"; import TableBody from "@mui/material/TableBody"; import TableCell from "@mui/material/TableCell"; @@ -9,6 +8,7 @@ import TableRow from "@mui/material/TableRow"; import type * as TypesGen from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Avatar } from "components/Avatar/Avatar"; +import { Button } from "components/Button/Button"; import { SettingsHeader, SettingsHeaderDescription, @@ -48,12 +48,11 @@ const OAuth2AppsSettingsPageView: FC = ({
- diff --git a/site/src/pages/ExternalAuthPage/ExternalAuthPage.tsx b/site/src/pages/ExternalAuthPage/ExternalAuthPage.tsx index 105e7ee501b38..c4ae645d015c2 100644 --- a/site/src/pages/ExternalAuthPage/ExternalAuthPage.tsx +++ b/site/src/pages/ExternalAuthPage/ExternalAuthPage.tsx @@ -1,4 +1,3 @@ -import Button from "@mui/material/Button"; import type { ApiErrorResponse } from "api/errors"; import { exchangeExternalAuthDevice, @@ -6,6 +5,7 @@ import { externalAuthProvider, } from "api/queries/externalAuth"; import { isAxiosError } from "axios"; +import { Button } from "components/Button/Button"; import { isExchangeErrorRetryable, newRetryDelay, @@ -91,6 +91,7 @@ const ExternalAuthPage: FC = () => {


+ )} @@ -353,12 +351,6 @@ const styles = { autoComplete: { width: 300, }, - removeButton: (theme) => ({ - color: theme.palette.error.main, - "&:hover": { - backgroundColor: "transparent", - }, - }), status: { textTransform: "capitalize", }, diff --git a/site/src/pages/HealthPage/DERPPage.tsx b/site/src/pages/HealthPage/DERPPage.tsx index 8b4b85bd37551..251082927ac47 100644 --- a/site/src/pages/HealthPage/DERPPage.tsx +++ b/site/src/pages/HealthPage/DERPPage.tsx @@ -1,11 +1,11 @@ import { useTheme } from "@emotion/react"; -import Button from "@mui/material/Button"; import type { HealthcheckReport, HealthSeverity, NetcheckReport, } from "api/typesGenerated"; import { Alert } from "components/Alert/Alert"; +import { Button } from "components/Button/Button"; import { MapPinIcon } from "lucide-react"; import type { FC } from "react"; import { Link, useOutletContext } from "react-router"; @@ -100,10 +100,9 @@ const DERPPage: FC = () => { }) .map(({ severity, region }) => { return ( - ); })} diff --git a/site/src/pages/LoginPage/OAuthSignInForm.tsx b/site/src/pages/LoginPage/OAuthSignInForm.tsx index e4872d6600389..140ceff738b39 100644 --- a/site/src/pages/LoginPage/OAuthSignInForm.tsx +++ b/site/src/pages/LoginPage/OAuthSignInForm.tsx @@ -1,8 +1,8 @@ import GitHubIcon from "@mui/icons-material/GitHub"; import KeyIcon from "@mui/icons-material/VpnKey"; -import Button from "@mui/material/Button"; import { visuallyHidden } from "@mui/utils"; import type { AuthMethods } from "api/typesGenerated"; +import { Button } from "components/Button/Button"; import { type FC, useId } from "react"; import { Language } from "./Language"; @@ -26,41 +26,43 @@ export const OAuthSignInForm: FC = ({
{authMethods?.github.enabled && ( )} {authMethods?.oidc.enabled && ( )}
diff --git a/site/src/pages/OrganizationSettingsPage/CustomRolesPage/CustomRolesPageView.tsx b/site/src/pages/OrganizationSettingsPage/CustomRolesPage/CustomRolesPageView.tsx index cd94b6a18e669..e3074f3ada94e 100644 --- a/site/src/pages/OrganizationSettingsPage/CustomRolesPage/CustomRolesPageView.tsx +++ b/site/src/pages/OrganizationSettingsPage/CustomRolesPage/CustomRolesPageView.tsx @@ -1,8 +1,7 @@ import type { Interpolation, Theme } from "@emotion/react"; -import Button from "@mui/material/Button"; import Skeleton from "@mui/material/Skeleton"; import type { AssignableRoles, Role } from "api/typesGenerated"; -import { Button as ShadcnButton } from "components/Button/Button"; +import { Button, Button as ShadcnButton } from "components/Button/Button"; import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; import { DropdownMenu, @@ -72,12 +71,11 @@ export const CustomRolesPageView: FC = ({ {canCreateOrgRole && isCustomRolesEnabled && ( - )} @@ -157,13 +155,11 @@ const RoleTable: FC = ({ cta={ canCreateOrgRole && isCustomRolesEnabled && ( - ) } diff --git a/site/src/pages/ResetPasswordPage/ChangePasswordPage.tsx b/site/src/pages/ResetPasswordPage/ChangePasswordPage.tsx index c7ae619950b43..3f447be2d92fe 100644 --- a/site/src/pages/ResetPasswordPage/ChangePasswordPage.tsx +++ b/site/src/pages/ResetPasswordPage/ChangePasswordPage.tsx @@ -1,5 +1,4 @@ import type { Interpolation, Theme } from "@emotion/react"; -import MUIButton from "@mui/material/Button"; import TextField from "@mui/material/TextField"; import { isApiValidationError } from "api/errors"; import { changePasswordWithOTP } from "api/queries/users"; @@ -119,15 +118,9 @@ const ChangePasswordPage: FC = ({ redirect }) => { Reset password - - Back to login - + diff --git a/site/src/pages/SetupPage/SetupPageView.tsx b/site/src/pages/SetupPage/SetupPageView.tsx index 96654bdda8514..57534ddbe74cd 100644 --- a/site/src/pages/SetupPage/SetupPageView.tsx +++ b/site/src/pages/SetupPage/SetupPageView.tsx @@ -1,7 +1,6 @@ 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"; import Link from "@mui/material/Link"; import MenuItem from "@mui/material/MenuItem"; @@ -173,17 +172,12 @@ export const SetupPageView: FC = ({ {authMethods?.github.enabled && ( <> - } - type="submit" - size="xlarge" - > - {Language.githubCreate} - +
diff --git a/site/src/pages/TemplatePage/TemplatePageHeader.tsx b/site/src/pages/TemplatePage/TemplatePageHeader.tsx index dd93054f64d9e..8db6afcd07292 100644 --- a/site/src/pages/TemplatePage/TemplatePageHeader.tsx +++ b/site/src/pages/TemplatePage/TemplatePageHeader.tsx @@ -1,4 +1,3 @@ -import Button from "@mui/material/Button"; import { API } from "api/api"; import { workspaces } from "api/queries/workspaces"; import type { @@ -7,7 +6,7 @@ import type { TemplateVersion, } from "api/typesGenerated"; import { Avatar } from "components/Avatar/Avatar"; -import { Button as ShadcnButton } from "components/Button/Button"; +import { Button, Button as ShadcnButton } from "components/Button/Button"; import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog"; import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog"; import { @@ -222,13 +221,11 @@ export const TemplatePageHeader: FC = ({ <> {!template.deprecated && workspacePermissions.createWorkspaceForUserID && ( - )} diff --git a/site/src/theme/constants.ts b/site/src/theme/constants.ts index f74611cefd324..28b5234d8f138 100644 --- a/site/src/theme/constants.ts +++ b/site/src/theme/constants.ts @@ -34,7 +34,5 @@ export const containerWidthMedium = 1080; export const sidePadding = 24; // MUI does not have aligned heights for buttons and inputs so we have to "hack" it a little bit -export const BUTTON_XL_HEIGHT = 44; export const BUTTON_LG_HEIGHT = 40; export const BUTTON_MD_HEIGHT = 36; -export const BUTTON_SM_HEIGHT = 32; diff --git a/site/src/theme/light/mui.ts b/site/src/theme/light/mui.ts index 8092b5f8cbe80..85b7919b872e3 100644 --- a/site/src/theme/light/mui.ts +++ b/site/src/theme/light/mui.ts @@ -108,57 +108,6 @@ const muiTheme = createTheme({ }, }, }, - MuiButton: { - ...components.MuiButton, - styleOverrides: { - ...components.MuiButton.styleOverrides, - outlined: ({ theme }) => ({ - boxShadow: "0 1px 4px #0001", - ":hover": { - boxShadow: "0 1px 4px #0001", - border: `1px solid ${theme.palette.secondary.main}`, - }, - "&.Mui-disabled": { - boxShadow: "none !important", - }, - }), - ["outlinedNeutral" as MuiStyle]: { - borderColor: tw.zinc[300], - - "&.Mui-disabled": { - borderColor: tw.zinc[200], - color: tw.zinc[500], - - "& > .MuiLoadingButton-loadingIndicator": { - color: tw.zinc[500], - }, - }, - }, - contained: { - boxShadow: "0 1px 4px #0001", - "&.Mui-disabled": { - boxShadow: "none !important", - }, - ":hover": { - boxShadow: "0 1px 4px #0001", - }, - }, - ["containedNeutral" as MuiStyle]: { - backgroundColor: tw.zinc[100], - border: `1px solid ${tw.zinc[200]}`, - - "&.Mui-disabled": { - backgroundColor: tw.zinc[50], - border: `1px solid ${tw.zinc[100]}`, - }, - - "&:hover": { - backgroundColor: tw.zinc[200], - border: `1px solid ${tw.zinc[300]}`, - }, - }, - }, - }, MuiButtonGroup: { styleOverrides: { root: { diff --git a/site/src/theme/mui.ts b/site/src/theme/mui.ts index fc20b0a9f9be1..740f4c4a1e7c9 100644 --- a/site/src/theme/mui.ts +++ b/site/src/theme/mui.ts @@ -6,8 +6,6 @@ import { BODY_FONT_FAMILY, BUTTON_LG_HEIGHT, BUTTON_MD_HEIGHT, - BUTTON_SM_HEIGHT, - BUTTON_XL_HEIGHT, borderRadius, } from "./constants"; import tw from "./tailwindColors"; @@ -61,96 +59,6 @@ export const components = { }), }, }, - // Button styles are based on - // https://tailwindui.com/components/application-ui/elements/buttons - MuiButtonBase: { - defaultProps: { - disableRipple: true, - }, - }, - MuiButton: { - defaultProps: { - variant: "outlined", - color: "neutral", - }, - styleOverrides: { - root: ({ theme }) => ({ - textTransform: "none", - letterSpacing: "normal", - fontWeight: 500, - height: BUTTON_MD_HEIGHT, - padding: "8px 16px", - borderRadius: "6px", - fontSize: 14, - - whiteSpace: "nowrap", - ":focus-visible": { - outline: `2px solid ${theme.palette.primary.main}`, - }, - - "& .MuiLoadingButton-loadingIndicator": { - width: 14, - height: 14, - }, - - "& .MuiLoadingButton-loadingIndicator .MuiCircularProgress-root": { - width: "inherit !important", - height: "inherit !important", - }, - }), - sizeSmall: { - height: BUTTON_SM_HEIGHT, - }, - sizeLarge: { - height: BUTTON_LG_HEIGHT, - }, - ["sizeXlarge" as MuiStyle]: { - height: BUTTON_XL_HEIGHT, - - // With higher size we need to increase icon spacing. - "& .MuiButton-startIcon": { - marginRight: 12, - }, - "& .MuiButton-endIcon": { - marginLeft: 12, - }, - }, - outlined: ({ theme }) => ({ - ":hover": { - border: `1px solid ${theme.palette.secondary.main}`, - }, - }), - ["outlinedNeutral" as MuiStyle]: { - borderColor: tw.zinc[600], - - "&.Mui-disabled": { - borderColor: tw.zinc[700], - color: tw.zinc[500], - - "& > .MuiLoadingButton-loadingIndicator": { - color: tw.zinc[500], - }, - }, - }, - ["containedNeutral" as MuiStyle]: { - backgroundColor: tw.zinc[800], - - "&:hover": { - backgroundColor: tw.zinc[700], - }, - }, - iconSizeMedium: { - "& > .MuiSvgIcon-root": { - fontSize: 14, - }, - }, - iconSizeSmall: { - "& > .MuiSvgIcon-root": { - fontSize: 13, - }, - }, - }, - }, MuiButtonGroup: { styleOverrides: { root: ({ theme }) => ({ @@ -161,12 +69,6 @@ export const components = { }), }, }, - ["MuiLoadingButton" as MuiStyle]: { - defaultProps: { - variant: "outlined", - color: "neutral", - }, - }, MuiTableContainer: { styleOverrides: { root: ({ theme }) => ({ From f1d9bd693c705c035936358ead69c99032fa941b Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Tue, 7 Oct 2025 16:59:34 +0000 Subject: [PATCH 2/7] add lint --- biome.jsonc | 1 + 1 file changed, 1 insertion(+) diff --git a/biome.jsonc b/biome.jsonc index daa99a8b90ce4..d1258a77d65ae 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -51,6 +51,7 @@ "@mui/material/Popover": "Use components/Popover/Popover instead.", "@mui/material/Typography": "Use native HTML elements instead. Eg: ,

,

, etc.", "@mui/material/Box": "Use a
instead.", + "@mui/material/Button": "Use a components/Button/Button instead.", "@mui/material/styles": "Import from @emotion/react instead.", "lodash": "Use lodash/ instead." } From a6d0a823de23fbd015f9a4e983cd83cddbda84a9 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Tue, 7 Oct 2025 19:05:12 +0000 Subject: [PATCH 3/7] fixes --- site/src/components/Filter/Filter.tsx | 5 +- .../InputGroup/InputGroup.stories.tsx | 79 ------------------- site/src/components/InputGroup/InputGroup.tsx | 52 ------------ site/src/pages/HealthPage/DERPPage.tsx | 2 +- site/src/pages/LoginPage/OAuthSignInForm.tsx | 2 + .../ResetPasswordPage/ChangePasswordPage.tsx | 2 +- 6 files changed, 6 insertions(+), 136 deletions(-) delete mode 100644 site/src/components/InputGroup/InputGroup.stories.tsx delete mode 100644 site/src/components/InputGroup/InputGroup.tsx diff --git a/site/src/components/Filter/Filter.tsx b/site/src/components/Filter/Filter.tsx index 1ee162acccf99..447b0c01f49ab 100644 --- a/site/src/components/Filter/Filter.tsx +++ b/site/src/components/Filter/Filter.tsx @@ -10,7 +10,6 @@ import { isApiValidationError, } from "api/errors"; import { Button } from "components/Button/Button"; -import { InputGroup } from "components/InputGroup/InputGroup"; import { SearchField } from "components/SearchField/SearchField"; import { useDebouncedFunction } from "hooks/debounce"; import { ChevronDownIcon, ExternalLinkIcon } from "lucide-react"; @@ -219,7 +218,7 @@ export const Filter: FC = ({ ) : ( <> - +
filter.update(query)} presets={presets} @@ -251,7 +250,7 @@ export const Filter: FC = ({ }, }} /> - +
{options} )} diff --git a/site/src/components/InputGroup/InputGroup.stories.tsx b/site/src/components/InputGroup/InputGroup.stories.tsx deleted file mode 100644 index 2f048c8a8f41e..0000000000000 --- a/site/src/components/InputGroup/InputGroup.stories.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import TextField from "@mui/material/TextField"; -import type { Meta, StoryObj } from "@storybook/react-vite"; -import { Button } from "components/Button/Button"; -import { InputGroup } from "./InputGroup"; - -const meta: Meta = { - title: "components/InputGroup", - component: InputGroup, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: { - children: ( - <> - - - - ), - }, -}; - -export const FocusedTextField: Story = { - args: { - children: ( - <> - - - - ), - }, -}; - -export const ErroredTextField: Story = { - args: { - children: ( - <> - - - - ), - }, -}; - -export const FocusedErroredTextField: Story = { - args: { - children: ( - <> - - - - ), - }, -}; - -export const WithThreeElements: Story = { - args: { - children: ( - <> - - - - - ), - }, -}; diff --git a/site/src/components/InputGroup/InputGroup.tsx b/site/src/components/InputGroup/InputGroup.tsx deleted file mode 100644 index d2979a860b52d..0000000000000 --- a/site/src/components/InputGroup/InputGroup.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import type { FC, HTMLProps } from "react"; -export const InputGroup: FC> = (props) => { - return ( -
*:not(:last-child)": { - marginRight: -1, - }, - - // Ensure the border of the hovered element is visible when borders - // overlap. - "& > *:hover": { - zIndex: 1, - }, - - // Display border elements when focused or in an error state, both of - // which take priority over hover. - "& .Mui-focused, & .Mui-error": { - zIndex: 2, - }, - - "& > *:first-of-type": { - borderTopRightRadius: 0, - borderBottomRightRadius: 0, - }, - - "& > *:last-child": { - borderTopLeftRadius: 0, - borderBottomLeftRadius: 0, - - "&.MuiFormControl-root .MuiInputBase-root": { - borderTopLeftRadius: 0, - borderBottomLeftRadius: 0, - }, - }, - - "& > *:not(:first-of-type):not(:last-child)": { - borderRadius: 0, - - "&.MuiFormControl-root .MuiInputBase-root": { - borderRadius: 0, - }, - }, - }} - /> - ); -}; diff --git a/site/src/pages/HealthPage/DERPPage.tsx b/site/src/pages/HealthPage/DERPPage.tsx index 251082927ac47..3a913f23e05d5 100644 --- a/site/src/pages/HealthPage/DERPPage.tsx +++ b/site/src/pages/HealthPage/DERPPage.tsx @@ -100,7 +100,7 @@ const DERPPage: FC = () => { }) .map(({ severity, region }) => { return ( - - From f87bf377ad53d4038a371653f418815f590f3b46 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Tue, 7 Oct 2025 19:17:50 +0000 Subject: [PATCH 4/7] add input group back --- site/src/components/Filter/Filter.tsx | 5 +- .../InputGroup/InputGroup.stories.tsx | 81 +++++++++++++++++++ site/src/components/InputGroup/InputGroup.tsx | 52 ++++++++++++ 3 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 site/src/components/InputGroup/InputGroup.stories.tsx create mode 100644 site/src/components/InputGroup/InputGroup.tsx diff --git a/site/src/components/Filter/Filter.tsx b/site/src/components/Filter/Filter.tsx index 447b0c01f49ab..1ee162acccf99 100644 --- a/site/src/components/Filter/Filter.tsx +++ b/site/src/components/Filter/Filter.tsx @@ -10,6 +10,7 @@ import { isApiValidationError, } from "api/errors"; import { Button } from "components/Button/Button"; +import { InputGroup } from "components/InputGroup/InputGroup"; import { SearchField } from "components/SearchField/SearchField"; import { useDebouncedFunction } from "hooks/debounce"; import { ChevronDownIcon, ExternalLinkIcon } from "lucide-react"; @@ -218,7 +219,7 @@ export const Filter: FC = ({ ) : ( <> -
+ filter.update(query)} presets={presets} @@ -250,7 +251,7 @@ export const Filter: FC = ({ }, }} /> -
+ {options} )} diff --git a/site/src/components/InputGroup/InputGroup.stories.tsx b/site/src/components/InputGroup/InputGroup.stories.tsx new file mode 100644 index 0000000000000..728970af93c49 --- /dev/null +++ b/site/src/components/InputGroup/InputGroup.stories.tsx @@ -0,0 +1,81 @@ +import TextField from "@mui/material/TextField"; +import type { Meta, StoryObj } from "@storybook/react-vite"; +import { Button } from "components/Button/Button"; +import { InputGroup } from "./InputGroup"; + +const meta: Meta = { + title: "components/InputGroup", + component: InputGroup, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + children: ( + <> + + + + ), + }, +}; + +export const FocusedTextField: Story = { + args: { + children: ( + <> + + + + ), + }, +}; + +export const ErroredTextField: Story = { + args: { + children: ( + <> + + + + ), + }, +}; + +export const FocusedErroredTextField: Story = { + args: { + children: ( + <> + + + + ), + }, +}; + +export const WithThreeElements: Story = { + args: { + children: ( + <> + + + + + ), + }, +}; diff --git a/site/src/components/InputGroup/InputGroup.tsx b/site/src/components/InputGroup/InputGroup.tsx new file mode 100644 index 0000000000000..d2979a860b52d --- /dev/null +++ b/site/src/components/InputGroup/InputGroup.tsx @@ -0,0 +1,52 @@ +import type { FC, HTMLProps } from "react"; +export const InputGroup: FC> = (props) => { + return ( +
*:not(:last-child)": { + marginRight: -1, + }, + + // Ensure the border of the hovered element is visible when borders + // overlap. + "& > *:hover": { + zIndex: 1, + }, + + // Display border elements when focused or in an error state, both of + // which take priority over hover. + "& .Mui-focused, & .Mui-error": { + zIndex: 2, + }, + + "& > *:first-of-type": { + borderTopRightRadius: 0, + borderBottomRightRadius: 0, + }, + + "& > *:last-child": { + borderTopLeftRadius: 0, + borderBottomLeftRadius: 0, + + "&.MuiFormControl-root .MuiInputBase-root": { + borderTopLeftRadius: 0, + borderBottomLeftRadius: 0, + }, + }, + + "& > *:not(:first-of-type):not(:last-child)": { + borderRadius: 0, + + "&.MuiFormControl-root .MuiInputBase-root": { + borderRadius: 0, + }, + }, + }} + /> + ); +}; From 620d06b4ec0c0883a34fa63e12ec5142ca223b70 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Tue, 7 Oct 2025 19:27:33 +0000 Subject: [PATCH 5/7] remove icon size from oauth buttons --- site/src/pages/LoginPage/OAuthSignInForm.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/site/src/pages/LoginPage/OAuthSignInForm.tsx b/site/src/pages/LoginPage/OAuthSignInForm.tsx index 0b8094d4f5885..ed991edad2685 100644 --- a/site/src/pages/LoginPage/OAuthSignInForm.tsx +++ b/site/src/pages/LoginPage/OAuthSignInForm.tsx @@ -6,11 +6,6 @@ import { Button } from "components/Button/Button"; import { type FC, useId } from "react"; import { Language } from "./Language"; -const iconStyles = { - width: 16, - height: 16, -}; - type OAuthSignInFormProps = { isSigningIn: boolean; redirectTo: string; @@ -38,7 +33,7 @@ export const OAuthSignInForm: FC = ({ redirectTo, )}`} > - + {Language.githubSignIn} @@ -61,7 +56,7 @@ export const OAuthSignInForm: FC = ({ {authMethods.oidc.iconUrl ? ( ) : ( - + )} {authMethods.oidc.signInText || Language.oidcSignIn} From 40210a41e6aae6f03c0bef3d7059122ace43bb04 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Wed, 8 Oct 2025 16:26:04 +0000 Subject: [PATCH 6/7] remove unecessary mui styles --- site/src/theme/light/mui.ts | 10 ---------- site/src/theme/mui.ts | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/site/src/theme/light/mui.ts b/site/src/theme/light/mui.ts index 85b7919b872e3..8fe2e25b6ca0d 100644 --- a/site/src/theme/light/mui.ts +++ b/site/src/theme/light/mui.ts @@ -108,16 +108,6 @@ const muiTheme = createTheme({ }, }, }, - MuiButtonGroup: { - styleOverrides: { - root: { - ">button:hover+button": { - // The !important is unfortunate, but necessary for the border. - borderLeftColor: `${tw.zinc[300]} !important`, - }, - }, - }, - }, MuiChip: { styleOverrides: { root: { diff --git a/site/src/theme/mui.ts b/site/src/theme/mui.ts index 740f4c4a1e7c9..4435579a33153 100644 --- a/site/src/theme/mui.ts +++ b/site/src/theme/mui.ts @@ -59,16 +59,6 @@ export const components = { }), }, }, - MuiButtonGroup: { - styleOverrides: { - root: ({ theme }) => ({ - ">button:hover+button": { - // The !important is unfortunate, but necessary for the border. - borderLeftColor: `${theme.palette.secondary.main} !important`, - }, - }), - }, - }, MuiTableContainer: { styleOverrides: { root: ({ theme }) => ({ From 2eafc7738edb46b033aec1d5ab248dfa56fdd4a9 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Wed, 8 Oct 2025 16:28:24 +0000 Subject: [PATCH 7/7] fix lint --- site/src/pages/LoginPage/OAuthSignInForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/LoginPage/OAuthSignInForm.tsx b/site/src/pages/LoginPage/OAuthSignInForm.tsx index ed991edad2685..343353d18dfca 100644 --- a/site/src/pages/LoginPage/OAuthSignInForm.tsx +++ b/site/src/pages/LoginPage/OAuthSignInForm.tsx @@ -79,7 +79,7 @@ const OidcIcon: FC = ({ iconUrl }) => { // if that happens, but also still need a way to inject accessible text return ( <> - +
Open ID Connect