Standardize Foundry frontend colors with semantic design tokens (#241)

Extract hardcoded colors from 15+ component files into a centralized
token system (tokens.ts + shared-styles.ts) so all UI colors flow
through FoundryTokens. This eliminates 160+ scattered color values
and makes light mode a single-file change in the future.

- Add FoundryTokens interface with dark/light variants
- Add shared style helpers (buttons, cards, inputs, badges)
- Bridge CSS custom properties for styles.css theme support
- Add useFoundryTokens() hook and ColorMode context
- Migrate all mock-layout/* and mock-onboarding components

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nicholas Kissel 2026-03-11 20:52:06 -07:00 committed by GitHub
parent ed6e6f6fa5
commit f09b9090bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 887 additions and 523 deletions

View file

@ -1,4 +1,4 @@
import { StrictMode } from "react";
import { StrictMode, useEffect, useMemo, useState } from "react";
import { createRoot } from "react-dom/client";
import { BaseProvider } from "baseui";
import { RouterProvider } from "@tanstack/react-router";
@ -6,7 +6,8 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Client as Styletron } from "styletron-engine-atomic";
import { Provider as StyletronProvider } from "styletron-react";
import { router } from "./app/router";
import { appTheme } from "./app/theme";
import { ColorModeCtx, darkTheme, getStoredColorMode, lightTheme, storeColorMode, type ColorMode } from "./app/theme";
import { applyCssTokens, getFoundryTokens } from "./styles/tokens";
import "./styles.css";
const queryClient = new QueryClient({
@ -20,14 +21,48 @@ const queryClient = new QueryClient({
const styletronEngine = new Styletron();
function App() {
const [colorMode, setColorModeState] = useState<ColorMode>(getStoredColorMode);
const colorModeCtx = useMemo(
() => ({
colorMode,
setColorMode: (mode: ColorMode) => {
storeColorMode(mode);
setColorModeState(mode);
},
}),
[colorMode],
);
const theme = colorMode === "dark" ? darkTheme : lightTheme;
const tokens = getFoundryTokens(theme);
// Sync CSS custom properties and root element styles with color mode
useEffect(() => {
applyCssTokens(tokens);
document.documentElement.style.colorScheme = colorMode;
document.documentElement.style.background = tokens.surfacePrimary;
document.documentElement.style.color = tokens.textPrimary;
document.body.style.background = tokens.surfacePrimary;
document.body.style.color = tokens.textPrimary;
}, [colorMode, tokens]);
return (
<ColorModeCtx.Provider value={colorModeCtx}>
<StyletronProvider value={styletronEngine}>
<BaseProvider theme={theme}>
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
</BaseProvider>
</StyletronProvider>
</ColorModeCtx.Provider>
);
}
createRoot(document.getElementById("root")!).render(
<StrictMode>
<StyletronProvider value={styletronEngine}>
<BaseProvider theme={appTheme}>
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
</BaseProvider>
</StyletronProvider>
<App />
</StrictMode>,
);