diff --git a/src/App.tsx b/src/App.tsx index 76efcff..9cb8c71 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,5 @@ import Home from './pages/home/Home.tsx'; -import { StylesProvider } from './styles/styles.provider.tsx'; +import { StylesProvider } from 'providers/StylesProvider.tsx'; function App() { return ( diff --git a/src/components/CloseIcon/InfoIcon.styled.ts b/src/components/CloseIcon/InfoIcon.styled.ts index efaa3da..baa19a1 100644 --- a/src/components/CloseIcon/InfoIcon.styled.ts +++ b/src/components/CloseIcon/InfoIcon.styled.ts @@ -4,10 +4,10 @@ import { css } from '@emotion/react'; export const Closed = styled.svg( ({ theme }) => css` cursor: pointer; - fill: ${theme.custom.colors.onContainerNormal}; + fill: ${theme.custom.colors.onContainer.normal}; &:hover { - fill: ${theme.custom.colors.text}; + fill: ${theme.custom.colors.onContainer.contrast}; } ` ); diff --git a/src/components/InfoIcon/InfoIcon.styled.ts b/src/components/InfoIcon/InfoIcon.styled.ts index 156de9e..c09f943 100644 --- a/src/components/InfoIcon/InfoIcon.styled.ts +++ b/src/components/InfoIcon/InfoIcon.styled.ts @@ -7,10 +7,10 @@ export const Info = styled.svg( top: 4px; right: 4px; cursor: pointer; - fill: ${theme.custom.colors.onContainerNormal}; + fill: ${theme.custom.colors.onContainer.normal}; &:hover { - fill: ${theme.custom.colors.text}; + fill: ${theme.custom.colors.onContainer.contrast}; } ` ); diff --git a/src/components/MoonIcon/MoonIcon.styled.ts b/src/components/MoonIcon/MoonIcon.styled.ts index b7d045d..28221d9 100644 --- a/src/components/MoonIcon/MoonIcon.styled.ts +++ b/src/components/MoonIcon/MoonIcon.styled.ts @@ -4,6 +4,6 @@ import { css } from '@emotion/react'; export const Sun = styled.svg( ({ theme }) => css` cursor: pointer; - fill: ${theme.custom.colors.text}; + fill: ${theme.custom.colors.onContainer.contrast}; ` ); diff --git a/src/components/MoonIcon/MoonIcon.tsx b/src/components/MoonIcon/MoonIcon.tsx index 4ad14df..43c3b31 100644 --- a/src/components/MoonIcon/MoonIcon.tsx +++ b/src/components/MoonIcon/MoonIcon.tsx @@ -9,7 +9,7 @@ function MoonIcon({ onClick: () => void; }) { const theme = useTheme(); - const textColor = theme.custom.colors.text; + const textColor = theme.custom.colors.onContainer.contrast; return ( css` cursor: pointer; - fill: ${theme.custom.colors.text}; + fill: ${theme.custom.colors.onContainer.contrast}; ` ); diff --git a/src/components/SunIcon/SunIcon.tsx b/src/components/SunIcon/SunIcon.tsx index 236ee43..7488b99 100644 --- a/src/components/SunIcon/SunIcon.tsx +++ b/src/components/SunIcon/SunIcon.tsx @@ -9,7 +9,7 @@ function SunIcon({ onClick: () => void; }) { const theme = useTheme(); - const textColor = theme.custom.colors.text; + const textColor = theme.custom.colors.onContainer.contrast; return ( css` - border: 1px solid ${theme.custom.colors.wheel.background}; + border: 1px solid ${theme.custom.colors.onContainer.dim}; background: ${theme.custom.colors.container}; margin: 0; padding: 10px; diff --git a/src/pages/home/sections/Callstack/Callstack.styled.ts b/src/pages/home/sections/Callstack/Callstack.styled.ts index 8e50c6c..4d1e743 100644 --- a/src/pages/home/sections/Callstack/Callstack.styled.ts +++ b/src/pages/home/sections/Callstack/Callstack.styled.ts @@ -12,7 +12,7 @@ export const Callstack = styled.div` export const CallstackElement = styled.div( ({ theme }) => css` - background: ${theme.custom.colors.onContainerNormal}; + background: ${theme.custom.colors.onContainer.dim}; border-radius: 5px; padding: 10px; word-wrap: break-word; diff --git a/src/pages/home/sections/Configurator/Editor/Editor.styled.ts b/src/pages/home/sections/Configurator/Editor/Editor.styled.ts index 5b0b187..c568894 100644 --- a/src/pages/home/sections/Configurator/Editor/Editor.styled.ts +++ b/src/pages/home/sections/Configurator/Editor/Editor.styled.ts @@ -10,16 +10,17 @@ export const EditorWrapper = styled.div( } .ace_gutter { - background: ${theme.custom.colors.wheel.background}; + background: ${theme.custom.colors.onContainer.dim}; } .selected_lines { position: absolute; - background: ${theme.custom.colors.wheel.macrotask.disabled}; + background: ${theme.custom.colors.tertiary}; + opacity: 0.3; } .ace_gutter-active-line { - background: ${theme.custom.colors.wheel.background}; + background: ${theme.custom.colors.onContainer.dim}; } .ace_content { diff --git a/src/pages/home/sections/Console/Console.styled.ts b/src/pages/home/sections/Console/Console.styled.ts index f38c3d9..dd9ff5e 100644 --- a/src/pages/home/sections/Console/Console.styled.ts +++ b/src/pages/home/sections/Console/Console.styled.ts @@ -11,7 +11,7 @@ export const LogQueue = styled.div` export const Log = styled.div( ({ theme }) => css` - background: ${theme.custom.colors.onContainerNormal}; + background: ${theme.custom.colors.onContainer.dim}; border-radius: 5px; padding: 10px; word-wrap: break-word; diff --git a/src/pages/home/sections/MicroTasksQueue/MicroTasksQueue.styled.ts b/src/pages/home/sections/MicroTasksQueue/MicroTasksQueue.styled.ts index 61a0980..09307b7 100644 --- a/src/pages/home/sections/MicroTasksQueue/MicroTasksQueue.styled.ts +++ b/src/pages/home/sections/MicroTasksQueue/MicroTasksQueue.styled.ts @@ -11,7 +11,7 @@ export const MicroTasksQueue = styled.div` export const MicroTask = styled.div( ({ theme }) => css` - background: ${theme.custom.colors.onContainerNormal}; + background: ${theme.custom.colors.onContainer.dim}; flex: 1; display: flex; justify-content: center; diff --git a/src/pages/home/sections/RequestAnimationFrameQueue/RequestAnimationFrameQueue.styled.ts b/src/pages/home/sections/RequestAnimationFrameQueue/RequestAnimationFrameQueue.styled.ts index af2e8ca..cf1d28d 100644 --- a/src/pages/home/sections/RequestAnimationFrameQueue/RequestAnimationFrameQueue.styled.ts +++ b/src/pages/home/sections/RequestAnimationFrameQueue/RequestAnimationFrameQueue.styled.ts @@ -11,7 +11,7 @@ export const CallbacksQueue = styled.div` export const Callback = styled.div( ({ theme }) => css` - background: ${theme.custom.colors.onContainerNormal}; + background: ${theme.custom.colors.onContainer.dim}; flex: 1; display: flex; justify-content: center; diff --git a/src/pages/home/sections/TasksQueue/TasksQueue.styled.ts b/src/pages/home/sections/TasksQueue/TasksQueue.styled.ts index a296eb2..5d78ef1 100644 --- a/src/pages/home/sections/TasksQueue/TasksQueue.styled.ts +++ b/src/pages/home/sections/TasksQueue/TasksQueue.styled.ts @@ -11,7 +11,7 @@ export const TasksQueue = styled.div` export const Task = styled.div( ({ theme }) => css` - background: ${theme.custom.colors.onContainerNormal}; + background: ${theme.custom.colors.onContainer.dim}; flex: 1; display: flex; justify-content: center; diff --git a/src/pages/home/sections/WebApiQueue/WebApiTask.styled.ts b/src/pages/home/sections/WebApiQueue/WebApiTask.styled.ts index dc7ece8..66dd351 100644 --- a/src/pages/home/sections/WebApiQueue/WebApiTask.styled.ts +++ b/src/pages/home/sections/WebApiQueue/WebApiTask.styled.ts @@ -3,7 +3,7 @@ import { css } from '@emotion/react'; export const WebApiItem = styled.div( ({ theme }) => css` - background: ${theme.custom.colors.onContainerNormal}; + background: ${theme.custom.colors.onContainer.dim}; border-radius: 5px; padding: 10px; position: absolute; @@ -22,8 +22,8 @@ export const Progress = styled.div<{ progress: number }>( ({ theme, progress }) => css` background-color: transparent; background-image: conic-gradient( - ${theme.custom.colors.onContainerContrast}, - ${theme.custom.colors.onContainerContrast} ${progress}%, + ${theme.custom.colors.onContainer.contrast}, + ${theme.custom.colors.onContainer.contrast} ${progress}%, transparent ${progress}% ); border-radius: 5px; diff --git a/src/pages/home/sections/Wheel/Pointer/Pointer.styled.ts b/src/pages/home/sections/Wheel/Pointer/Pointer.styled.ts index cb1689e..b1dfb65 100644 --- a/src/pages/home/sections/Wheel/Pointer/Pointer.styled.ts +++ b/src/pages/home/sections/Wheel/Pointer/Pointer.styled.ts @@ -30,7 +30,7 @@ export const SectorWithInnerBorder = styled.div( border-image: linear-gradient( to right, transparent 50%, - ${colors.text} 50% + ${colors.onContainer.contrast} 50% ); box-sizing: border-box; @@ -46,7 +46,8 @@ export const SectorWithInnerBorder = styled.div( 0 0; transform-origin: 50% 100%; transform: rotate(160deg); - border-left: ${eventLoopPointerBorderWidth}px solid ${colors.text}; + border-left: ${eventLoopPointerBorderWidth}px solid + ${colors.onContainer.contrast}; box-sizing: border-box; left: 0; } @@ -66,7 +67,11 @@ export const SectorWithOuterBorder = styled.div( transform-origin: 50% 100%; transform: rotate(280deg); border-bottom: ${widths.eventLoopPointerBorderWidth}px solid transparent; - border-image: linear-gradient(to right, transparent 50%, ${colors.text} 50%) + border-image: linear-gradient( + to right, + transparent 50%, + ${colors.onContainer.contrast} 50% + ) 1; box-sizing: border-box; @@ -77,10 +82,11 @@ export const SectorWithOuterBorder = styled.div( content: ''; border-radius: ${widths.eventLoopRadius}px ${widths.eventLoopRadius}px 0 0; border-bottom: ${widths.eventLoopPointerBorderWidth}px solid - ${colors.text}; + ${colors.onContainer.contrast}; transform-origin: 50% 100%; transform: rotate(160deg); - border-left: ${widths.eventLoopPointerBorderWidth}px solid ${colors.text}; + border-left: ${widths.eventLoopPointerBorderWidth}px solid + ${colors.onContainer.contrast}; box-sizing: border-box; left: 0; } diff --git a/src/pages/home/sections/Wheel/Wheel.styled.ts b/src/pages/home/sections/Wheel/Wheel.styled.ts index f029e6f..b87a3e9 100644 --- a/src/pages/home/sections/Wheel/Wheel.styled.ts +++ b/src/pages/home/sections/Wheel/Wheel.styled.ts @@ -30,13 +30,31 @@ export const CircleOuter = styled.div( left: 0; right: 0; bottom: 0; - background: ${theme.custom.colors.wheel.background}; + background: ${theme.custom.colors.onContainer.dim}; border-radius: 50%; ` ); -export const Sector = styled.div<{ background: string; degree: number }>( - ({ theme, background, degree }) => css` +export const Sector = styled.div<{ + background: string; + degree: number; + enabled: boolean; +}>(({ theme, background, degree, enabled }) => { + const saturation = { + light: 2, + dark: 1.3, + }[theme.custom.mode]; + const brightness = { + light: { + enabled: 1.4, + disabled: 1, + }, + dark: { + enabled: 1, + disabled: 0.8, + }, + }[theme.custom.mode]; + return css` height: ${theme.custom.widths.eventLoopRadius}px; width: ${theme.custom.widths.eventLoopDiameter}px; overflow: hidden; @@ -52,12 +70,15 @@ export const Sector = styled.div<{ background: string; degree: number }>( border-radius: ${theme.custom.widths.eventLoopRadius}px ${theme.custom.widths.eventLoopRadius}px 0 0; background-color: ${background}; + filter: saturate(${saturation}) + brightness(${enabled ? brightness.enabled : brightness.disabled}); + opacity: ${enabled ? 1 : 0.3}; transform-origin: 50% 100%; transform: rotate(160deg); left: 0; } - ` -); + `; +}); export const CloseIcon = styled(InfoClosed)` position: absolute; diff --git a/src/pages/home/sections/Wheel/Wheel.tsx b/src/pages/home/sections/Wheel/Wheel.tsx index 961fb47..190d726 100644 --- a/src/pages/home/sections/Wheel/Wheel.tsx +++ b/src/pages/home/sections/Wheel/Wheel.tsx @@ -18,6 +18,13 @@ function Wheel({ className }: { className?: string }) { const theme = useTheme(); const [isOpened, toggle] = useBoolean(false); + const { primary, secondary, tertiary } = theme.custom.colors; + const colors = { + microtask: primary, + macrotask: secondary, + render: tertiary, + }; + return (

Event Loop

@@ -26,12 +33,13 @@ function Wheel({ className }: { className?: string }) { {events.map(({ degree, type }) => { - const enabled = stops[type] ? 'enabled' : 'disabled'; - const background = theme.custom.colors.wheel[type][enabled]; + const enabled = stops[type]; + const background = colors[type]; return ( diff --git a/src/styles/styles.provider.tsx b/src/providers/StylesProvider.tsx similarity index 62% rename from src/styles/styles.provider.tsx rename to src/providers/StylesProvider.tsx index 7a16554..ffb6a19 100644 --- a/src/styles/styles.provider.tsx +++ b/src/providers/StylesProvider.tsx @@ -1,12 +1,14 @@ import { Global, ThemeProvider } from '@emotion/react'; import { PropsWithChildren } from 'react'; import { useThemeStore } from 'store/store.ts'; -import { darkTheme, lightTheme } from './styles.theme.ts'; -import { getGlobalStyles } from './styles.utils.ts'; +import { getGlobalStyles } from './StylesProvider.utils.ts'; +import { colorsDark, colorsLight } from '../theme/colors.ts'; +import { getTheme } from '../theme/theme.ts'; export function StylesProvider({ children }: PropsWithChildren) { const { isDark } = useThemeStore(); - const theme = isDark ? darkTheme : lightTheme; + const palette = isDark ? colorsDark : colorsLight; + const theme = getTheme(palette); const globalStyles = getGlobalStyles({ theme }); return ( diff --git a/src/styles/styles.utils.ts b/src/providers/StylesProvider.utils.ts similarity index 79% rename from src/styles/styles.utils.ts rename to src/providers/StylesProvider.utils.ts index d0df2ca..81ee71c 100644 --- a/src/styles/styles.utils.ts +++ b/src/providers/StylesProvider.utils.ts @@ -3,7 +3,7 @@ import { css, Theme } from '@emotion/react'; export const getGlobalStyles = ({ theme }: { theme: Theme }) => css` html { font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - color: ${theme.custom.colors.text}; + color: ${theme.custom.colors.onBackground}; background-color: ${theme.custom.colors.background}; height: 100%; } @@ -25,7 +25,7 @@ export const getGlobalStyles = ({ theme }: { theme: Theme }) => css` } a { - color: ${theme.custom.colors.text}; + color: ${theme.custom.colors.onBackground}; } body { @@ -56,10 +56,10 @@ export const getGlobalStyles = ({ theme }: { theme: Theme }) => css` } ::-webkit-scrollbar-thumb { - background: ${theme.custom.colors.onContainerNormal}; + background: ${theme.custom.colors.onContainer.normal}; } :focus-visible { - outline: 2px solid ${theme.custom.colors.onContainerNormal}; + outline: 2px solid ${theme.custom.colors.onContainer.normal}; } `; diff --git a/src/styles/styles.theme.ts b/src/styles/styles.theme.ts deleted file mode 100644 index e2e2358..0000000 --- a/src/styles/styles.theme.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { createTheme } from '@mui/material'; -import { Theme } from '@emotion/react'; - -const getMuiTheme = (isDark: boolean) => - createTheme({ - palette: { - mode: isDark ? 'dark' : 'light', - primary: { - main: isDark ? '#35495a' : '#42729E', - }, - }, - typography: { - fontSize: 12, - }, - components: { - MuiTooltip: { - styleOverrides: { - tooltip: { - fontSize: '14', - color: isDark ? 'rgba(255, 255, 255, 0.87)' : 'rgba(0, 0, 0, 0.75)', - backgroundColor: isDark ? '#35495a' : '#C5D7E7', - }, - }, - }, - MuiMenu: { - styleOverrides: { - list: { - backgroundColor: isDark ? '#35495a' : '#A9C3DB', - }, - }, - }, - MuiSelect: { - styleOverrides: { - root: { - '&.Mui-focused .MuiOutlinedInput-notchedOutline': { - borderColor: isDark ? 'gray' : '#42729E', - }, - }, - }, - }, - MuiInputLabel: { - styleOverrides: { - root: { - '&.Mui-focused': { - color: isDark ? 'gray' : '#42729E', - }, - }, - }, - }, - }, - }); - -const sharedCustomTheme = { - breakpoints: { - desktop: 768, - }, - widths: { - eventLoopRadius: 150, - eventLoopDiameter: 300, - eventLoopWheelWidth: 50, - eventLoopPointerBorderWidth: 4, - }, -}; - -export const darkTheme: Theme = { - ...getMuiTheme(true), - custom: { - ...sharedCustomTheme, - colors: { - background: '#0D151C', - container: '#131f2a', - onContainerNormal: '#35495a', - onContainerContrast: '#3d92e1', - text: 'rgba(255, 255, 255, 0.87)', - - wheel: { - background: '#1A2A38', - microtask: { - disabled: '#35495a', - enabled: '#3d92e1', - }, - macrotask: { - disabled: '#3e594c', - enabled: '#0FC469', - }, - render: { - disabled: '#64493e', - enabled: '#d5600c', - }, - }, - }, - }, -}; - -export const lightTheme: Theme = { - ...getMuiTheme(false), - custom: { - ...sharedCustomTheme, - colors: { - background: '#C5D7E7', - container: '#A9C3DB', - onContainerNormal: '#8CAFCF', - onContainerContrast: '#22476D', - text: '#1D3D5E', - - wheel: { - background: '#7797B6', - microtask: { - disabled: '#9BAD86', - enabled: '#B0D982', - }, - macrotask: { - disabled: '#CC9076', - enabled: '#FF8957', - }, - render: { - disabled: '#976D84', - enabled: '#D971AA', - }, - }, - }, - }, -}; diff --git a/src/theme/colors.ts b/src/theme/colors.ts new file mode 100644 index 0000000..41b908e --- /dev/null +++ b/src/theme/colors.ts @@ -0,0 +1,38 @@ +import { PaletteMode } from '@mui/material'; +import { palette } from './palette.ts'; + +export type ColorsSystem = typeof colorsLight | typeof colorsDark; + +export const colorsDark = { + mode: 'dark' as PaletteMode, + colors: { + background: palette.primary['5'], + onBackground: palette.primary['90'], + container: palette.primary['10'], + onContainer: { + dim: palette.primary['15'], + normal: palette.primary['50'], + contrast: palette.primary['90'], + }, + primary: palette.primary['60'], + secondary: palette.secondary['60'], + tertiary: palette.tertiary['60'], + }, +}; + +export const colorsLight = { + mode: 'light' as PaletteMode, + colors: { + background: palette.primary['95'], + onBackground: palette.primary['20'], + container: palette.primary['90'], + onContainer: { + dim: palette.primary['80'], + normal: palette.primary['50'], + contrast: palette.primary['30'], + }, + primary: palette.primary['50'], + secondary: palette.secondary['50'], + tertiary: palette.tertiary['50'], + }, +}; diff --git a/src/theme/palette.ts b/src/theme/palette.ts new file mode 100644 index 0000000..f97bc65 --- /dev/null +++ b/src/theme/palette.ts @@ -0,0 +1,83 @@ +//https://coolors.co/264653-6d9f71-a65961 +export const palette = { + primary: { + '0': '#000000', + '5': '#00131B', + '10': '#001F29', + '15': '#042936', + '20': '#123441', + '25': '#1F3F4C', + '30': '#2B4B58', + '35': '#375764', + '40': '#436370', + '50': '#5C7C8A', + '60': '#7595A4', + '70': '#90B0BF', + '80': '#ABCBDB', + '90': '#C6E8F8', + '95': '#DFF4FF', + '98': '#F3FAFF', + '99': '#FAFCFF', + '100': '#FFFFFF', + }, + secondary: { + '0': '#000000', + '5': '#001504', + '10': '#002108', + '15': '#002D0E', + '20': '#053915', + '25': '#14441F', + '30': '#21502A', + '35': '#2D5C35', + '40': '#396940', + '50': '#518257', + '60': '#6A9C6F', + '70': '#84B787', + '80': '#9FD3A1', + '90': '#BAF0BC', + '95': '#C8FEC9', + '98': '#EBFFE7', + '99': '#F6FFF1', + '100': '#FFFFFF', + }, + tertiary: { + '0': '#000000', + '5': '#2C0008', + '10': '#3C0611', + '15': '#4A101A', + '20': '#581B24', + '25': '#66262F', + '30': '#74313A', + '35': '#823D45', + '40': '#914850', + '50': '#AF6068', + '60': '#CD7981', + '70': '#EB929A', + '80': '#FFB2B8', + '90': '#FFDADB', + '95': '#FFECED', + '98': '#FFF8F7', + '99': '#FFFBFF', + '100': '#FFFFFF', + }, + neutral: { + '0': '#000000', + '5': '#101112', + '10': '#1B1C1C', + '15': '#252626', + '20': '#303031', + '25': '#3B3B3C', + '30': '#464747', + '35': '#525253', + '40': '#5E5E5F', + '50': '#777777', + '60': '#919091', + '70': '#ACABAB', + '80': '#C7C6C6', + '90': '#E4E2E2', + '95': '#F2F0F0', + '98': '#FBF9F9', + '99': '#FEFCFC', + '100': '#FFFFFF', + }, +}; diff --git a/src/theme/theme.ts b/src/theme/theme.ts new file mode 100644 index 0000000..1db5330 --- /dev/null +++ b/src/theme/theme.ts @@ -0,0 +1,84 @@ +import { ColorsSystem } from './colors.ts'; +import { createTheme } from '@mui/material'; +import { Theme } from '@emotion/react'; + +export const getMuiTheme = (cs: ColorsSystem) => + createTheme({ + palette: { + mode: cs.mode, + primary: { + main: cs.colors.onContainer.contrast, + }, + }, + typography: { + fontSize: 12, + }, + components: { + MuiTooltip: { + styleOverrides: { + tooltip: { + fontSize: '14', + color: cs.colors.onContainer.contrast, + backgroundColor: cs.colors.onContainer.dim, + }, + }, + }, + MuiMenu: { + styleOverrides: { + list: { + backgroundColor: cs.colors.onContainer.dim, + }, + }, + }, + MuiSelect: { + styleOverrides: { + root: { + '&.Mui-focused .MuiOutlinedInput-notchedOutline': { + borderColor: cs.colors.onContainer.normal, + }, + }, + }, + }, + MuiInputLabel: { + styleOverrides: { + root: { + '&.Mui-focused': { + color: cs.colors.onContainer.contrast, + }, + }, + }, + }, + }, + }); + +export const getTheme = (cs: ColorsSystem): Theme => { + const { colors } = cs; + return { + ...getMuiTheme(cs), + custom: { + mode: cs.mode, + breakpoints: { + desktop: 768, + }, + widths: { + eventLoopRadius: 150, + eventLoopDiameter: 300, + eventLoopWheelWidth: 50, + eventLoopPointerBorderWidth: 4, + }, + colors: { + background: colors.background, + onBackground: colors.onBackground, + container: colors.container, + onContainer: { + dim: colors.onContainer.dim, + normal: colors.onContainer.normal, + contrast: colors.onContainer.contrast, + }, + primary: colors.primary, + secondary: colors.secondary, + tertiary: colors.tertiary, + }, + }, + }; +};