diff --git a/frontend/packages/core/src/AppLayout/drawer.tsx b/frontend/packages/core/src/AppLayout/drawer.tsx index e06ececf22..88b18ff7de 100644 --- a/frontend/packages/core/src/AppLayout/drawer.tsx +++ b/frontend/packages/core/src/AppLayout/drawer.tsx @@ -18,7 +18,6 @@ import { useAppContext } from "../Contexts"; import { useNavigate } from "../navigation"; import type { PopperItemProps } from "../popper"; import { Popper, PopperItem } from "../popper"; -import { THEME_VARIANTS } from "../Theme/colors"; import { filterHiddenRoutes, routesByGrouping, sortedGroupings, workflowByRoute } from "./utils"; @@ -30,9 +29,7 @@ const DrawerPanel = styled(MuiDrawer)(({ theme }: { theme: Theme }) => ({ top: "unset", width: "inherit", backgroundColor: - theme.palette.mode === THEME_VARIANTS.light - ? theme.palette.contrastColor - : theme.palette.background.paper, + theme.palette.mode === "light" ? theme.palette.contrastColor : theme.palette.background.paper, boxShadow: `0px 5px 15px ${alpha(theme.palette.primary[400], 0.2)}`, position: "relative", display: "flex", diff --git a/frontend/packages/core/src/AppLayout/theme-switcher.tsx b/frontend/packages/core/src/AppLayout/theme-switcher.tsx index 0806658f63..c26db3b042 100644 --- a/frontend/packages/core/src/AppLayout/theme-switcher.tsx +++ b/frontend/packages/core/src/AppLayout/theme-switcher.tsx @@ -6,18 +6,17 @@ import get from "lodash/get"; import { useUserPreferences } from "../Contexts"; import { Select } from "../Input"; -import { THEME_VARIANTS } from "../Theme/colors"; const ThemeSwitcher = () => { const { preferences, dispatch } = useUserPreferences(); const options = [ { - label: THEME_VARIANTS.light, + label: "Light", startAdornment: , }, { - label: THEME_VARIANTS.dark, + label: "Dark", startAdornment: , }, ]; @@ -25,7 +24,7 @@ const ThemeSwitcher = () => { const handleOnChange = (value: string) => { dispatch({ type: "SetPref", - payload: { key: "theme", value }, + payload: { key: "theme", value: value.toUpperCase() }, }); }; diff --git a/frontend/packages/core/src/AppProvider/index.tsx b/frontend/packages/core/src/AppProvider/index.tsx index 5c485883c8..a25bc07eee 100644 --- a/frontend/packages/core/src/AppProvider/index.tsx +++ b/frontend/packages/core/src/AppProvider/index.tsx @@ -13,11 +13,12 @@ import { FEATURE_FLAG_POLL_RATE, featureFlags } from "../flags"; import Landing from "../landing"; import type { ClutchError } from "../Network/errors"; import NotFound from "../not-found"; +import { Theme } from "../Theme"; +import type { ThemeOverrides } from "../Theme/types"; import { registeredWorkflows } from "./registrar"; import ShortLinkProxy, { ShortLinkBaseRoute } from "./short-link-proxy"; import ShortLinkStateHydrator from "./short-link-state-hydrator"; -import { Theme } from "./themes"; import type { ConfiguredRoute, Workflow, WorkflowConfiguration } from "./workflow"; import ErrorBoundary from "./workflow"; @@ -76,14 +77,16 @@ interface ClutchAppProps { [key: string]: () => WorkflowConfiguration; }; configuration: UserConfiguration; - appConfiguration: AppConfiguration; + appConfiguration?: AppConfiguration; children?: ClutchAppChild | ClutchAppChild[]; + themeOverrides?: ThemeOverrides; } const ClutchApp = ({ availableWorkflows, configuration: userConfiguration, appConfiguration, + themeOverrides, children, }: ClutchAppProps) => { const [workflows, setWorkflows] = React.useState([]); @@ -161,7 +164,7 @@ const ClutchApp = ({ return ( - +
diff --git a/frontend/packages/core/src/AppProvider/themes.tsx b/frontend/packages/core/src/AppProvider/themes.tsx deleted file mode 100644 index 1a2b213fdf..0000000000 --- a/frontend/packages/core/src/AppProvider/themes.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React from "react"; -import { useTheme as useMuiTheme } from "@mui/material"; -import type { Theme as MuiTheme } from "@mui/material/styles"; -import get from "lodash/get"; -import isEmpty from "lodash/isEmpty"; - -import { useUserPreferences } from "../Contexts"; -import { ThemeProvider } from "../Theme"; -import type { ClutchColors } from "../Theme/types"; -import { THEME_VARIANTS } from "../Theme/types"; - -declare module "@mui/material/styles" { - interface Theme { - colors: ClutchColors; - } - interface ThemeOptions { - colors?: ClutchColors; - } - interface Palette { - contrastColor: string; - headerGradient: string; - brandColor: string; - } -} - -const useTheme = () => useMuiTheme() as MuiTheme; - -const Theme: React.FC = ({ children }) => { - const { preferences } = useUserPreferences(); - - const prefersDarkMode = - window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; - - const themeVariant = get(preferences, "theme"); - - const variant = isEmpty(themeVariant) - ? prefersDarkMode - ? THEME_VARIANTS.dark - : THEME_VARIANTS.light - : themeVariant; - - return {children}; -}; - -export { Theme, useTheme }; diff --git a/frontend/packages/core/src/Charts/linearTimeline.tsx b/frontend/packages/core/src/Charts/linearTimeline.tsx index 43aee97ed8..72c6dd0560 100644 --- a/frontend/packages/core/src/Charts/linearTimeline.tsx +++ b/frontend/packages/core/src/Charts/linearTimeline.tsx @@ -10,7 +10,7 @@ import { YAxis, } from "recharts"; -import { useTheme } from "../AppProvider/themes"; +import { useTheme } from "../Theme"; import { calculateDomainEdges, calculateTicks, localTimeFormatter } from "./helpers"; import type { CustomTooltipProps, LinearTimelineData, LinearTimelineStylingProps } from "./types"; @@ -92,9 +92,9 @@ const LinearTimeline = ({ style={{ backgroundColor: stylingProps?.tooltipBackgroundColor || - theme.colors.charts.linearTimeline.tooltipBackgroundColor, + theme.chartColors.linearTimeline.tooltipBackgroundColor, color: - stylingProps?.tooltipTextColor || theme.colors.charts.linearTimeline.tooltipTextColor, + stylingProps?.tooltipTextColor || theme.chartColors.linearTimeline.tooltipTextColor, }} > {localTimeFormatter(payload[0].value)} @@ -111,9 +111,9 @@ const LinearTimeline = ({ ({ - fill: theme.colors.charts.pie.labelPrimary, + fill: theme.chartColors.pie.labelPrimary, })); const ChartLabelSecondary = styled("text")(({ theme }: { theme: Theme }) => ({ - fill: theme.colors.charts.pie.labelSecondary, + fill: theme.chartColors.pie.labelSecondary, })); const renderActiveShape = (props, options) => { diff --git a/frontend/packages/core/src/Theme/colors.tsx b/frontend/packages/core/src/Theme/colors.tsx index e3e39f9af6..f9d0e3e346 100644 --- a/frontend/packages/core/src/Theme/colors.tsx +++ b/frontend/packages/core/src/Theme/colors.tsx @@ -1,244 +1,8 @@ -import type { ClutchColors, ComponentState, ThemeVariant } from "./types"; - -export enum THEME_VARIANTS { - light = "light", - dark = "dark", -} +import type { ComponentState, ThemeVariant } from "./types"; +import VARIANTS from "./variants"; export const brandColor = "#02acbe"; -const LIGHT_CHART_COLORS: string[] = [ - "#651FFF", - "#FF4081", - "#0091EA", - "#00695C", - "#9E9D24", - "#880E4F", - "#01579B", - "#F4511E", - "#009688", - "#C2185B", - "#1A237E", - "#7C4DFF", - "#88451D", - "#AA00FF", -]; - -const DARK_CHART_COLORS: string[] = [ - "#651FFF", - "#FF4081", - "#0091EA", - "#00695C", - "#9E9D24", - "#880E4F", - "#01579B", - "#F4511E", - "#009688", - "#C2185B", - "#1A237E", - "#7C4DFF", - "#88451D", - "#AA00FF", -]; - -export const LIGHT_COLORS: ClutchColors = { - neutral: { - 50: "#F8F8F9", - 100: "#F0F1F3", - 200: "#DBDBE0", - 300: "#C2C3CB", - 400: "#9E9FAC", - 500: "#868798", - 600: "#56586E", - 700: "#3D4059", - 800: "#252845", - 900: "#0D1030", - A100: "#0D1030", - A200: "#0D1030", - A400: "#0D1030", - A700: "#0D1030", - }, - blue: { - 50: "#F9F9FE", - 100: "#F5F6FD", - 200: "#EBEDFB", - 300: "#D7DAF6", - 400: "#C2C8F2", - 500: "#727FE1", - 600: "#3548D4", - 700: "#1629B9", - 800: "#0A1CA6", - 900: "#011082", - A100: "#011082", - A200: "#011082", - A400: "#011082", - A700: "#011082", - }, - green: { - 50: "#E5FCE8", - 100: "#CBF7CF", - 200: "#ACF2B2", - 300: "#6CD47A", - 400: "#4AB958", - 500: "#32A140", - 600: "#1C872A", - 700: "#106E1D", - 800: "#086515", - 900: "#02590E", - A100: "#02590E", - A200: "#02590E", - A400: "#02590E", - A700: "#02590E", - }, - amber: { - 50: "#FFFBEB", - 100: "#FEF3C7", - 200: "#FDE68A", - 300: "#FCD34D", - 400: "#FBBF24", - 500: "#F59E0B", - 600: "#D97706", - 700: "#B45309", - 800: "#92400E", - 900: "#78350F", - A100: "#78350F", - A200: "#78350F", - A400: "#78350F", - A700: "#78350F", - }, - red: { - 50: "#FFF4F3", - 100: "#FDDCD2", - 200: "#F6A996", - 300: "#F3886E", - 400: "#F26E50", - 500: "#F15534", - 600: "#CA4428", - 700: "#A1301C", - 800: "#792111", - 900: "#571608", - A100: "#571608", - A200: "#571608", - A400: "#571608", - A700: "#571608", - }, - charts: { - common: { - data: LIGHT_CHART_COLORS, - }, - pie: { - labelPrimary: "#0D1030", - labelSecondary: "#868798", - }, - linearTimeline: { - xAxisStroke: "#000", - tooltipBackgroundColor: "#FFF", - tooltipTextColor: "#000", - gridBackgroundColor: "#000", - gridStroke: "#FFF", - }, - }, -}; - -export const DARK_COLORS: ClutchColors = { - neutral: { - 50: "#232542", - 100: "#30324E", - 200: "#3E4059", - 300: "#55566D", - 400: "#77788A", - 500: "#8D8E9E", - 600: "#A4A5B1", - 700: "#D2D2D8", - 800: "#E8E8EB", - 900: "#FFFFFF", - A100: "#FFFFFF", - A200: "#FFFFFF", - A400: "#FFFFFF", - A700: "#FFFFFF", - }, - blue: { - 50: "#090A42", - 100: "#050656", - 200: "#0A086B", - 300: "#13199D", - 400: "#2A4FF6", - 500: "#4281F6", - 600: "#5AABF6", - 700: "#8CC4F8", - 800: "#C2E1FE", - 900: "#DCECFB", - A100: "#DCECFB", - A200: "#DCECFB", - A400: "#DCECFB", - A700: "#DCECFB", - }, - green: { - 50: "#002C05", - 100: "#084713", - 200: "#145F1D", - 300: "#217A2A", - 400: "#2D9638", - 500: "#54B45B", - 600: "#73C178", - 700: "#9CD29E", - 800: "#C3E4C4", - 900: "#E6F4E7", - A100: "#E6F4E7", - A200: "#E6F4E7", - A400: "#E6F4E7", - A700: "#E6F4E7", - }, - amber: { - 50: "#352215", - 100: "#7E3E02", - 200: "#985304", - 300: "#B26A08", - 400: "#CC820D", - 500: "#E69F2A", - 600: "#EAB04E", - 700: "#EFC67F", - 800: "#F6DCB1", - 900: "#FBF1E0", - A100: "#FBF1E0", - A200: "#FBF1E0", - A400: "#FBF1E0", - A700: "#FBF1E0", - }, - red: { - 50: "#501306", - 100: "#621809", - 200: "#751E0D", - 300: "#972814", - 400: "#B3351E", - 500: "#C8482C", - 600: "#EB7A60", - 700: "#F4A08A", - 800: "#F0B9AB", - 900: "#FBE8E7", - A100: "#FFFFFF", - A200: "#FFFFFF", - A400: "#FFFFFF", - A700: "#FFFFFF", - }, - charts: { - common: { - data: DARK_CHART_COLORS, - }, - pie: { - labelPrimary: "#0D1030", - labelSecondary: "#8D8E9E", - }, - linearTimeline: { - xAxisStroke: "#FFF", - tooltipBackgroundColor: "#FFF", - tooltipTextColor: "#000", - gridBackgroundColor: "#FFF", - gridStroke: "#000", - }, - }, -}; - export const STATE_OPACITY: { [key in ComponentState]: number } = { hover: 0.5, focused: 0.1, @@ -247,7 +11,6 @@ export const STATE_OPACITY: { [key in ComponentState]: number } = { disabled: 0.5, }; -const clutchColors = (variant: ThemeVariant) => - variant === THEME_VARIANTS.light ? LIGHT_COLORS : DARK_COLORS; +const clutchColors = (variant: ThemeVariant) => VARIANTS[variant]; export { clutchColors }; diff --git a/frontend/packages/core/src/Theme/index.tsx b/frontend/packages/core/src/Theme/index.tsx index a4243fc5bb..b258508970 100644 --- a/frontend/packages/core/src/Theme/index.tsx +++ b/frontend/packages/core/src/Theme/index.tsx @@ -1,13 +1,43 @@ +import React from "react"; +import type { Theme as MuiTheme } from "@mui/material"; +import { useTheme as useMuiTheme } from "@mui/material"; import { alpha } from "@mui/material/styles"; +import get from "lodash/get"; +import isEmpty from "lodash/isEmpty"; + +import { useUserPreferences } from "../Contexts"; import { STATE_OPACITY } from "./colors"; import ThemeProvider from "./theme"; -import type { ComponentState } from "./types"; +import type { ComponentState, ThemeOverrides } from "./types"; + +interface ThemeProps { + children: React.ReactNode; + overrides?: ThemeOverrides; +} // Return the appropriate color for a specified state and color. const stateColor = (state: ComponentState, color: string) => { return alpha(color, STATE_OPACITY[state]); }; -// TODO: Use the ThemeProvider once the Theme component can be replaced -export { stateColor, ThemeProvider }; +const useTheme = () => useMuiTheme() as MuiTheme; + +const Theme = ({ children, overrides }: ThemeProps) => { + const { preferences } = useUserPreferences(); + + const prefersDarkMode = + window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; + + const themeVariant = get(preferences, "theme"); + + const variant = isEmpty(themeVariant) ? (prefersDarkMode ? "DARK" : "LIGHT") : themeVariant; + + return ( + + {children} + + ); +}; + +export { Theme, useTheme, stateColor, ThemeProvider }; diff --git a/frontend/packages/core/src/Theme/palette.tsx b/frontend/packages/core/src/Theme/palette.tsx index 4b7ecb457e..6e10db1109 100644 --- a/frontend/packages/core/src/Theme/palette.tsx +++ b/frontend/packages/core/src/Theme/palette.tsx @@ -1,38 +1,30 @@ -import type { PaletteOptions as MuiPaletteOptions } from "@mui/material/styles"; import { alpha, TypeText } from "@mui/material/styles"; -import { brandColor, DARK_COLORS, LIGHT_COLORS, THEME_VARIANTS } from "./colors"; -import type { ClutchColors, ThemeVariant } from "./types"; - -interface PaletteOptions extends MuiPaletteOptions { - type: ThemeVariant; - contrastColor: string; - headerGradient: string; - brandColor: string; -} +import { brandColor } from "./colors"; +import type { ClutchColors, PaletteOptions, ThemeVariant } from "./types"; +import VARIANTS from "./variants"; const lightText: Partial = { - primary: LIGHT_COLORS.neutral[900], - secondary: alpha(LIGHT_COLORS.neutral[900], 0.65), + primary: VARIANTS.LIGHT.colors.neutral[900], + secondary: alpha(VARIANTS.LIGHT.colors.neutral[900], 0.65), // tertiary // inverse }; const darkText: Partial = { - primary: alpha(DARK_COLORS.neutral[900], 0.9), - secondary: alpha(DARK_COLORS.neutral[900], 0.75), + primary: alpha(VARIANTS.DARK.colors.neutral[900], 0.9), + secondary: alpha(VARIANTS.DARK.colors.neutral[900], 0.75), // tertiary // inverse }; const palette = (variant: ThemeVariant): PaletteOptions => { - const isLightMode = variant === THEME_VARIANTS.light; - const color = (isLightMode ? LIGHT_COLORS : DARK_COLORS) as ClutchColors; + const isLightMode = variant === "LIGHT"; + const color = (isLightMode ? VARIANTS.LIGHT.colors : VARIANTS.DARK.colors) as ClutchColors; - // TODO: add all clutch colors to "common colors" return { type: variant, - mode: variant, + mode: (variant === "LIGHT" ? "light" : "dark") as PaletteOptions["mode"], brandColor, primary: color.blue, secondary: color.neutral, diff --git a/frontend/packages/core/src/Theme/theme.tsx b/frontend/packages/core/src/Theme/theme.tsx index d2ea3cd33e..4007608cc7 100644 --- a/frontend/packages/core/src/Theme/theme.tsx +++ b/frontend/packages/core/src/Theme/theme.tsx @@ -6,19 +6,43 @@ import { StyledEngineProvider, ThemeProvider as MuiThemeProvider, } from "@mui/material"; +import { defaultsDeep } from "lodash"; -import { clutchColors, THEME_VARIANTS } from "./colors"; +import { clutchColors } from "./colors"; import palette from "./palette"; -import type { ThemeVariant } from "./types"; +import type { + ChartColors, + ClutchColors, + CustomClutchTheme, + ThemeOverrides, + ThemeVariant, +} from "./types"; declare module "@emotion/react" { export interface Theme extends MuiTheme {} } -// Create a Material UI theme is propagated to all children. -const createTheme = (variant: ThemeVariant): MuiTheme => { +declare module "@mui/material/styles" { + interface Theme { + colors: ClutchColors; + chartColors: ChartColors; + } + interface ThemeOptions { + colors?: ClutchColors; + chartColors?: ChartColors; + } + interface Palette { + contrastColor: string; + headerGradient: string; + brandColor: string; + } +} + +const defaultTheme = (variant: ThemeVariant): MuiTheme => { + const { colors, chartColors } = clutchColors(variant); return createMuiTheme({ - colors: clutchColors(variant), + colors, + chartColors, palette: palette(variant), transitions: { // https://material-ui.com/getting-started/faq/#how-can-i-disable-transitions-globally @@ -69,14 +93,30 @@ const createTheme = (variant: ThemeVariant): MuiTheme => { }); }; +const generateTheme = (variant: ThemeVariant, theme?: CustomClutchTheme): MuiTheme => { + const baseTheme = defaultTheme(variant); + if (!theme) { + return baseTheme; + } + const { colors, chartColors, palette: basePalette, ...rest } = baseTheme; + + return createMuiTheme({ + colors: defaultsDeep(theme.colors ?? {}, colors), + chartColors: defaultsDeep(theme.chartColors ?? {}, chartColors), + palette: defaultsDeep(theme?.palette ?? {}, basePalette), + ...defaultsDeep(theme?.themeOptions ?? {}, rest), + }); +}; + interface ThemeProps { variant?: ThemeVariant; children: React.ReactNode; + overrides?: ThemeOverrides; } -const ThemeProvider = ({ children, variant = THEME_VARIANTS.light }: ThemeProps) => ( +const ThemeProvider = ({ children, variant, overrides = {} }: ThemeProps) => ( - + {children} diff --git a/frontend/packages/core/src/Theme/types.tsx b/frontend/packages/core/src/Theme/types.tsx index 7b224cf3a7..4c9cef7bae 100644 --- a/frontend/packages/core/src/Theme/types.tsx +++ b/frontend/packages/core/src/Theme/types.tsx @@ -1,11 +1,9 @@ -import type { Color } from "@mui/material"; +import type { Color, Theme as MuiTheme } from "@mui/material"; +import type { PaletteOptions as MuiPaletteOptions } from "@mui/material/styles"; -export type ThemeVariant = "light" | "dark"; +import type VARIANTS from "./variants"; -export enum THEME_VARIANTS { - light = "light", - dark = "dark", -} +export type ThemeVariant = keyof typeof VARIANTS; export interface StrokeColor { primary: string; @@ -14,21 +12,13 @@ export interface StrokeColor { inverse: string; } -export interface ChartColors { - common: { - data: string[]; - }; - pie: { - labelPrimary: string; - labelSecondary: string; - }; - linearTimeline: { - xAxisStroke: string; - tooltipBackgroundColor: string; - tooltipTextColor: string; - gridBackgroundColor: string; - gridStroke: string; - }; +export interface ThemeOptions extends MuiTheme {} + +export interface PaletteOptions extends MuiPaletteOptions { + type: ThemeVariant; + contrastColor: string; + headerGradient: string; + brandColor: string; } export interface ClutchColors { @@ -37,7 +27,62 @@ export interface ClutchColors { green: Color; amber: Color; red: Color; - charts: ChartColors; } +interface CommonChartColors { + data: string[]; +} + +interface PieChartColors { + labelPrimary: string; + labelSecondary: string; +} + +interface TimelineChartColors { + xAxisStroke: string; + tooltipBackgroundColor: string; + tooltipTextColor: string; + gridBackgroundColor: string; + gridStroke: string; +} + +export interface ChartColors { + common: CommonChartColors; + pie: PieChartColors; + linearTimeline: TimelineChartColors; +} + +export interface ClutchTheme { + colors: ClutchColors; + chartColors: ChartColors; +} + +type Partial = { + [P in keyof T]?: T[P]; +}; + +export type CustomClutchColor = Partial; +export type CustomClutchColors = { + [P in keyof ClutchColors]?: CustomClutchColor; +}; +export type CustomChartColors = { + [P in keyof ChartColors]?: Partial; +}; +export type CustomPalette = { + [P in keyof PaletteOptions]?: Partial; +}; +export type CustomThemeOptions = { + [P in keyof ThemeOptions]?: Partial; +}; +export interface CustomClutchTheme { + colors?: CustomClutchColors; + chartColors?: CustomChartColors; + palette?: CustomPalette; + themeOptions?: CustomThemeOptions; +} + +export type ThemeOverrides = { + [P in ThemeVariant]?: CustomClutchTheme; +}; + export type ComponentState = "hover" | "focused" | "pressed" | "selected" | "disabled"; diff --git a/frontend/packages/core/src/Theme/variants/dark/chart.tsx b/frontend/packages/core/src/Theme/variants/dark/chart.tsx new file mode 100644 index 0000000000..1caf271a66 --- /dev/null +++ b/frontend/packages/core/src/Theme/variants/dark/chart.tsx @@ -0,0 +1,37 @@ +import type { ChartColors } from "../../types"; + +const COLORS: string[] = [ + "#651FFF", + "#FF4081", + "#0091EA", + "#00695C", + "#9E9D24", + "#880E4F", + "#01579B", + "#F4511E", + "#009688", + "#C2185B", + "#1A237E", + "#7C4DFF", + "#88451D", + "#AA00FF", +]; + +const chartColors: ChartColors = { + common: { + data: COLORS, + }, + pie: { + labelPrimary: "#0D1030", + labelSecondary: "#8D8E9E", + }, + linearTimeline: { + xAxisStroke: "#FFF", + tooltipBackgroundColor: "#FFF", + tooltipTextColor: "#000", + gridBackgroundColor: "#FFF", + gridStroke: "#000", + }, +}; + +export default chartColors; diff --git a/frontend/packages/core/src/Theme/variants/dark/colors.tsx b/frontend/packages/core/src/Theme/variants/dark/colors.tsx new file mode 100644 index 0000000000..0a59b93514 --- /dev/null +++ b/frontend/packages/core/src/Theme/variants/dark/colors.tsx @@ -0,0 +1,98 @@ +import type { Color } from "@mui/material"; + +import type { ClutchColors } from "../../types"; + +const neutral: Color = { + 50: "#232542", + 100: "#30324E", + 200: "#3E4059", + 300: "#55566D", + 400: "#77788A", + 500: "#8D8E9E", + 600: "#A4A5B1", + 700: "#D2D2D8", + 800: "#E8E8EB", + 900: "#FFFFFF", + A100: "#FFFFFF", + A200: "#FFFFFF", + A400: "#FFFFFF", + A700: "#FFFFFF", +}; + +const blue: Color = { + 50: "#090A42", + 100: "#050656", + 200: "#0A086B", + 300: "#13199D", + 400: "#2A4FF6", + 500: "#4281F6", + 600: "#5AABF6", + 700: "#8CC4F8", + 800: "#C2E1FE", + 900: "#DCECFB", + A100: "#DCECFB", + A200: "#DCECFB", + A400: "#DCECFB", + A700: "#DCECFB", +}; + +const green: Color = { + 50: "#002C05", + 100: "#084713", + 200: "#145F1D", + 300: "#217A2A", + 400: "#2D9638", + 500: "#54B45B", + 600: "#73C178", + 700: "#9CD29E", + 800: "#C3E4C4", + 900: "#E6F4E7", + A100: "#E6F4E7", + A200: "#E6F4E7", + A400: "#E6F4E7", + A700: "#E6F4E7", +}; + +const amber: Color = { + 50: "#352215", + 100: "#7E3E02", + 200: "#985304", + 300: "#B26A08", + 400: "#CC820D", + 500: "#E69F2A", + 600: "#EAB04E", + 700: "#EFC67F", + 800: "#F6DCB1", + 900: "#FBF1E0", + A100: "#FBF1E0", + A200: "#FBF1E0", + A400: "#FBF1E0", + A700: "#FBF1E0", +}; + +const red: Color = { + 50: "#501306", + 100: "#621809", + 200: "#751E0D", + 300: "#972814", + 400: "#B3351E", + 500: "#C8482C", + 600: "#EB7A60", + 700: "#F4A08A", + 800: "#F0B9AB", + 900: "#FBE8E7", + A100: "#FFFFFF", + A200: "#FFFFFF", + A400: "#FFFFFF", + A700: "#FFFFFF", +}; + +const colors: ClutchColors = { + neutral, + blue, + green, + amber, + red, +}; + +export default colors; diff --git a/frontend/packages/core/src/Theme/variants/dark/index.tsx b/frontend/packages/core/src/Theme/variants/dark/index.tsx new file mode 100644 index 0000000000..9fc7906011 --- /dev/null +++ b/frontend/packages/core/src/Theme/variants/dark/index.tsx @@ -0,0 +1,11 @@ +import type { ClutchTheme } from "../../types"; + +import chartColors from "./chart"; +import colors from "./colors"; + +const DARK_THEME: ClutchTheme = { + chartColors, + colors, +}; + +export default DARK_THEME; diff --git a/frontend/packages/core/src/Theme/variants/index.tsx b/frontend/packages/core/src/Theme/variants/index.tsx new file mode 100644 index 0000000000..3f32e54727 --- /dev/null +++ b/frontend/packages/core/src/Theme/variants/index.tsx @@ -0,0 +1,9 @@ +import DARK_THEME from "./dark"; +import LIGHT_THEME from "./light"; + +const VARIANTS = { + DARK: DARK_THEME, + LIGHT: LIGHT_THEME, +}; + +export default VARIANTS; diff --git a/frontend/packages/core/src/Theme/variants/light/chart.tsx b/frontend/packages/core/src/Theme/variants/light/chart.tsx new file mode 100644 index 0000000000..0b451185df --- /dev/null +++ b/frontend/packages/core/src/Theme/variants/light/chart.tsx @@ -0,0 +1,37 @@ +import type { ChartColors } from "../../types"; + +const COLORS: string[] = [ + "#651FFF", + "#FF4081", + "#0091EA", + "#00695C", + "#9E9D24", + "#880E4F", + "#01579B", + "#F4511E", + "#009688", + "#C2185B", + "#1A237E", + "#7C4DFF", + "#88451D", + "#AA00FF", +]; + +const chartColors: ChartColors = { + common: { + data: COLORS, + }, + pie: { + labelPrimary: "#0D1030", + labelSecondary: "#868798", + }, + linearTimeline: { + xAxisStroke: "#000", + tooltipBackgroundColor: "#FFF", + tooltipTextColor: "#000", + gridBackgroundColor: "#000", + gridStroke: "#FFF", + }, +}; + +export default chartColors; diff --git a/frontend/packages/core/src/Theme/variants/light/colors.tsx b/frontend/packages/core/src/Theme/variants/light/colors.tsx new file mode 100644 index 0000000000..307df39bce --- /dev/null +++ b/frontend/packages/core/src/Theme/variants/light/colors.tsx @@ -0,0 +1,98 @@ +import type { Color } from "@mui/material"; + +import type { ClutchColors } from "../../types"; + +const neutral: Color = { + 50: "#F8F8F9", + 100: "#F0F1F3", + 200: "#DBDBE0", + 300: "#C2C3CB", + 400: "#9E9FAC", + 500: "#868798", + 600: "#56586E", + 700: "#3D4059", + 800: "#252845", + 900: "#0D1030", + A100: "#0D1030", + A200: "#0D1030", + A400: "#0D1030", + A700: "#0D1030", +}; + +const blue: Color = { + 50: "#F9F9FE", + 100: "#F5F6FD", + 200: "#EBEDFB", + 300: "#D7DAF6", + 400: "#C2C8F2", + 500: "#727FE1", + 600: "#3548D4", + 700: "#1629B9", + 800: "#0A1CA6", + 900: "#011082", + A100: "#011082", + A200: "#011082", + A400: "#011082", + A700: "#011082", +}; + +const green: Color = { + 50: "#E5FCE8", + 100: "#CBF7CF", + 200: "#ACF2B2", + 300: "#6CD47A", + 400: "#4AB958", + 500: "#32A140", + 600: "#1C872A", + 700: "#106E1D", + 800: "#086515", + 900: "#02590E", + A100: "#02590E", + A200: "#02590E", + A400: "#02590E", + A700: "#02590E", +}; + +const amber: Color = { + 50: "#FFFBEB", + 100: "#FEF3C7", + 200: "#FDE68A", + 300: "#FCD34D", + 400: "#FBBF24", + 500: "#F59E0B", + 600: "#D97706", + 700: "#B45309", + 800: "#92400E", + 900: "#78350F", + A100: "#78350F", + A200: "#78350F", + A400: "#78350F", + A700: "#78350F", +}; + +const red: Color = { + 50: "#FFF4F3", + 100: "#FDDCD2", + 200: "#F6A996", + 300: "#F3886E", + 400: "#F26E50", + 500: "#F15534", + 600: "#CA4428", + 700: "#A1301C", + 800: "#792111", + 900: "#571608", + A100: "#571608", + A200: "#571608", + A400: "#571608", + A700: "#571608", +}; + +const colors: ClutchColors = { + neutral, + blue, + green, + amber, + red, +}; + +export default colors; diff --git a/frontend/packages/core/src/Theme/variants/light/index.tsx b/frontend/packages/core/src/Theme/variants/light/index.tsx new file mode 100644 index 0000000000..b1ba04dcad --- /dev/null +++ b/frontend/packages/core/src/Theme/variants/light/index.tsx @@ -0,0 +1,11 @@ +import type { ClutchTheme } from "../../types"; + +import chartColors from "./chart"; +import colors from "./colors"; + +const LIGHT: ClutchTheme = { + chartColors, + colors, +}; + +export default LIGHT; diff --git a/frontend/packages/core/src/index.tsx b/frontend/packages/core/src/index.tsx index 66a6be3013..fe86f5739e 100644 --- a/frontend/packages/core/src/index.tsx +++ b/frontend/packages/core/src/index.tsx @@ -59,8 +59,7 @@ export { default as Code } from "./text"; export { default as TimeAgo } from "./timeago"; export { Typography } from "./typography"; export { default as ClutchApp } from "./AppProvider"; -export { useTheme } from "./AppProvider/themes"; -export { ThemeProvider } from "./Theme"; +export { ThemeProvider, useTheme } from "./Theme"; export { css as EMOTION_CSS, keyframes as EMOTION_KEYFRAMES } from "@emotion/react"; @@ -77,3 +76,12 @@ export type { WorkflowRemoveDataFn, WorkflowRetrieveDataFn, WorkflowStoreDataFn export type { ClutchError } from "./Network/errors"; export type { TypographyProps } from "./typography"; export type { StyledComponent } from "@emotion/styled"; +export type { + CustomClutchColor, + CustomClutchColors, + CustomChartColors, + CustomPalette, + CustomThemeOptions, + CustomClutchTheme, + ThemeOverrides, +} from "./Theme/types"; diff --git a/frontend/packages/core/src/landing.tsx b/frontend/packages/core/src/landing.tsx index 888fc21f98..5421494916 100644 --- a/frontend/packages/core/src/landing.tsx +++ b/frontend/packages/core/src/landing.tsx @@ -6,7 +6,6 @@ import Typography from "@mui/material/Typography"; import { userId } from "./AppLayout/user"; import { workflowsByTrending } from "./AppLayout/utils"; import { MonsterGraphic } from "./Assets/Graphics"; -import { THEME_VARIANTS } from "./Theme/colors"; import { LandingCard } from "./card"; import { useAppContext } from "./Contexts"; import { useNavigate } from "./navigation"; @@ -18,9 +17,7 @@ const StyledLanding = styled.div(({ theme }: { theme: Theme }) => ({ "& .welcome": { display: "flex", backgroundColor: - theme.palette.mode === THEME_VARIANTS.light - ? theme.palette.contrastColor - : theme.palette.background.paper, + theme.palette.mode === "light" ? theme.palette.contrastColor : theme.palette.background.paper, padding: "32px 80px", }, diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 7c66de43f4..802466ab83 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "./tsconfig.base.json", "compilerOptions": { + "composite": false, "outDir": "dist", "paths": { "@clutch-sh/*": ["api/*", "packages/*/src", "workflows/*/src"] diff --git a/tools/setup-git-hooks.sh b/tools/setup-git-hooks.sh index 8481c6d3d2..7a165a73d7 100755 --- a/tools/setup-git-hooks.sh +++ b/tools/setup-git-hooks.sh @@ -13,5 +13,7 @@ fi GITHUB_ROOT="${SCRIPT_ROOT}/.github" GIT_REPO_ROOT="${REPO_ROOT}/.git" -echo "Setting up git pre-commit hooks for ${REPO_ROOT}" -ln -s -f "${GITHUB_ROOT}/hooks/pre-commit" "${GIT_REPO_ROOT}/hooks/pre-commit" +if [[ -f "${GITHUB_ROOT}/hooks/pre-commit" && -f "${GIT_REPO_ROOT}/hooks/pre-commit" ]]; then + echo "Setting up git pre-commit hooks for ${REPO_ROOT}" + ln -s -f "${GITHUB_ROOT}/hooks/pre-commit" "${GIT_REPO_ROOT}/hooks/pre-commit" +fi