From 05c54d6decf2705ab273c7eb8aaf0624dc91bf68 Mon Sep 17 00:00:00 2001 From: Jake Howell Date: Tue, 4 Aug 2026 05:05:16 +0000 Subject: [PATCH 01/11] refactor(site): arrivederci mui --- site/.storybook/preview.tsx | 30 +- site/AGENTS.md | 21 +- site/package.json | 4 - site/pnpm-lock.yaml | 454 +----------------- site/src/@types/emotion.d.ts | 5 - site/src/@types/mui.d.ts | 19 - site/src/components/Command/Command.tsx | 5 +- site/src/components/Slider/Slider.tsx | 30 +- site/src/components/Switch/Switch.tsx | 7 +- .../SyntaxHighlighter/SyntaxHighlighter.tsx | 2 +- .../SyntaxHighlighter/coderTheme.ts | 3 +- site/src/components/Tabs/Tabs.tsx | 2 - site/src/contexts/ThemeProvider.tsx | 41 +- site/src/index.css | 17 +- .../WorkspaceTiming/ResourcesChart.tsx | 3 +- .../WorkspaceTiming/ScriptsChart.tsx | 3 +- .../components/ChatElements/Response.tsx | 5 +- .../ChatElements/tools/EditFilesTool.tsx | 2 +- .../ChatElements/tools/ReadFileTool.tsx | 2 +- .../components/ChatElements/tools/Tool.tsx | 2 +- .../ChatElements/tools/WriteFileTool.tsx | 2 +- .../components/DiffViewer/DiffViewer.tsx | 2 +- .../AnnouncementBannerDialog.tsx | 4 +- .../LicensesSettingsPageView.tsx | 2 +- .../MonacoEditor.tsx | 2 +- site/src/theme/appearance.tsx | 3 +- site/src/theme/constants.ts | 7 - site/src/theme/context.tsx | 26 + site/src/theme/dark/index.ts | 4 +- site/src/theme/dark/monaco.ts | 6 +- site/src/theme/dark/mui.ts | 84 ---- site/src/theme/dark/palette.ts | 21 + site/src/theme/darkProtanDeuter/index.ts | 4 +- site/src/theme/darkProtanDeuter/mui.ts | 12 - site/src/theme/darkTritan/index.ts | 4 +- site/src/theme/darkTritan/mui.ts | 9 - site/src/theme/index.ts | 9 +- site/src/theme/light/index.ts | 4 +- site/src/theme/light/monaco.ts | 6 +- site/src/theme/light/mui.ts | 185 ------- site/src/theme/light/palette.ts | 21 + site/src/theme/lightProtanDeuter/index.ts | 4 +- site/src/theme/lightProtanDeuter/mui.ts | 10 - site/src/theme/lightTritan/index.ts | 4 +- site/src/theme/lightTritan/mui.ts | 8 - site/src/theme/mui.ts | 222 --------- site/src/theme/palette.ts | 20 + site/tailwind.config.js | 3 - site/tsconfig.json | 1 - site/vite.config.mts | 55 +-- 50 files changed, 181 insertions(+), 1220 deletions(-) delete mode 100644 site/src/@types/emotion.d.ts delete mode 100644 site/src/@types/mui.d.ts create mode 100644 site/src/theme/context.tsx delete mode 100644 site/src/theme/dark/mui.ts create mode 100644 site/src/theme/dark/palette.ts delete mode 100644 site/src/theme/darkProtanDeuter/mui.ts delete mode 100644 site/src/theme/darkTritan/mui.ts delete mode 100644 site/src/theme/light/mui.ts create mode 100644 site/src/theme/light/palette.ts delete mode 100644 site/src/theme/lightProtanDeuter/mui.ts delete mode 100644 site/src/theme/lightTritan/mui.ts delete mode 100644 site/src/theme/mui.ts create mode 100644 site/src/theme/palette.ts diff --git a/site/.storybook/preview.tsx b/site/.storybook/preview.tsx index 5d554465f08a3..a3873be2f85aa 100644 --- a/site/.storybook/preview.tsx +++ b/site/.storybook/preview.tsx @@ -1,11 +1,5 @@ import "../src/index.css"; import "../src/theme/globalFonts"; -import { ThemeProvider as EmotionThemeProvider } from "@emotion/react"; -import CssBaseline from "@mui/material/CssBaseline"; -import { - ThemeProvider as MuiThemeProvider, - StyledEngineProvider, -} from "@mui/material/styles"; import { DecoratorHelpers } from "@storybook/addon-themes"; import type { Decorator, Parameters } from "@storybook/react-vite"; import { StrictMode } from "react"; @@ -14,6 +8,7 @@ import { withRouter } from "storybook-addon-remix-react-router"; import { TooltipProvider } from "../src/components/Tooltip/Tooltip"; import themes, { baseModeFor, isConcreteThemeName } from "../src/theme"; import { AppearanceProvider } from "../src/theme/appearance"; +import { ThemeContextProvider } from "../src/theme/context"; DecoratorHelpers.initializeThemeState(Object.keys(themes), "dark"); @@ -112,20 +107,15 @@ const withTheme: Decorator = (Story, context) => { return ( - - - - - - - - - - - - + + + + + + + ); }; diff --git a/site/AGENTS.md b/site/AGENTS.md index 915674b3c20a2..6640567b485c1 100644 --- a/site/AGENTS.md +++ b/site/AGENTS.md @@ -80,7 +80,6 @@ Debug logs and pprof dumps use the same job name and commit SHA convention. ## Components -- MUI components are deprecated - migrate away from these when encountered - Use shadcn/ui components first - check `site/src/components` for existing implementations. - Do not use shadcn CLI - manually add components to maintain consistency - The modules folder should contain components with business logic specific to the codebase. @@ -103,9 +102,8 @@ Debug logs and pprof dumps use the same job name and commit SHA convention. ## Styling -- Emotion CSS is deprecated. Use Tailwind CSS instead. +- Use Tailwind CSS for styling. - Use custom Tailwind classes in tailwind.config.js. -- Tailwind CSS reset is currently not used to maintain compatibility with MUI - Responsive design - use Tailwind's responsive prefixes (sm:, md:, lg:, xl:) - Do not use `dark:` prefix for dark mode @@ -279,23 +277,6 @@ Debug logs and pprof dumps use the same job name and commit SHA convention. audit the diff against FE1 to FE10 and fix every FAIL before creating the PR -## Migration (MUI → shadcn) (Emotion → Tailwind) - -### Migration Strategy - -- Identify MUI components in current feature -- Find shadcn equivalent in existing components -- Create wrapper if needed for missing functionality -- Update tests to reflect new component structure -- Remove MUI imports once migration complete - -### Migration Guidelines - -- Use Tailwind classes for all new styling -- Replace Emotion `css` prop with Tailwind classes -- Leverage custom color tokens: `content-primary`, `surface-secondary`, etc. -- Use `className` with `clsx` for conditional styling - ## React Rules ### 1. Purity & Immutability diff --git a/site/package.json b/site/package.json index 56b7969b80a58..e187e3c9b825d 100644 --- a/site/package.json +++ b/site/package.json @@ -42,9 +42,6 @@ "@dnd-kit/utilities": "3.2.2", "@emoji-mart/data": "1.2.1", "@emoji-mart/react": "1.1.1", - "@emotion/cache": "11.14.0", - "@emotion/react": "11.14.0", - "@emotion/styled": "11.14.1", "@fontsource-variable/geist": "5.3.0", "@fontsource-variable/geist-mono": "5.2.7", "@fontsource/fira-code": "5.2.7", @@ -54,7 +51,6 @@ "@lexical/react": "0.44.0", "@lexical/utils": "0.48.0", "@monaco-editor/react": "4.7.0", - "@mui/material": "5.18.0", "@novnc/novnc": "^1.5.0", "@pierre/diffs": "1.2.7", "@pierre/trees": "1.0.0-beta.4", diff --git a/site/pnpm-lock.yaml b/site/pnpm-lock.yaml index b3c6980da951a..6d1f26c735062 100644 --- a/site/pnpm-lock.yaml +++ b/site/pnpm-lock.yaml @@ -47,15 +47,6 @@ importers: '@emoji-mart/react': specifier: 1.1.1 version: 1.1.1(emoji-mart@5.6.0)(react@19.2.8) - '@emotion/cache': - specifier: 11.14.0 - version: 11.14.0 - '@emotion/react': - specifier: 11.14.0 - version: 11.14.0(@types/react@19.2.17)(react@19.2.8) - '@emotion/styled': - specifier: 11.14.1 - version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8) '@fontsource-variable/geist': specifier: 5.3.0 version: 5.3.0 @@ -83,9 +74,6 @@ importers: '@monaco-editor/react': specifier: 4.7.0 version: 4.7.0(monaco-editor@0.55.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) - '@mui/material': - specifier: 5.18.0 - version: 5.18.0(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@novnc/novnc': specifier: ^1.5.0 version: 1.5.0 @@ -513,10 +501,6 @@ packages: resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==, tarball: https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.27.1': - resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==, tarball: https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz} - engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.29.7': resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==, tarball: https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz} engines: {node: '>=6.9.0'} @@ -765,60 +749,12 @@ packages: emoji-mart: ^5.2 react: ^16.8 || ^17 || ^18 - '@emotion/babel-plugin@11.13.5': - resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==, tarball: https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz} - - '@emotion/cache@11.14.0': - resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==, tarball: https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz} - - '@emotion/hash@0.9.2': - resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==, tarball: https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz} - '@emotion/is-prop-valid@1.4.0': resolution: {integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==, tarball: https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz} '@emotion/memoize@0.9.0': resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==, tarball: https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz} - '@emotion/react@11.14.0': - resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==, tarball: https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz} - peerDependencies: - '@types/react': '*' - react: '>=16.8.0' - peerDependenciesMeta: - '@types/react': - optional: true - - '@emotion/serialize@1.3.3': - resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==, tarball: https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz} - - '@emotion/sheet@1.4.0': - resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==, tarball: https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz} - - '@emotion/styled@11.14.1': - resolution: {integrity: sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==, tarball: https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz} - peerDependencies: - '@emotion/react': ^11.0.0-rc.0 - '@types/react': '*' - react: '>=16.8.0' - peerDependenciesMeta: - '@types/react': - optional: true - - '@emotion/unitless@0.10.0': - resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==, tarball: https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz} - - '@emotion/use-insertion-effect-with-fallbacks@1.2.0': - resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==, tarball: https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz} - peerDependencies: - react: '>=16.8.0' - - '@emotion/utils@1.4.2': - resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==, tarball: https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz} - - '@emotion/weak-memoize@0.4.0': - resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==, tarball: https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz} - '@esbuild/aix-ppc64@0.25.12': resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==, tarball: https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz} engines: {node: '>=18'} @@ -1212,83 +1148,6 @@ packages: resolution: {integrity: sha512-SSnyl/4ni/2ViHKkiZb8eajA/eN1DNFaHjhGiLUdZvDz6PKF4COSf/17xqSz64nOo2Ia29SA6B2KNCsyCbVmaQ==, tarball: https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.35.9.tgz} engines: {node: '>=18'} - '@mui/core-downloads-tracker@5.18.0': - resolution: {integrity: sha512-jbhwoQ1AY200PSSOrNXmrFCaSDSJWP7qk6urkTmIirvRXDROkqe+QwcLlUiw/PrREwsIF/vm3/dAXvjlMHF0RA==, tarball: https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.18.0.tgz} - - '@mui/material@5.18.0': - resolution: {integrity: sha512-bbH/HaJZpFtXGvWg3TsBWG4eyt3gah3E7nCNU8GLyRjVoWcA91Vm/T+sjHfUcwgJSw9iLtucfHBoq+qW/T30aA==, tarball: https://registry.npmjs.org/@mui/material/-/material-5.18.0.tgz} - engines: {node: '>=12.0.0'} - peerDependencies: - '@emotion/react': ^11.5.0 - '@emotion/styled': ^11.3.0 - '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 - react: ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': - optional: true - '@types/react': - optional: true - - '@mui/private-theming@5.17.1': - resolution: {integrity: sha512-XMxU0NTYcKqdsG8LRmSoxERPXwMbp16sIXPcLVgLGII/bVNagX0xaheWAwFv8+zDK7tI3ajllkuD3GZZE++ICQ==, tarball: https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.17.1.tgz} - engines: {node: '>=12.0.0'} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 - react: ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - - '@mui/styled-engine@5.18.0': - resolution: {integrity: sha512-BN/vKV/O6uaQh2z5rXV+MBlVrEkwoS/TK75rFQ2mjxA7+NBo8qtTAOA4UaM0XeJfn7kh2wZ+xQw2HAx0u+TiBg==, tarball: https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.18.0.tgz} - engines: {node: '>=12.0.0'} - peerDependencies: - '@emotion/react': ^11.4.1 - '@emotion/styled': ^11.3.0 - react: ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': - optional: true - - '@mui/system@5.18.0': - resolution: {integrity: sha512-ojZGVcRWqWhu557cdO3pWHloIGJdzVtxs3rk0F9L+x55LsUjcMUVkEhiF7E4TMxZoF9MmIHGGs0ZX3FDLAf0Xw==, tarball: https://registry.npmjs.org/@mui/system/-/system-5.18.0.tgz} - engines: {node: '>=12.0.0'} - peerDependencies: - '@emotion/react': ^11.5.0 - '@emotion/styled': ^11.3.0 - '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 - react: ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': - optional: true - '@types/react': - optional: true - - '@mui/types@7.2.24': - resolution: {integrity: sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==, tarball: https://registry.npmjs.org/@mui/types/-/types-7.2.24.tgz} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - - '@mui/utils@5.17.1': - resolution: {integrity: sha512-jEZ8FTqInt2WzxDV8bhImWBqeQRD99c/id/fq83H0ER9tFl+sfZlaAoCdznGvbSQQ9ividMxqSV2c7cC1vBcQg==, tarball: https://registry.npmjs.org/@mui/utils/-/utils-5.17.1.tgz} - engines: {node: '>=12.0.0'} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 - react: ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@napi-rs/wasm-runtime@1.0.7': resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==, tarball: https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz} @@ -1472,9 +1331,6 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==, tarball: https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz} - '@popperjs/core@2.11.8': - resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==, tarball: https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz} - '@preact/signals-core@1.14.2': resolution: {integrity: sha512-RZHdBj9ZF4n40Rp4jS052EHHjBWf96P9oNdXPfhQTovCuWY9iQn3Gq+gOTJSgBO9A/JBuPfMOWsSX/lIU9Pc/A==, tarball: https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.14.2.tgz} @@ -2858,12 +2714,6 @@ packages: '@types/novnc__novnc@1.5.0': resolution: {integrity: sha512-9DrDJK1hUT6Cbp4t03IsU/DsR6ndnIrDgZVrzITvspldHQ7n81F3wUDfq89zmPM3wg4GErH11IQa0QuTgLMf+w==, tarball: https://registry.npmjs.org/@types/novnc__novnc/-/novnc__novnc-1.5.0.tgz} - '@types/parse-json@4.0.2': - resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==, tarball: https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz} - - '@types/prop-types@15.7.15': - resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==, tarball: https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz} - '@types/qs@6.9.7': resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==, tarball: https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz} @@ -2888,11 +2738,6 @@ packages: '@types/react-syntax-highlighter@15.5.13': resolution: {integrity: sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==, tarball: https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz} - '@types/react-transition-group@4.4.12': - resolution: {integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==, tarball: https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz} - peerDependencies: - '@types/react': '*' - '@types/react-virtualized-auto-sizer@1.0.8': resolution: {integrity: sha512-keJpNyhiwfl2+N12G1ocCVA5ZDBArbPLe/S90X3kt7fam9naeHdaYYWbpe2sHczp70JWJ+2QLhBE8kLvLuVNjA==, tarball: https://registry.npmjs.org/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.8.tgz} deprecated: This is a stub types definition. react-virtualized-auto-sizer provides its own type definitions, so you do not need this installed. @@ -3173,10 +3018,6 @@ packages: axios@1.18.1: resolution: {integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==, tarball: https://registry.npmjs.org/axios/-/axios-1.18.1.tgz} - babel-plugin-macros@3.1.0: - resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==, tarball: https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz} - engines: {node: '>=10', npm: '>=6'} - babel-plugin-react-compiler@1.0.0: resolution: {integrity: sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==, tarball: https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz} @@ -3258,10 +3099,6 @@ packages: resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==, tarball: https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz} engines: {node: '>= 0.4'} - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, tarball: https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz} - engines: {node: '>=6'} - camelcase-css@2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==, tarball: https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz} engines: {node: '>= 6'} @@ -3419,9 +3256,6 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==, tarball: https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz} engines: {node: '>= 0.6'} - convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==, tarball: https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz} - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==, tarball: https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz} @@ -3445,10 +3279,6 @@ packages: cose-base@2.2.0: resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==, tarball: https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz} - cosmiconfig@7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==, tarball: https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz} - engines: {node: '>=10'} - cpu-features@0.0.10: resolution: {integrity: sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==, tarball: https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz} engines: {node: '>=10.0.0'} @@ -3484,9 +3314,6 @@ packages: resolution: {integrity: sha512-OytmFH+13/QXONJcC75QNdMtKpceNk3u8ThBjyyYjkEcy/ekBwR1mMAuNvi3gdBPW3N5TlCzQ0WZw8H0lN/bDw==, tarball: https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.3.tgz} engines: {node: '>=20'} - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==, tarball: https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz} - csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==, tarball: https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz} @@ -3842,9 +3669,6 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==, tarball: https://registry.npmjs.org/entities/-/entities-6.0.1.tgz} engines: {node: '>=0.12'} - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==, tarball: https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz} - es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, tarball: https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz} engines: {node: '>= 0.4'} @@ -3879,10 +3703,6 @@ packages: escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==, tarball: https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz} - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, tarball: https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz} - engines: {node: '>=10'} - escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==, tarball: https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz} engines: {node: '>=12'} @@ -3969,9 +3789,6 @@ packages: resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==, tarball: https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz} engines: {node: '>= 0.8'} - find-root@1.1.0: - resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==, tarball: https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz} - follow-redirects@1.16.0: resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==, tarball: https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz} engines: {node: '>=4.0'} @@ -4222,10 +4039,6 @@ packages: immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==, tarball: https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz} - import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==, tarball: https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz} - engines: {node: '>=6'} - indent-string@4.0.0: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==, tarball: https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz} engines: {node: '>=8'} @@ -4270,9 +4083,6 @@ packages: is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==, tarball: https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz} - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==, tarball: https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz} - is-bigint@1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==, tarball: https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz} @@ -4457,9 +4267,6 @@ packages: engines: {node: '>=6'} hasBin: true - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, tarball: https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz} - json-rpc-2.0@1.7.1: resolution: {integrity: sha512-JqZjhjAanbpkXIzFE7u8mE/iFblawwlXtONaCvRqI+pyABVz7B4M1EUNpyVW+dZjqgQ2L5HFmZCmOCgUKm00hg==, tarball: https://registry.npmjs.org/json-rpc-2.0/-/json-rpc-2.0-1.7.1.tgz} @@ -5043,20 +4850,12 @@ packages: pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==, tarball: https://registry.npmjs.org/pako/-/pako-1.0.11.tgz} - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, tarball: https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz} - engines: {node: '>=6'} - parse-entities@2.0.0: resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==, tarball: https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz} parse-entities@4.0.2: resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==, tarball: https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz} - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, tarball: https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz} - engines: {node: '>=8'} - parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==, tarball: https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz} @@ -5097,10 +4896,6 @@ packages: path-to-regexp@6.3.0: resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==, tarball: https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz} - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, tarball: https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz} - engines: {node: '>=8'} - pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==, tarball: https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz} @@ -5380,9 +5175,6 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==, tarball: https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz} - react-is@19.1.1: - resolution: {integrity: sha512-tr41fA15Vn8p4X9ntI+yCyeGSf1TlYaY5vlTZfQmeLBrFo3psOPX6HhTDnFNL9uj3EhP0KAQ80cugCl4b4BERA==, tarball: https://registry.npmjs.org/react-is/-/react-is-19.1.1.tgz} - react-markdown@9.1.0: resolution: {integrity: sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw==, tarball: https://registry.npmjs.org/react-markdown/-/react-markdown-9.1.0.tgz} peerDependencies: @@ -5574,10 +5366,6 @@ packages: resize-observer-polyfill@1.5.1: resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==, tarball: https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz} - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, tarball: https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz} - engines: {node: '>=4'} - resolve@1.22.11: resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==, tarball: https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz} engines: {node: '>= 0.4'} @@ -5746,10 +5534,6 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==, tarball: https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz} engines: {node: '>=0.10.0'} - source-map@0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==, tarball: https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz} - engines: {node: '>=0.10.0'} - source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, tarball: https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz} engines: {node: '>=0.10.0'} @@ -5873,9 +5657,6 @@ packages: style-to-object@1.0.9: resolution: {integrity: sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==, tarball: https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.9.tgz} - stylis@4.2.0: - resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==, tarball: https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz} - stylis@4.3.6: resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==, tarball: https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz} @@ -6637,13 +6418,6 @@ snapshots: '@babel/helper-globals@7.29.7': {} - '@babel/helper-module-imports@7.27.1': - dependencies: - '@babel/traverse': 7.29.7 - '@babel/types': 7.29.7 - transitivePeerDependencies: - - supports-color - '@babel/helper-module-imports@7.29.7': dependencies: '@babel/traverse': 7.29.7 @@ -6884,88 +6658,13 @@ snapshots: emoji-mart: 5.6.0 react: 19.2.8 - '@emotion/babel-plugin@11.13.5': - dependencies: - '@babel/helper-module-imports': 7.27.1 - '@babel/runtime': 7.26.10 - '@emotion/hash': 0.9.2 - '@emotion/memoize': 0.9.0 - '@emotion/serialize': 1.3.3 - babel-plugin-macros: 3.1.0 - convert-source-map: 1.9.0 - escape-string-regexp: 4.0.0 - find-root: 1.1.0 - source-map: 0.5.7 - stylis: 4.2.0 - transitivePeerDependencies: - - supports-color - - '@emotion/cache@11.14.0': - dependencies: - '@emotion/memoize': 0.9.0 - '@emotion/sheet': 1.4.0 - '@emotion/utils': 1.4.2 - '@emotion/weak-memoize': 0.4.0 - stylis: 4.2.0 - - '@emotion/hash@0.9.2': {} - '@emotion/is-prop-valid@1.4.0': dependencies: '@emotion/memoize': 0.9.0 + optional: true - '@emotion/memoize@0.9.0': {} - - '@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8)': - dependencies: - '@babel/runtime': 7.26.10 - '@emotion/babel-plugin': 11.13.5 - '@emotion/cache': 11.14.0 - '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.8) - '@emotion/utils': 1.4.2 - '@emotion/weak-memoize': 0.4.0 - hoist-non-react-statics: 3.3.2 - react: 19.2.8 - optionalDependencies: - '@types/react': 19.2.17 - transitivePeerDependencies: - - supports-color - - '@emotion/serialize@1.3.3': - dependencies: - '@emotion/hash': 0.9.2 - '@emotion/memoize': 0.9.0 - '@emotion/unitless': 0.10.0 - '@emotion/utils': 1.4.2 - csstype: 3.2.3 - - '@emotion/sheet@1.4.0': {} - - '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8)': - dependencies: - '@babel/runtime': 7.26.10 - '@emotion/babel-plugin': 11.13.5 - '@emotion/is-prop-valid': 1.4.0 - '@emotion/react': 11.14.0(@types/react@19.2.17)(react@19.2.8) - '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.8) - '@emotion/utils': 1.4.2 - react: 19.2.8 - optionalDependencies: - '@types/react': 19.2.17 - transitivePeerDependencies: - - supports-color - - '@emotion/unitless@0.10.0': {} - - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.8)': - dependencies: - react: 19.2.8 - - '@emotion/utils@1.4.2': {} - - '@emotion/weak-memoize@0.4.0': {} + '@emotion/memoize@0.9.0': + optional: true '@esbuild/aix-ppc64@0.25.12': optional: true @@ -7380,82 +7079,6 @@ snapshots: outvariant: 1.4.3 strict-event-emitter: 0.5.1 - '@mui/core-downloads-tracker@5.18.0': {} - - '@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': - dependencies: - '@babel/runtime': 7.26.10 - '@mui/core-downloads-tracker': 5.18.0 - '@mui/system': 5.18.0(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8) - '@mui/types': 7.2.24(@types/react@19.2.17) - '@mui/utils': 5.17.1(@types/react@19.2.17)(react@19.2.8) - '@popperjs/core': 2.11.8 - '@types/react-transition-group': 4.4.12(@types/react@19.2.17) - clsx: 2.1.1 - csstype: 3.1.3 - prop-types: 15.8.1 - react: 19.2.8 - react-dom: 19.2.8(react@19.2.8) - react-is: 19.1.1 - react-transition-group: 4.4.5(react-dom@19.2.8(react@19.2.8))(react@19.2.8) - optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.2.17)(react@19.2.8) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8) - '@types/react': 19.2.17 - - '@mui/private-theming@5.17.1(@types/react@19.2.17)(react@19.2.8)': - dependencies: - '@babel/runtime': 7.26.10 - '@mui/utils': 5.17.1(@types/react@19.2.17)(react@19.2.8) - prop-types: 15.8.1 - react: 19.2.8 - optionalDependencies: - '@types/react': 19.2.17 - - '@mui/styled-engine@5.18.0(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8))(react@19.2.8)': - dependencies: - '@babel/runtime': 7.26.10 - '@emotion/cache': 11.14.0 - '@emotion/serialize': 1.3.3 - csstype: 3.2.3 - prop-types: 15.8.1 - react: 19.2.8 - optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.2.17)(react@19.2.8) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8) - - '@mui/system@5.18.0(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8)': - dependencies: - '@babel/runtime': 7.26.10 - '@mui/private-theming': 5.17.1(@types/react@19.2.17)(react@19.2.8) - '@mui/styled-engine': 5.18.0(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8))(react@19.2.8) - '@mui/types': 7.2.24(@types/react@19.2.17) - '@mui/utils': 5.17.1(@types/react@19.2.17)(react@19.2.8) - clsx: 2.1.1 - csstype: 3.1.3 - prop-types: 15.8.1 - react: 19.2.8 - optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.2.17)(react@19.2.8) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.17)(react@19.2.8))(@types/react@19.2.17)(react@19.2.8) - '@types/react': 19.2.17 - - '@mui/types@7.2.24(@types/react@19.2.17)': - optionalDependencies: - '@types/react': 19.2.17 - - '@mui/utils@5.17.1(@types/react@19.2.17)(react@19.2.8)': - dependencies: - '@babel/runtime': 7.26.10 - '@mui/types': 7.2.24(@types/react@19.2.17) - '@types/prop-types': 15.7.15 - clsx: 2.1.1 - prop-types: 15.8.1 - react: 19.2.8 - react-is: 19.1.1 - optionalDependencies: - '@types/react': 19.2.17 - '@napi-rs/wasm-runtime@1.0.7': dependencies: '@emnapi/core': 1.11.2 @@ -7598,8 +7221,6 @@ snapshots: '@polka/url@1.0.0-next.29': {} - '@popperjs/core@2.11.8': {} - '@preact/signals-core@1.14.2': {} '@protobufjs/aspromise@1.1.2': {} @@ -9021,10 +8642,6 @@ snapshots: '@types/novnc__novnc@1.5.0': {} - '@types/parse-json@4.0.2': {} - - '@types/prop-types@15.7.15': {} - '@types/qs@6.9.7': {} '@types/range-parser@1.2.4': {} @@ -9046,10 +8663,6 @@ snapshots: dependencies: '@types/react': 19.2.17 - '@types/react-transition-group@4.4.12(@types/react@19.2.17)': - dependencies: - '@types/react': 19.2.17 - '@types/react-virtualized-auto-sizer@1.0.8(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: react-virtualized-auto-sizer: 1.0.26(react-dom@19.2.8(react@19.2.8))(react@19.2.8) @@ -9360,12 +8973,6 @@ snapshots: - debug - supports-color - babel-plugin-macros@3.1.0: - dependencies: - '@babel/runtime': 7.26.10 - cosmiconfig: 7.1.0 - resolve: 1.22.12 - babel-plugin-react-compiler@1.0.0: dependencies: '@babel/types': 7.28.5 @@ -9469,8 +9076,6 @@ snapshots: call-bind-apply-helpers: 1.0.2 get-intrinsic: 1.3.0 - callsites@3.1.0: {} - camelcase-css@2.0.1: {} caniuse-lite@1.0.30001806: {} @@ -9616,8 +9221,6 @@ snapshots: content-type@1.0.5: {} - convert-source-map@1.9.0: {} - convert-source-map@2.0.0: {} cookie-signature@1.0.7: {} @@ -9636,14 +9239,6 @@ snapshots: dependencies: layout-base: 2.0.1 - cosmiconfig@7.1.0: - dependencies: - '@types/parse-json': 4.0.2 - import-fresh: 3.3.1 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 2.8.3 - cpu-features@0.0.10: dependencies: buildcheck: 0.0.6 @@ -9679,8 +9274,6 @@ snapshots: '@csstools/css-syntax-patches-for-csstree': 1.0.20 css-tree: 3.1.0 - csstype@3.1.3: {} - csstype@3.2.3: {} cytoscape-cose-bilkent@4.1.0(cytoscape@3.33.1): @@ -10044,10 +9637,6 @@ snapshots: entities@6.0.1: {} - error-ex@1.3.2: - dependencies: - is-arrayish: 0.2.1 - es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -10110,8 +9699,6 @@ snapshots: escape-html@1.0.3: {} - escape-string-regexp@4.0.0: {} - escape-string-regexp@5.0.0: {} esm-env@1.2.2: {} @@ -10223,8 +9810,6 @@ snapshots: transitivePeerDependencies: - supports-color - find-root@1.1.0: {} - follow-redirects@1.16.0: {} for-each@0.3.4: @@ -10539,11 +10124,6 @@ snapshots: immediate@3.0.6: {} - import-fresh@3.3.1: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - indent-string@4.0.0: {} inherits@2.0.4: {} @@ -10587,8 +10167,6 @@ snapshots: get-intrinsic: 1.3.0 is-typed-array: 1.1.15 - is-arrayish@0.2.1: {} - is-bigint@1.0.4: dependencies: has-bigints: 1.0.2 @@ -10765,8 +10343,6 @@ snapshots: jsesc@3.1.0: {} - json-parse-even-better-errors@2.3.1: {} - json-rpc-2.0@1.7.1: {} json5@2.2.3: {} @@ -11558,10 +11134,6 @@ snapshots: pako@1.0.11: {} - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - parse-entities@2.0.0: dependencies: character-entities: 1.2.4 @@ -11581,13 +11153,6 @@ snapshots: is-decimal: 2.0.1 is-hexadecimal: 2.0.1 - parse-json@5.2.0: - dependencies: - '@babel/code-frame': 7.29.7 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - parse5@7.3.0: dependencies: entities: 6.0.1 @@ -11619,8 +11184,6 @@ snapshots: path-to-regexp@6.3.0: {} - path-type@4.0.0: {} - pathe@2.0.3: {} pathval@2.0.1: {} @@ -11937,8 +11500,6 @@ snapshots: react-is@18.3.1: {} - react-is@19.1.1: {} - react-markdown@9.1.0(@types/react@19.2.17)(react@19.2.8): dependencies: '@types/hast': 3.0.4 @@ -12191,8 +11752,6 @@ snapshots: resize-observer-polyfill@1.5.1: {} - resolve-from@4.0.0: {} - resolve@1.22.11: dependencies: is-core-module: 2.16.1 @@ -12425,8 +11984,6 @@ snapshots: source-map-js@1.2.1: {} - source-map@0.5.7: {} - source-map@0.6.1: {} source-map@0.7.4: {} @@ -12575,8 +12132,6 @@ snapshots: dependencies: inline-style-parser: 0.2.4 - stylis@4.2.0: {} - stylis@4.3.6: {} sucrase@3.35.1: @@ -13134,7 +12689,8 @@ snapshots: yallist@3.1.1: {} - yaml@2.8.3: {} + yaml@2.8.3: + optional: true yargs-parser@21.1.1: {} diff --git a/site/src/@types/emotion.d.ts b/site/src/@types/emotion.d.ts deleted file mode 100644 index 6724c41e40891..0000000000000 --- a/site/src/@types/emotion.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { Theme as CoderTheme } from "#/theme"; - -declare module "@emotion/react" { - interface Theme extends CoderTheme {} -} diff --git a/site/src/@types/mui.d.ts b/site/src/@types/mui.d.ts deleted file mode 100644 index 5128ae7b1953a..0000000000000 --- a/site/src/@types/mui.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { PaletteColor, PaletteColorOptions } from "@mui/material/styles"; - -declare module "@mui/material/styles" { - interface Palette { - neutral: PaletteColor; - dots: string; - } - - interface PaletteOptions { - neutral?: PaletteColorOptions; - dots?: string; - } -} - -declare module "@mui/material/Checkbox" { - interface CheckboxPropsSizeOverrides { - xsmall: true; - } -} diff --git a/site/src/components/Command/Command.tsx b/site/src/components/Command/Command.tsx index e59377acbde0d..45bd67572c8f1 100644 --- a/site/src/components/Command/Command.tsx +++ b/site/src/components/Command/Command.tsx @@ -40,10 +40,7 @@ export const CommandList: React.FC< > = ({ className, ...props }) => { return ( ); diff --git a/site/src/components/Slider/Slider.tsx b/site/src/components/Slider/Slider.tsx index c2e4704e10cb7..21ddaa690f371 100644 --- a/site/src/components/Slider/Slider.tsx +++ b/site/src/components/Slider/Slider.tsx @@ -7,31 +7,37 @@ import { cn } from "#/utils/cn"; export const Slider: React.FC< React.ComponentPropsWithRef -> = ({ className, ...props }) => { +> = ({ className, defaultValue, value, min = 0, max = 100, ...props }) => { + const thumbCount = Array.isArray(value) + ? value.length + : Array.isArray(defaultValue) + ? defaultValue.length + : 1; + return ( - - + /> + ))} ); }; diff --git a/site/src/components/Switch/Switch.tsx b/site/src/components/Switch/Switch.tsx index 03c9eea16ac6e..3a4d63e70f8cf 100644 --- a/site/src/components/Switch/Switch.tsx +++ b/site/src/components/Switch/Switch.tsx @@ -29,13 +29,12 @@ const switchVariants = cva( ); const thumbVariants = cva( - "pointer-events-none block rounded-full bg-surface-primary shadow-lg ring-0 transition-transform", + "pointer-events-none block rounded-full bg-surface-primary shadow-lg ring-0 transition-transform data-[state=unchecked]:translate-x-0", { variants: { size: { - default: - "size-4 data-[state=checked]:translate-x-2.5 data-[state=unchecked]:-translate-x-1.5", - sm: "size-3 data-[state=checked]:translate-x-1.5 data-[state=unchecked]:-translate-x-1.5", + default: "size-4 data-[state=checked]:translate-x-4", + sm: "size-3 data-[state=checked]:translate-x-3", }, }, defaultVariants: { diff --git a/site/src/components/SyntaxHighlighter/SyntaxHighlighter.tsx b/site/src/components/SyntaxHighlighter/SyntaxHighlighter.tsx index 68d9e140ce528..ed072a89e5a59 100644 --- a/site/src/components/SyntaxHighlighter/SyntaxHighlighter.tsx +++ b/site/src/components/SyntaxHighlighter/SyntaxHighlighter.tsx @@ -1,8 +1,8 @@ -import { useTheme } from "@emotion/react"; import Editor, { DiffEditor, loader } from "@monaco-editor/react"; import type * as Monaco from "monaco-editor"; import * as monaco from "monaco-editor"; import { type ComponentProps, type FC, useCallback } from "react"; +import { useTheme } from "#/theme/context"; import { useCoderTheme } from "./coderTheme"; loader.config({ monaco }); diff --git a/site/src/components/SyntaxHighlighter/coderTheme.ts b/site/src/components/SyntaxHighlighter/coderTheme.ts index 0150ff3f1ab15..caecbf2fe6fa1 100644 --- a/site/src/components/SyntaxHighlighter/coderTheme.ts +++ b/site/src/components/SyntaxHighlighter/coderTheme.ts @@ -1,6 +1,7 @@ -import { useTheme } from "@emotion/react"; import { useMonaco } from "@monaco-editor/react"; import { useEffect, useState } from "react"; +import { useTheme } from "#/theme/context"; + export const useCoderTheme = (): { isLoading: boolean; name: string } => { const [isLoading, setIsLoading] = useState(true); const monaco = useMonaco(); diff --git a/site/src/components/Tabs/Tabs.tsx b/site/src/components/Tabs/Tabs.tsx index 6548ec9dac124..b519047b16f18 100644 --- a/site/src/components/Tabs/Tabs.tsx +++ b/site/src/components/Tabs/Tabs.tsx @@ -128,8 +128,6 @@ export const LinkTabs = ({
= ({ children }) => { const theme = themes[concreteName]; - return ( - - {children} - - ); + return {children}; }; -// This is being added to allow Tailwind classes to be used with MUI components. https://mui.com/material-ui/integrations/interoperability/#tailwind-css -const cache = createCache({ - key: "css", - prepend: true, -}); - interface ThemeOverrideProps { theme: Theme; children?: ReactNode; @@ -78,15 +56,10 @@ interface ThemeOverrideProps { export const ThemeOverride: FC = ({ theme, children }) => { return ( - - - - - - {children} - - - - + + + {children} + + ); }; diff --git a/site/src/index.css b/site/src/index.css index ef882c1a9ea48..f81ccea53fe7e 100644 --- a/site/src/index.css +++ b/site/src/index.css @@ -364,6 +364,10 @@ @apply h-full; } + body { + @apply bg-surface-primary text-content-primary font-sans antialiased; + } + button, input { @apply font-sans; @@ -417,19 +421,6 @@ overflow-y: scroll !important; } } - - /* - This is a temporary fix for MUI Modals/Popovers until they are removed. - When html has scrollbar-gutter: stable, the browser reserves space for the scrollbar. - MUI Modals/Popovers, when locking body scroll, add `overflow: hidden` and `padding-right` - to the body to compensate for the scrollbar they are hiding. This added padding-right - conflicts with the already reserved gutter space, causing a layout shift. - This rule overrides MUI's added padding-right on the body specifically when MUI - is likely to have set both overflow:hidden and padding-right. - */ - body[style*="overflow: hidden"][style*="padding-right"] { - padding-right: 0px; - } } @layer utilities { diff --git a/site/src/modules/workspaces/WorkspaceTiming/ResourcesChart.tsx b/site/src/modules/workspaces/WorkspaceTiming/ResourcesChart.tsx index da936ef54e50d..d543215d73211 100644 --- a/site/src/modules/workspaces/WorkspaceTiming/ResourcesChart.tsx +++ b/site/src/modules/workspaces/WorkspaceTiming/ResourcesChart.tsx @@ -1,4 +1,3 @@ -import { type Theme, useTheme } from "@emotion/react"; import { ExternalLinkIcon } from "lucide-react"; import { type FC, useState } from "react"; import { Link } from "react-router"; @@ -7,6 +6,8 @@ import { TooltipContent, TooltipTrigger, } from "#/components/Tooltip/Tooltip"; +import type { Theme } from "#/theme"; +import { useTheme } from "#/theme/context"; import { Bar } from "./Chart/Bar"; import { Chart, diff --git a/site/src/modules/workspaces/WorkspaceTiming/ScriptsChart.tsx b/site/src/modules/workspaces/WorkspaceTiming/ScriptsChart.tsx index 1e51d025284c4..ec3d540b352f3 100644 --- a/site/src/modules/workspaces/WorkspaceTiming/ScriptsChart.tsx +++ b/site/src/modules/workspaces/WorkspaceTiming/ScriptsChart.tsx @@ -1,10 +1,11 @@ -import { type Theme, useTheme } from "@emotion/react"; import { type FC, useState } from "react"; import { Tooltip, TooltipContent, TooltipTrigger, } from "#/components/Tooltip/Tooltip"; +import type { Theme } from "#/theme"; +import { useTheme } from "#/theme/context"; import { Bar } from "./Chart/Bar"; import { Chart, diff --git a/site/src/pages/AgentsPage/components/ChatElements/Response.tsx b/site/src/pages/AgentsPage/components/ChatElements/Response.tsx index 01fbb6e3f228a..6f75d3b579b71 100644 --- a/site/src/pages/AgentsPage/components/ChatElements/Response.tsx +++ b/site/src/pages/AgentsPage/components/ChatElements/Response.tsx @@ -1,4 +1,3 @@ -import { useTheme } from "@emotion/react"; import { File as FileViewer, type SupportedLanguages, @@ -11,6 +10,7 @@ import { type UrlTransform, } from "streamdown"; import { ScrollArea } from "#/components/ScrollArea/ScrollArea"; +import { useTheme } from "#/theme/context"; import { cn } from "#/utils/cn"; interface ResponseProps extends Omit, "children"> { @@ -184,8 +184,7 @@ const createComponents = ( ); }, - // Horizontal rule: reset browser default inset/ridge border - // (preflight is disabled) to a clean 1px solid line. + // Horizontal rule: only a top border so it reads as a clean divider. hr: () => (
), diff --git a/site/src/pages/AgentsPage/components/ChatElements/tools/EditFilesTool.tsx b/site/src/pages/AgentsPage/components/ChatElements/tools/EditFilesTool.tsx index 015d9c65bfb5a..1af4bf6b8acbd 100644 --- a/site/src/pages/AgentsPage/components/ChatElements/tools/EditFilesTool.tsx +++ b/site/src/pages/AgentsPage/components/ChatElements/tools/EditFilesTool.tsx @@ -1,9 +1,9 @@ -import { useTheme } from "@emotion/react"; import type { FileDiffMetadata } from "@pierre/diffs"; import { FileDiff } from "@pierre/diffs/react"; import type React from "react"; import type * as TypesGen from "#/api/typesGenerated"; import { ScrollArea } from "#/components/ScrollArea/ScrollArea"; +import { useTheme } from "#/theme/context"; import { getPathBasename } from "../../../utils/path"; import { DiffFileHeader } from "./DiffFileHeader"; import { diff --git a/site/src/pages/AgentsPage/components/ChatElements/tools/ReadFileTool.tsx b/site/src/pages/AgentsPage/components/ChatElements/tools/ReadFileTool.tsx index e9462fa79350e..88d9132f92dc7 100644 --- a/site/src/pages/AgentsPage/components/ChatElements/tools/ReadFileTool.tsx +++ b/site/src/pages/AgentsPage/components/ChatElements/tools/ReadFileTool.tsx @@ -1,7 +1,7 @@ -import { useTheme } from "@emotion/react"; import { File as FileViewer } from "@pierre/diffs/react"; import type React from "react"; import { ScrollArea } from "#/components/ScrollArea/ScrollArea"; +import { useTheme } from "#/theme/context"; import { getPathBasename } from "../../../utils/path"; import { asRecord, asString } from "../runtimeTypeUtils"; import { ToolCall } from "./ToolCall"; diff --git a/site/src/pages/AgentsPage/components/ChatElements/tools/Tool.tsx b/site/src/pages/AgentsPage/components/ChatElements/tools/Tool.tsx index f96212bedf3af..a6b9bf1e88291 100644 --- a/site/src/pages/AgentsPage/components/ChatElements/tools/Tool.tsx +++ b/site/src/pages/AgentsPage/components/ChatElements/tools/Tool.tsx @@ -1,8 +1,8 @@ -import { useTheme } from "@emotion/react"; import { File as FileViewer } from "@pierre/diffs/react"; import { type ComponentPropsWithRef, type FC, memo } from "react"; import type * as TypesGen from "#/api/typesGenerated"; import { ScrollArea } from "#/components/ScrollArea/ScrollArea"; +import { useTheme } from "#/theme/context"; import { cn } from "#/utils/cn"; import { AdvisorTool, type AdvisorToolResultType } from "./AdvisorTool"; import { diff --git a/site/src/pages/AgentsPage/components/ChatElements/tools/WriteFileTool.tsx b/site/src/pages/AgentsPage/components/ChatElements/tools/WriteFileTool.tsx index 4c43eee49354a..26c89503fca29 100644 --- a/site/src/pages/AgentsPage/components/ChatElements/tools/WriteFileTool.tsx +++ b/site/src/pages/AgentsPage/components/ChatElements/tools/WriteFileTool.tsx @@ -1,9 +1,9 @@ -import { useTheme } from "@emotion/react"; import type { FileDiffMetadata } from "@pierre/diffs"; import { FileDiff } from "@pierre/diffs/react"; import type React from "react"; import type * as TypesGen from "#/api/typesGenerated"; import { ScrollArea } from "#/components/ScrollArea/ScrollArea"; +import { useTheme } from "#/theme/context"; import { getPathBasename } from "../../../utils/path"; import { DiffFileHeader } from "./DiffFileHeader"; import { diff --git a/site/src/pages/AgentsPage/components/DiffViewer/DiffViewer.tsx b/site/src/pages/AgentsPage/components/DiffViewer/DiffViewer.tsx index 1be56678479fc..3b6070e07fae1 100644 --- a/site/src/pages/AgentsPage/components/DiffViewer/DiffViewer.tsx +++ b/site/src/pages/AgentsPage/components/DiffViewer/DiffViewer.tsx @@ -1,4 +1,3 @@ -import { useTheme } from "@emotion/react"; import type { CodeViewHandle, CodeViewItem, @@ -22,6 +21,7 @@ import { } from "react"; import { ErrorAlert } from "#/components/Alert/ErrorAlert"; import { Skeleton } from "#/components/Skeleton/Skeleton"; +import { useTheme } from "#/theme/context"; import { cn } from "#/utils/cn"; import { countChangedLines } from "../../utils/countChangedLines"; import { changeColor, changeLabel } from "../../utils/diffColors"; diff --git a/site/src/pages/DeploymentSettingsPage/AppearanceSettingsPage/AnnouncementBannerDialog.tsx b/site/src/pages/DeploymentSettingsPage/AppearanceSettingsPage/AnnouncementBannerDialog.tsx index ccf1e6d993a59..b6a34d4b4532e 100644 --- a/site/src/pages/DeploymentSettingsPage/AppearanceSettingsPage/AnnouncementBannerDialog.tsx +++ b/site/src/pages/DeploymentSettingsPage/AppearanceSettingsPage/AnnouncementBannerDialog.tsx @@ -1,5 +1,3 @@ -import { useTheme } from "@emotion/react"; -import TextField from "@mui/material/TextField"; import { useFormik } from "formik"; import { type FC, useState } from "react"; import { SliderPicker, TwitterPicker } from "react-color"; @@ -14,6 +12,8 @@ import { DialogTitle, } from "#/components/Dialog/Dialog"; import { AnnouncementBannerView } from "#/modules/dashboard/AnnouncementBanners/AnnouncementBannerView"; +import { useTheme } from "#/theme/context"; +import { cn } from "#/utils/cn"; import { getFormHelpers } from "#/utils/formUtils"; interface AnnouncementBannerDialogProps { diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx index 60689401139a3..582e250de9917 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx @@ -1,4 +1,3 @@ -import { useTheme } from "@emotion/react"; import { PlusIcon, RotateCwIcon } from "lucide-react"; import type { FC } from "react"; import Confetti from "react-confetti"; @@ -20,6 +19,7 @@ import { TooltipTrigger, } from "#/components/Tooltip/Tooltip"; import { useWindowSize } from "#/hooks/useWindowSize"; +import { useTheme } from "#/theme/context"; import { AIGovernanceUsersConsumption } from "./AIGovernanceUsersConsumptionChart"; import { LicenseCard } from "./LicenseCard"; import { LicenseSeatConsumptionChart } from "./LicenseSeatConsumptionChart"; diff --git a/site/src/pages/TemplateVersionEditorPage/MonacoEditor.tsx b/site/src/pages/TemplateVersionEditorPage/MonacoEditor.tsx index 90106ab01e187..8bf8b4a6a7c44 100644 --- a/site/src/pages/TemplateVersionEditorPage/MonacoEditor.tsx +++ b/site/src/pages/TemplateVersionEditorPage/MonacoEditor.tsx @@ -1,8 +1,8 @@ -import { useTheme } from "@emotion/react"; import Editor, { loader } from "@monaco-editor/react"; import * as monaco from "monaco-editor"; import { type FC, useEffect } from "react"; import { MONOSPACE_FONT_FAMILY } from "#/theme/constants"; +import { useTheme } from "#/theme/context"; loader.config({ monaco }); diff --git a/site/src/theme/appearance.tsx b/site/src/theme/appearance.tsx index 40120856c7fe7..bc864cf2b8ec2 100644 --- a/site/src/theme/appearance.tsx +++ b/site/src/theme/appearance.tsx @@ -8,8 +8,7 @@ import { import type { ExternalImageModeStyles } from "#/theme/externalImages"; /** - * Publishes *user* appearance values derived from the active site theme so - * components can consume them without depending on Emotion's `useTheme`. + * Publishes *user* appearance values derived from the active site theme. * * This is the client-side, theme-derived appearance surface (for example, how * external images should be tinted for the active theme). It is intentionally diff --git a/site/src/theme/constants.ts b/site/src/theme/constants.ts index 8b54c8d1a6389..e9d2d5c964ece 100644 --- a/site/src/theme/constants.ts +++ b/site/src/theme/constants.ts @@ -1,12 +1,9 @@ import type { TerminalFontName } from "#/api/typesGenerated"; -export const borderRadius = 8; - const MONOSPACE_DEFAULT_FONT = "Geist Mono Variable"; const TERMINAL_SYMBOL_FONT = "'Coder Terminal Symbols'"; export const MONOSPACE_FONT_FAMILY = "'Geist Mono Variable', 'IBM Plex Mono', 'Lucida Console', 'Lucida Sans Typewriter', 'Liberation Mono', 'Monaco', 'Courier New', Courier, monospace"; -export const BODY_FONT_FAMILY = `"Geist Variable", system-ui, sans-serif`; const withTerminalSymbolFallback = (fontFamily: string) => fontFamily.replace(", monospace", `, ${TERMINAL_SYMBOL_FONT}, monospace`); @@ -42,7 +39,3 @@ export const navHeight = 62; export const containerWidth = 1380; 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_LG_HEIGHT = 40; -export const BUTTON_MD_HEIGHT = 36; diff --git a/site/src/theme/context.tsx b/site/src/theme/context.tsx new file mode 100644 index 0000000000000..1dbfad5c1c050 --- /dev/null +++ b/site/src/theme/context.tsx @@ -0,0 +1,26 @@ +import { createContext, type FC, type ReactNode, useContext } from "react"; +import type { Theme } from "#/theme"; + +const ThemeContext = createContext(undefined); + +interface ThemeContextProviderProps { + theme: Theme; + children: ReactNode; +} + +export const ThemeContextProvider: FC = ({ + theme, + children, +}) => { + return ( + {children} + ); +}; + +export const useTheme = (): Theme => { + const theme = useContext(ThemeContext); + if (theme === undefined) { + throw new Error("useTheme must be used within a ThemeContextProvider"); + } + return theme; +}; diff --git a/site/src/theme/dark/index.ts b/site/src/theme/dark/index.ts index 29cec249232c6..78668aa8f2967 100644 --- a/site/src/theme/dark/index.ts +++ b/site/src/theme/dark/index.ts @@ -2,11 +2,11 @@ import { forDarkThemes } from "../externalImages"; import branding from "./branding"; import experimental from "./experimental"; import monaco from "./monaco"; -import muiTheme from "./mui"; +import palette from "./palette"; import roles from "./roles"; export default { - ...muiTheme, + palette, externalImages: forDarkThemes, experimental, branding, diff --git a/site/src/theme/dark/monaco.ts b/site/src/theme/dark/monaco.ts index 4c73d8b9918e8..a7c4e72732f11 100644 --- a/site/src/theme/dark/monaco.ts +++ b/site/src/theme/dark/monaco.ts @@ -1,5 +1,5 @@ import type * as monaco from "monaco-editor"; -import muiTheme from "./mui"; +import palette from "./palette"; export default { base: "vs-dark", @@ -31,7 +31,7 @@ export default { }, ], colors: { - "editor.foreground": muiTheme.palette.text.primary, - "editor.background": muiTheme.palette.background.paper, + "editor.foreground": palette.text.primary, + "editor.background": palette.background.paper, }, } satisfies monaco.editor.IStandaloneThemeData as monaco.editor.IStandaloneThemeData; diff --git a/site/src/theme/dark/mui.ts b/site/src/theme/dark/mui.ts deleted file mode 100644 index fd526e4bcc584..0000000000000 --- a/site/src/theme/dark/mui.ts +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @deprecated MUI dark theme is deprecated. Migrate to Tailwind CSS theme system. - * This file provides MUI theme configuration for legacy compatibility only. - */ - -/** @deprecated MUI createTheme is deprecated. Migrate to Tailwind CSS theme system. */ -import { createTheme } from "@mui/material/styles"; -import { BODY_FONT_FAMILY, borderRadius } from "../constants"; -import { components } from "../mui"; -import tw from "../tailwindColors"; - -const muiTheme = createTheme({ - palette: { - mode: "dark", - primary: { - main: tw.sky[500], - contrastText: tw.white, - light: tw.sky[400], - dark: tw.sky[600], - }, - secondary: { - main: tw.zinc[500], - contrastText: tw.zinc[200], - dark: tw.zinc[400], - }, - background: { - default: tw.zinc[950], - paper: tw.zinc[900], - }, - text: { - primary: tw.zinc[50], - secondary: tw.zinc[400], - disabled: tw.zinc[500], - }, - divider: tw.zinc[700], - warning: { - light: tw.amber[500], - main: tw.amber[800], - dark: tw.amber[950], - }, - success: { - main: tw.green[500], - dark: tw.green[600], - }, - info: { - light: tw.blue[400], - main: tw.blue[600], - dark: tw.blue[950], - contrastText: tw.zinc[200], - }, - error: { - light: tw.red[400], - main: tw.red[500], - dark: tw.red[950], - contrastText: tw.zinc[200], - }, - action: { - hover: tw.zinc[800], - }, - neutral: { - main: tw.zinc[50], - }, - dots: tw.zinc[500], - }, - typography: { - fontFamily: BODY_FONT_FAMILY, - - body1: { - fontSize: "1rem" /* 16px at default scaling */, - lineHeight: "160%", - }, - - body2: { - fontSize: "0.875rem" /* 14px at default scaling */, - lineHeight: "160%", - }, - }, - shape: { - borderRadius, - }, - components, -}); - -export default muiTheme; diff --git a/site/src/theme/dark/palette.ts b/site/src/theme/dark/palette.ts new file mode 100644 index 0000000000000..160efeff13740 --- /dev/null +++ b/site/src/theme/dark/palette.ts @@ -0,0 +1,21 @@ +import type { Palette } from "../palette"; +import tw from "../tailwindColors"; + +const palette: Palette = { + mode: "dark", + primary: { + main: tw.sky[500], + }, + secondary: { + main: tw.zinc[500], + }, + background: { + default: tw.zinc[950], + paper: tw.zinc[900], + }, + text: { + primary: tw.zinc[50], + }, +}; + +export default palette; diff --git a/site/src/theme/darkProtanDeuter/index.ts b/site/src/theme/darkProtanDeuter/index.ts index 29cec249232c6..17b6544a3e2e0 100644 --- a/site/src/theme/darkProtanDeuter/index.ts +++ b/site/src/theme/darkProtanDeuter/index.ts @@ -1,12 +1,12 @@ +import palette from "../dark/palette"; import { forDarkThemes } from "../externalImages"; import branding from "./branding"; import experimental from "./experimental"; import monaco from "./monaco"; -import muiTheme from "./mui"; import roles from "./roles"; export default { - ...muiTheme, + palette, externalImages: forDarkThemes, experimental, branding, diff --git a/site/src/theme/darkProtanDeuter/mui.ts b/site/src/theme/darkProtanDeuter/mui.ts deleted file mode 100644 index b59dca2f3e430..0000000000000 --- a/site/src/theme/darkProtanDeuter/mui.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @deprecated MUI theme is deprecated. Migrate to Tailwind CSS theme system. - * - * MUI components are deprecated and the colorblind-friendly palette is - * expressed through `roles.ts` and the CSS variables in - * `site/src/index.css`, both of which drive the Tailwind-rendered UI that - * the diff panel and semantic roles use. We re-export the base dark MUI - * theme so `palette.mode === "dark"` stays correct for any remaining - * legacy MUI component that inspects it (for example, the Shiki theme - * selector in `DiffViewer.tsx`). - */ -export { default } from "../dark/mui"; diff --git a/site/src/theme/darkTritan/index.ts b/site/src/theme/darkTritan/index.ts index 29cec249232c6..17b6544a3e2e0 100644 --- a/site/src/theme/darkTritan/index.ts +++ b/site/src/theme/darkTritan/index.ts @@ -1,12 +1,12 @@ +import palette from "../dark/palette"; import { forDarkThemes } from "../externalImages"; import branding from "./branding"; import experimental from "./experimental"; import monaco from "./monaco"; -import muiTheme from "./mui"; import roles from "./roles"; export default { - ...muiTheme, + palette, externalImages: forDarkThemes, experimental, branding, diff --git a/site/src/theme/darkTritan/mui.ts b/site/src/theme/darkTritan/mui.ts deleted file mode 100644 index 80e0ddc63284a..0000000000000 --- a/site/src/theme/darkTritan/mui.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @deprecated MUI theme is deprecated. Migrate to Tailwind CSS theme system. - * - * The colorblind-friendly palette is expressed through `roles.ts` and the - * CSS variables in `site/src/index.css`. We re-export the base dark MUI - * theme so `palette.mode === "dark"` stays correct for any remaining - * legacy MUI component that inspects it. - */ -export { default } from "../dark/mui"; diff --git a/site/src/theme/index.ts b/site/src/theme/index.ts index 33f140cdaa96b..311d045ab7d83 100644 --- a/site/src/theme/index.ts +++ b/site/src/theme/index.ts @@ -1,5 +1,3 @@ -/** @deprecated MUI Theme type is deprecated. Migrate to Tailwind CSS theme system. */ -import type { Theme as MuiTheme } from "@mui/material/styles"; import type * as monaco from "monaco-editor"; import type { Branding } from "./branding"; import dark from "./dark"; @@ -10,11 +8,12 @@ import type { ExternalImageModeStyles } from "./externalImages"; import light from "./light"; import lightProtanDeuter from "./lightProtanDeuter"; import lightTritan from "./lightTritan"; +import type { Palette } from "./palette"; import type { Roles } from "./roles"; -export interface Theme extends Omit { - /** @deprecated prefer `theme.roles` when possible */ - palette: MuiTheme["palette"]; +export interface Theme { + /** @deprecated prefer roles or CSS variables when possible */ + palette: Palette; /** Sets of colors that can be used based on the role that a UI element serves * for the user. diff --git a/site/src/theme/light/index.ts b/site/src/theme/light/index.ts index fd50cbd9f9638..d5c1ba556d653 100644 --- a/site/src/theme/light/index.ts +++ b/site/src/theme/light/index.ts @@ -2,11 +2,11 @@ import { forLightThemes } from "../externalImages"; import branding from "./branding"; import experimental from "./experimental"; import monaco from "./monaco"; -import muiTheme from "./mui"; +import palette from "./palette"; import roles from "./roles"; export default { - ...muiTheme, + palette, externalImages: forLightThemes, experimental, branding, diff --git a/site/src/theme/light/monaco.ts b/site/src/theme/light/monaco.ts index 2da6974033b3b..d325b06dc23df 100644 --- a/site/src/theme/light/monaco.ts +++ b/site/src/theme/light/monaco.ts @@ -1,5 +1,5 @@ import type * as monaco from "monaco-editor"; -import muiTheme from "./mui"; +import palette from "./palette"; export default { base: "vs", @@ -31,7 +31,7 @@ export default { }, ], colors: { - "editor.foreground": muiTheme.palette.text.primary, - "editor.background": muiTheme.palette.background.paper, + "editor.foreground": palette.text.primary, + "editor.background": palette.background.paper, }, } satisfies monaco.editor.IStandaloneThemeData as monaco.editor.IStandaloneThemeData; diff --git a/site/src/theme/light/mui.ts b/site/src/theme/light/mui.ts deleted file mode 100644 index de3f2c0a1aaed..0000000000000 --- a/site/src/theme/light/mui.ts +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @deprecated MUI light theme is deprecated. Migrate to Tailwind CSS theme system. - * This file provides MUI theme configuration for legacy compatibility only. - */ - -/** @deprecated MUI createTheme is deprecated. Migrate to Tailwind CSS theme system. */ -import { createTheme } from "@mui/material/styles"; -import { BODY_FONT_FAMILY, borderRadius } from "../constants"; -import { components } from "../mui"; -import tw from "../tailwindColors"; - -// biome-ignore lint/suspicious/noExplicitAny: needed for MUI overrides -type MuiStyle = any; - -const muiTheme = createTheme({ - palette: { - mode: "light", - primary: { - main: tw.sky[600], - contrastText: tw.sky[50], - light: tw.sky[400], - dark: tw.sky[500], - }, - secondary: { - main: tw.zinc[500], - contrastText: tw.zinc[800], - dark: tw.zinc[600], - }, - background: { - default: tw.zinc[50], - paper: tw.zinc[100], - }, - text: { - primary: tw.zinc[950], - secondary: tw.zinc[600], - disabled: tw.zinc[500], - }, - divider: tw.zinc[200], - warning: { - light: tw.amber[400], - main: tw.amber[800], - dark: tw.amber[950], - }, - success: { - main: tw.green[500], - dark: tw.green[600], - }, - info: { - light: tw.blue[400], - main: tw.blue[600], - dark: tw.blue[950], - contrastText: tw.zinc[200], - }, - error: { - light: tw.red[400], - main: tw.red[500], - dark: tw.red[950], - contrastText: tw.zinc[800], - }, - action: { - hover: tw.zinc[100], - }, - neutral: { - main: tw.zinc[950], - }, - dots: tw.zinc[400], - }, - typography: { - fontFamily: BODY_FONT_FAMILY, - - body1: { - fontSize: "1rem" /* 16px at default scaling */, - lineHeight: "160%", - }, - - body2: { - fontSize: "0.875rem" /* 14px at default scaling */, - lineHeight: "160%", - }, - }, - shape: { - borderRadius, - }, - components: { - ...components, - MuiCssBaseline: { - styleOverrides: (theme) => ` - html, body, #root, #storybook-root { - height: 100%; - } - - button, input { - font-family: ${BODY_FONT_FAMILY}; - } - - input:-webkit-autofill, - input:-webkit-autofill:hover, - input:-webkit-autofill:focus, - input:-webkit-autofill:active { - -webkit-box-shadow: 0 0 0 100px ${theme.palette.background.default} inset !important; - } - - ::placeholder { - color: ${theme.palette.text.disabled}; - } - `, - }, - MuiAvatar: { - styleOverrides: { - root: components.MuiAvatar.styleOverrides.root, - colorDefault: { - backgroundColor: tw.zinc[700], - }, - }, - }, - MuiChip: { - styleOverrides: { - root: { - backgroundColor: tw.zinc[400], - }, - }, - }, - MuiInputBase: { - ...components.MuiInputBase, - styleOverrides: { - ...components.MuiInputBase.styleOverrides, - ["colorPrimary" as MuiStyle]: { - // Same as button - "& .MuiOutlinedInput-notchedOutline": { - borderColor: tw.zinc[300], - }, - // The default outlined input color is white, which seemed jarring. - "&:hover:not(.Mui-error):not(.Mui-focused) .MuiOutlinedInput-notchedOutline": - { - borderColor: tw.zinc[500], - }, - }, - }, - }, - MuiCheckbox: { - styleOverrides: { - root: { - /** - * Adds focus styling to checkboxes (which doesn't exist normally, for - * some reason?). - * - * The checkbox component is a root span with a checkbox input inside - * it. MUI does not allow you to use selectors like (& input) to - * target the inner checkbox (even though you can use & td to style - * tables). Tried every combination of selector possible (including - * lots of !important), and the main issue seems to be that the - * styling just never gets processed for it to get injected into the - * CSSOM. - * - * Had to settle for adding styling to the span itself (which does - * make the styling more obvious, even if there's not much room for - * customization). - */ - "&.Mui-focusVisible": { - boxShadow: `0 0 0 2px ${tw.blue[600]}`, - }, - - "&.Mui-disabled": { - color: tw.zinc[500], - }, - }, - }, - }, - MuiTooltip: { - styleOverrides: { - tooltip: ({ theme }) => ({ - lineHeight: "150%", - borderRadius: 4, - background: theme.palette.background.paper, - color: theme.palette.secondary.contrastText, - border: `1px solid ${theme.palette.divider}`, - padding: "8px 16px", - boxShadow: "0 1px 4px #0001", - }), - }, - }, - }, -}); - -export default muiTheme; diff --git a/site/src/theme/light/palette.ts b/site/src/theme/light/palette.ts new file mode 100644 index 0000000000000..75f6b9fa7e8f8 --- /dev/null +++ b/site/src/theme/light/palette.ts @@ -0,0 +1,21 @@ +import type { Palette } from "../palette"; +import tw from "../tailwindColors"; + +const palette: Palette = { + mode: "light", + primary: { + main: tw.sky[600], + }, + secondary: { + main: tw.zinc[500], + }, + background: { + default: tw.zinc[50], + paper: tw.zinc[100], + }, + text: { + primary: tw.zinc[950], + }, +}; + +export default palette; diff --git a/site/src/theme/lightProtanDeuter/index.ts b/site/src/theme/lightProtanDeuter/index.ts index fd50cbd9f9638..220f82eb9033b 100644 --- a/site/src/theme/lightProtanDeuter/index.ts +++ b/site/src/theme/lightProtanDeuter/index.ts @@ -1,12 +1,12 @@ import { forLightThemes } from "../externalImages"; +import palette from "../light/palette"; import branding from "./branding"; import experimental from "./experimental"; import monaco from "./monaco"; -import muiTheme from "./mui"; import roles from "./roles"; export default { - ...muiTheme, + palette, externalImages: forLightThemes, experimental, branding, diff --git a/site/src/theme/lightProtanDeuter/mui.ts b/site/src/theme/lightProtanDeuter/mui.ts deleted file mode 100644 index 7f75c070c190b..0000000000000 --- a/site/src/theme/lightProtanDeuter/mui.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @deprecated MUI theme is deprecated. Migrate to Tailwind CSS theme system. - * - * The colorblind-friendly palette is expressed through `roles.ts` and the - * CSS variables in `site/src/index.css`. We re-export the base light MUI - * theme so `palette.mode === "light"` stays correct for any remaining - * legacy MUI component that inspects it, including the Shiki theme - * selector in `DiffViewer.tsx`. - */ -export { default } from "../light/mui"; diff --git a/site/src/theme/lightTritan/index.ts b/site/src/theme/lightTritan/index.ts index fd50cbd9f9638..220f82eb9033b 100644 --- a/site/src/theme/lightTritan/index.ts +++ b/site/src/theme/lightTritan/index.ts @@ -1,12 +1,12 @@ import { forLightThemes } from "../externalImages"; +import palette from "../light/palette"; import branding from "./branding"; import experimental from "./experimental"; import monaco from "./monaco"; -import muiTheme from "./mui"; import roles from "./roles"; export default { - ...muiTheme, + palette, externalImages: forLightThemes, experimental, branding, diff --git a/site/src/theme/lightTritan/mui.ts b/site/src/theme/lightTritan/mui.ts deleted file mode 100644 index 718b6aa2b71a0..0000000000000 --- a/site/src/theme/lightTritan/mui.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @deprecated MUI theme is deprecated. Migrate to Tailwind CSS theme system. - * - * Re-exports the base light MUI theme so `palette.mode === "light"` stays - * correct for legacy MUI components. Colorblind palette overrides live in - * `roles.ts` and the CSS variables block in `site/src/index.css`. - */ -export { default } from "../light/mui"; diff --git a/site/src/theme/mui.ts b/site/src/theme/mui.ts deleted file mode 100644 index 11e93bf9be686..0000000000000 --- a/site/src/theme/mui.ts +++ /dev/null @@ -1,222 +0,0 @@ -/** - * @deprecated MUI theme configuration is deprecated. Migrate to Tailwind CSS theme system. - * This file provides MUI theme overrides for legacy compatibility only. - */ - -/** @deprecated MUI ThemeOptions is deprecated. Migrate to Tailwind CSS theme system. */ -import type { ThemeOptions } from "@mui/material/styles"; -import { BUTTON_LG_HEIGHT, BUTTON_MD_HEIGHT } from "./constants"; -import tw from "./tailwindColors"; - -// biome-ignore lint/suspicious/noExplicitAny: needed for MUI overrides -type MuiStyle = any; - -export const components = { - MuiAvatar: { - styleOverrides: { - root: { - width: 36, - height: 36, - fontSize: 18, - - "& .MuiSvgIcon-root": { - width: "50%", - }, - }, - colorDefault: ({ theme }) => ({ - backgroundColor: theme.palette.primary.light, - }), - }, - }, - MuiLink: { - defaultProps: { - underline: "hover", - }, - }, - MuiSkeleton: { - styleOverrides: { - root: ({ theme }) => ({ - backgroundColor: theme.palette.divider, - }), - }, - }, - MuiLinearProgress: { - styleOverrides: { - root: { - borderRadius: 999, - }, - }, - }, - MuiMenu: { - defaultProps: { - anchorOrigin: { - vertical: "bottom", - horizontal: "right", - }, - transformOrigin: { - vertical: "top", - horizontal: "right", - }, - }, - styleOverrides: { - paper: { - marginTop: 8, - borderRadius: 4, - padding: "4px 0", - minWidth: 160, - }, - root: { - // It should be the same as the menu padding - "& .MuiDivider-root": { - marginTop: "4px !important", - marginBottom: "4px !important", - }, - }, - }, - }, - MuiMenuItem: { - styleOverrides: { - root: { - gap: 12, - - "& .MuiSvgIcon-root": { - fontSize: 20, - }, - }, - }, - }, - MuiSnackbar: { - styleOverrides: { - anchorOriginBottomRight: { - bottom: `${24 + 36}px !important`, // 36 is the bottom bar height - }, - }, - }, - MuiSnackbarContent: { - styleOverrides: { - root: { - borderRadius: "4px !important", - }, - }, - }, - MuiTextField: { - defaultProps: { - InputLabelProps: { - shrink: true, - }, - }, - }, - MuiInputBase: { - defaultProps: { - color: "primary", - }, - styleOverrides: { - root: { - height: BUTTON_LG_HEIGHT, - }, - sizeSmall: { - height: BUTTON_MD_HEIGHT, - fontSize: 14, - }, - multiline: { - height: "auto", - }, - ["colorPrimary" as MuiStyle]: { - // Same as button - "& .MuiOutlinedInput-notchedOutline": { - borderColor: tw.zinc[600], - }, - // The default outlined input color is white, which seemed jarring. - "&:hover:not(.Mui-error):not(.Mui-focused) .MuiOutlinedInput-notchedOutline": - { - borderColor: tw.zinc[500], - }, - }, - }, - }, - MuiFormHelperText: { - defaultProps: { - sx: { - marginLeft: 0, - marginTop: 1, - "&::first-letter": { - // Server errors are returned in all lowercase. To display them as - // field errors in the UI, we capitalize the first letter. - textTransform: "uppercase", - }, - }, - }, - }, - MuiRadio: { - defaultProps: { - disableRipple: true, - }, - }, - MuiCheckbox: { - styleOverrides: { - root: { - /** - * Adds focus styling to checkboxes (which doesn't exist normally, for - * some reason?). - * - * The checkbox component is a root span with a checkbox input inside - * it. MUI does not allow you to use selectors like (& input) to - * target the inner checkbox (even though you can use & td to style - * tables). Tried every combination of selector possible (including - * lots of !important), and the main issue seems to be that the - * styling just never gets processed for it to get injected into the - * CSSOM. - * - * Had to settle for adding styling to the span itself (which does - * make the styling more obvious, even if there's not much room for - * customization). - */ - "&.Mui-focusVisible": { - boxShadow: `0 0 0 2px ${tw.blue[400]}`, - }, - - "&.Mui-disabled": { - color: tw.zinc[500], - }, - - "& .MuiSvgIcon-fontSizeXsmall": { - fontSize: "1rem", - }, - }, - }, - }, - MuiAutocomplete: { - styleOverrides: { - root: { - // Not sure why but since the input has padding we don't need it here - "& .MuiInputBase-root": { - padding: "0px 0px 0px 8px", - }, - }, - }, - }, - MuiList: { - defaultProps: { - disablePadding: true, - }, - }, - MuiTabs: { - defaultProps: { - textColor: "primary", - indicatorColor: "primary", - }, - }, - MuiTooltip: { - styleOverrides: { - tooltip: ({ theme }) => ({ - lineHeight: "150%", - borderRadius: 4, - background: theme.palette.divider, - padding: "8px 16px", - }), - arrow: ({ theme }) => ({ - color: theme.palette.divider, - }), - }, - }, -} satisfies ThemeOptions["components"]; diff --git a/site/src/theme/palette.ts b/site/src/theme/palette.ts new file mode 100644 index 0000000000000..f7ba7902c62c9 --- /dev/null +++ b/site/src/theme/palette.ts @@ -0,0 +1,20 @@ +/** + * Minimal palette used by remaining non-Tailwind consumers (Monaco, charts, + * confetti, color pickers). Prefer semantic CSS variables and roles when possible. + */ +export interface Palette { + mode: "dark" | "light"; + primary: { + main: string; + }; + secondary: { + main: string; + }; + background: { + default: string; + paper: string; + }; + text: { + primary: string; + }; +} diff --git a/site/tailwind.config.js b/site/tailwind.config.js index 839299b1d3e35..14f66470128e2 100644 --- a/site/tailwind.config.js +++ b/site/tailwind.config.js @@ -1,8 +1,5 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - corePlugins: { - preflight: false, - }, darkMode: ["selector"], content: [ "./index.html", diff --git a/site/tsconfig.json b/site/tsconfig.json index 4b5dc19dbe4e7..c2df2443a3174 100644 --- a/site/tsconfig.json +++ b/site/tsconfig.json @@ -5,7 +5,6 @@ "incremental": true, "isolatedModules": true, "jsx": "react-jsx", - "jsxImportSource": "@emotion/react", "lib": ["dom", "esnext"], "module": "preserve", "moduleResolution": "bundler", diff --git a/site/vite.config.mts b/site/vite.config.mts index d739b4b6d774a..4b6c9f1476a67 100644 --- a/site/vite.config.mts +++ b/site/vite.config.mts @@ -62,8 +62,6 @@ export default defineConfig({ }, codeSplitting: { groups: [ - { name: "mui", test: /@mui/ }, - { name: "emotion", test: /@emotion/ }, { name: "monaco", test: /monaco-editor/ }, { name: "xterm", test: /@xterm/ }, { name: "emoji-mart", test: /emoji-mart/ }, @@ -157,58 +155,11 @@ export default defineConfig({ }, allowedHosts: [".coder", ".dev.coder.com"], }, - // Pre-bundle deps that Vite tends to discover late (deep MUI - // imports, Emotion). Without this, Vite re-optimizes mid-session - // which returns 504 "Outdated Optimize Dep" for every previously - // served chunk, cascading into dynamic import failures. + // Pre-bundle deps that Vite tends to discover late. Without this, Vite + // re-optimizes mid-session which returns 504 "Outdated Optimize Dep" for + // every previously served chunk, cascading into dynamic import failures. optimizeDeps: { include: [ - "@emotion/cache", - "@emotion/css", - "@emotion/react", - "@emotion/react/jsx-runtime", - "@emotion/styled", - "@mui/material/Autocomplete", - "@mui/material/Card", - "@mui/material/CardActionArea", - "@mui/material/CardContent", - "@mui/material/Checkbox", - "@mui/material/Collapse", - "@mui/material/CssBaseline", - "@mui/material/Dialog", - "@mui/material/DialogActions", - "@mui/material/DialogContent", - "@mui/material/DialogContentText", - "@mui/material/DialogTitle", - "@mui/material/Divider", - "@mui/material/Drawer", - "@mui/material/FormControl", - "@mui/material/FormControlLabel", - "@mui/material/FormGroup", - "@mui/material/FormHelperText", - "@mui/material/FormLabel", - "@mui/material/InputAdornment", - "@mui/material/InputBase", - "@mui/material/Link", - "@mui/material/List", - "@mui/material/ListItem", - "@mui/material/ListItemText", - "@mui/material/Menu", - "@mui/material/MenuItem", - "@mui/material/MenuList", - "@mui/material/Radio", - "@mui/material/RadioGroup", - "@mui/material/Select", - "@mui/material/Skeleton", - "@mui/material/Snackbar", - "@mui/material/Stack", - "@mui/material/TableRow", - "@mui/material/TextField", - "@mui/material/ToggleButton", - "@mui/material/ToggleButtonGroup", - "@mui/material/styles", - "@mui/system/createTheme", - "@mui/system/useTheme", // Discovered at runtime without this entry, triggering // a mid-run dep re-optimization that breaks imports. "@tanstack/react-query-devtools", From 18c6c4fb89ca8645ab0ec92a55f62f4a4a6191c4 Mon Sep 17 00:00:00 2001 From: Jake Howell Date: Tue, 11 Aug 2026 03:04:14 +0000 Subject: [PATCH 02/11] feat: remove mui deconfiguration --- .github/dependabot.yaml | 3 -- .vscode/settings.json | 4 -- biome.jsonc | 64 ----------------------------- docs/about/contributing/frontend.md | 8 ---- 4 files changed, 79 deletions(-) diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index d4ad58b2d4496..649f4d626caf4 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -79,9 +79,6 @@ updates: xterm: patterns: - "@xterm*" - mui: - patterns: - - "@mui*" react: patterns: - "react" diff --git a/.vscode/settings.json b/.vscode/settings.json index 9008f766c6bf8..4a493a7b1b3f8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -72,10 +72,6 @@ // We discourage people from various older libraries that // are no longer recommended/being migrated from. "typescript.preferences.autoImportSpecifierExcludeRegexes": [ - // discourage people from using MUI components - "^@mui(?:/.*)?$", - // discourage people from using Emotion CSS - "^@emotion(?:/.*)?$", // we prefer people use `lodash/foo` over `lodash` "^lodash$" ] diff --git a/biome.jsonc b/biome.jsonc index e7e351963d091..6267c813e96f9 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -52,70 +52,6 @@ "message": "React 19 no longer requires forwardRef. Use ref as a prop instead.", "importNames": ["forwardRef"] }, - "@mui/material/Alert": "Use components/Alert/Alert instead.", - "@mui/material/AlertTitle": "Use components/Alert/Alert instead.", - // "@mui/material/Autocomplete": "Use shadcn/ui Combobox instead.", - "@mui/material/Avatar": "Use components/Avatar/Avatar instead.", - "@mui/material/Box": "Use a
with Tailwind classes instead.", - "@mui/material/Button": "Use components/Button/Button instead.", - // "@mui/material/Card": "Use shadcn/ui Card component instead.", - // "@mui/material/CardActionArea": "Use shadcn/ui Card component instead.", - // "@mui/material/CardContent": "Use shadcn/ui Card component instead.", - // "@mui/material/Checkbox": "Use shadcn/ui Checkbox component instead.", - "@mui/material/Chip": "Use components/Badge or Tailwind styles instead.", - // "@mui/material/CircularProgress": "Use components/Spinner/Spinner instead.", - // "@mui/material/Collapse": "Use shadcn/ui Collapsible instead.", - // "@mui/material/CssBaseline": "Use Tailwind CSS base styles instead.", - // "@mui/material/Dialog": "Use shadcn/ui Dialog component instead.", - // "@mui/material/DialogActions": "Use shadcn/ui Dialog component instead.", - // "@mui/material/DialogContent": "Use shadcn/ui Dialog component instead.", - // "@mui/material/DialogContentText": "Use shadcn/ui Dialog component instead.", - // "@mui/material/DialogTitle": "Use shadcn/ui Dialog component instead.", - // "@mui/material/Divider": "Use shadcn/ui Separator or
with Tailwind instead.", - // "@mui/material/Drawer": "Use shadcn/ui Sheet component instead.", - // "@mui/material/FormControl": "Use native form elements with Tailwind instead.", - // "@mui/material/FormControlLabel": "Use shadcn/ui Label with form components instead.", - "@mui/material/FormGroup": "Use a
with Tailwind classes instead.", - // "@mui/material/FormHelperText": "Use a

with Tailwind classes instead.", - "@mui/material/FormLabel": "Use shadcn/ui Label component instead.", - "@mui/material/Grid": "Use Tailwind grid utilities instead.", - "@mui/material/IconButton": "Use components/Button/Button with variant='icon' instead.", - // "@mui/material/InputAdornment": "Use Tailwind positioning in input wrapper instead.", - // "@mui/material/InputBase": "Use shadcn/ui Input component instead.", - "@mui/material/LinearProgress": "Use a progress bar with Tailwind instead.", - // "@mui/material/Link": "Use React Router Link or native tags instead.", - // "@mui/material/List": "Use native