aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-08-12 21:57:01 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-08-12 22:05:43 +0200
commit66216786a70e415775cf7e4b84cfd7d74b07aad0 (patch)
treea47dc186fb309627c069edacf9754b9ec483d0a4 /subprojects
parentrefactor(frontend): EditorParent line numbers (diff)
downloadrefinery-66216786a70e415775cf7e4b84cfd7d74b07aad0.tar.gz
refinery-66216786a70e415775cf7e4b84cfd7d74b07aad0.tar.zst
refinery-66216786a70e415775cf7e4b84cfd7d74b07aad0.zip
feat(frontend): light/dark mode switch
Diffstat (limited to 'subprojects')
-rw-r--r--subprojects/frontend/src/App.tsx22
-rw-r--r--subprojects/frontend/src/ToggleDarkModeButton.tsx24
-rw-r--r--subprojects/frontend/src/TopBar.tsx29
-rw-r--r--subprojects/frontend/src/editor/EditorParent.ts25
-rw-r--r--subprojects/frontend/src/theme/ThemeProvider.tsx65
5 files changed, 118 insertions, 47 deletions
diff --git a/subprojects/frontend/src/App.tsx b/subprojects/frontend/src/App.tsx
index d3ec63eb..12cf9311 100644
--- a/subprojects/frontend/src/App.tsx
+++ b/subprojects/frontend/src/App.tsx
@@ -1,11 +1,7 @@
1import MenuIcon from '@mui/icons-material/Menu';
2import AppBar from '@mui/material/AppBar';
3import Box from '@mui/material/Box'; 1import Box from '@mui/material/Box';
4import IconButton from '@mui/material/IconButton';
5import Toolbar from '@mui/material/Toolbar';
6import Typography from '@mui/material/Typography';
7import React from 'react'; 2import React from 'react';
8 3
4import TopBar from './TopBar';
9import EditorArea from './editor/EditorArea'; 5import EditorArea from './editor/EditorArea';
10import EditorButtons from './editor/EditorButtons'; 6import EditorButtons from './editor/EditorButtons';
11import GenerateButton from './editor/GenerateButton'; 7import GenerateButton from './editor/GenerateButton';
@@ -13,21 +9,7 @@ import GenerateButton from './editor/GenerateButton';
13export default function App(): JSX.Element { 9export default function App(): JSX.Element {
14 return ( 10 return (
15 <Box display="flex" flexDirection="column" sx={{ height: '100vh' }}> 11 <Box display="flex" flexDirection="column" sx={{ height: '100vh' }}>
16 <AppBar position="static" color="inherit"> 12 <TopBar />
17 <Toolbar>
18 <IconButton
19 edge="start"
20 sx={{ mr: 2 }}
21 color="inherit"
22 aria-label="menu"
23 >
24 <MenuIcon />
25 </IconButton>
26 <Typography variant="h6" component="h1" flexGrow={1}>
27 Refinery
28 </Typography>
29 </Toolbar>
30 </AppBar>
31 <Box 13 <Box
32 display="flex" 14 display="flex"
33 justifyContent="space-between" 15 justifyContent="space-between"
diff --git a/subprojects/frontend/src/ToggleDarkModeButton.tsx b/subprojects/frontend/src/ToggleDarkModeButton.tsx
new file mode 100644
index 00000000..1685ec80
--- /dev/null
+++ b/subprojects/frontend/src/ToggleDarkModeButton.tsx
@@ -0,0 +1,24 @@
1import DarkModeIcon from '@mui/icons-material/DarkMode';
2import LightModeIcon from '@mui/icons-material/LightMode';
3import IconButton from '@mui/material/IconButton';
4import { observer } from 'mobx-react-lite';
5import React from 'react';
6
7import { useRootStore } from './RootStore';
8
9function ToggleDarkModeButton(): JSX.Element {
10 const { themeStore } = useRootStore();
11 const { darkMode } = themeStore;
12
13 return (
14 <IconButton
15 color="inherit"
16 onClick={() => themeStore.toggleDarkMode()}
17 aria-label={darkMode ? 'Switch to light mode' : 'Switch to dark mode'}
18 >
19 {darkMode ? <LightModeIcon /> : <DarkModeIcon />}
20 </IconButton>
21 );
22}
23
24export default observer(ToggleDarkModeButton);
diff --git a/subprojects/frontend/src/TopBar.tsx b/subprojects/frontend/src/TopBar.tsx
new file mode 100644
index 00000000..5ac74e7a
--- /dev/null
+++ b/subprojects/frontend/src/TopBar.tsx
@@ -0,0 +1,29 @@
1import MenuIcon from '@mui/icons-material/Menu';
2import AppBar from '@mui/material/AppBar';
3import IconButton from '@mui/material/IconButton';
4import Toolbar from '@mui/material/Toolbar';
5import Typography from '@mui/material/Typography';
6import React from 'react';
7
8import ToggleDarkModeButton from './ToggleDarkModeButton';
9
10export default function TopBar(): JSX.Element {
11 return (
12 <AppBar position="static" color="primary">
13 <Toolbar>
14 <IconButton
15 edge="start"
16 sx={{ mr: 2 }}
17 color="inherit"
18 aria-label="menu"
19 >
20 <MenuIcon />
21 </IconButton>
22 <Typography variant="h6" component="h1" flexGrow={1}>
23 Refinery
24 </Typography>
25 <ToggleDarkModeButton />
26 </Toolbar>
27 </AppBar>
28 );
29}
diff --git a/subprojects/frontend/src/editor/EditorParent.ts b/subprojects/frontend/src/editor/EditorParent.ts
index a4cdfa38..805065fc 100644
--- a/subprojects/frontend/src/editor/EditorParent.ts
+++ b/subprojects/frontend/src/editor/EditorParent.ts
@@ -90,12 +90,12 @@ export default styled('div', {
90 borderLeft: `2px solid ${theme.palette.primary.main}`, 90 borderLeft: `2px solid ${theme.palette.primary.main}`,
91 }, 91 },
92 '.cm-selectionBackground': { 92 '.cm-selectionBackground': {
93 background: '#3e4453', 93 background: theme.palette.selection.main,
94 }, 94 },
95 '.cm-focused': { 95 '.cm-focused': {
96 outline: 'none', 96 outline: 'none',
97 '.cm-selectionBackground': { 97 '.cm-selectionBackground': {
98 background: '#3e4453', 98 background: theme.palette.selection.main,
99 }, 99 },
100 }, 100 },
101 '.cm-panels-top': { 101 '.cm-panels-top': {
@@ -123,10 +123,11 @@ export default styled('div', {
123 li: { 123 li: {
124 borderBottom: `1px solid ${theme.palette.divider}`, 124 borderBottom: `1px solid ${theme.palette.divider}`,
125 cursor: 'pointer', 125 cursor: 'pointer',
126 color: theme.palette.text.primary,
126 }, 127 },
127 '[aria-selected]': { 128 '[aria-selected]': {
128 background: '#3e4453', 129 background: theme.palette.selection.main,
129 color: theme.palette.text.primary, 130 color: theme.palette.selection.contrastText,
130 }, 131 },
131 '&:focus [aria-selected]': { 132 '&:focus [aria-selected]': {
132 background: theme.palette.primary.main, 133 background: theme.palette.primary.main,
@@ -161,7 +162,7 @@ export default styled('div', {
161 color: theme.palette.text.disabled, 162 color: theme.palette.text.disabled,
162 }, 163 },
163 '.tok-number': { 164 '.tok-number': {
164 color: '#6188a6', 165 color: theme.palette.highlight.number,
165 }, 166 },
166 '.tok-string': { 167 '.tok-string': {
167 color: theme.palette.secondary.dark, 168 color: theme.palette.secondary.dark,
@@ -173,7 +174,7 @@ export default styled('div', {
173 color: theme.palette.text.primary, 174 color: theme.palette.text.primary,
174 }, 175 },
175 '.tok-variableName': { 176 '.tok-variableName': {
176 color: '#c8ae9d', 177 color: theme.palette.highlight.parameter,
177 }, 178 },
178 '.tok-problem-node': { 179 '.tok-problem-node': {
179 '&, & .tok-variableName': { 180 '&, & .tok-variableName': {
@@ -224,9 +225,9 @@ export default styled('div', {
224 fontStyle: 'normal', 225 fontStyle: 'normal',
225 }, 226 },
226 '[aria-selected]': { 227 '[aria-selected]': {
227 background: `${theme.palette.primary.main} !important`, 228 background: `${theme.palette.selection.main} !important`,
228 '.cm-completionIcon, .cm-completionLabel, .cm-completionDetail': { 229 '.cm-completionIcon, .cm-completionLabel, .cm-completionDetail': {
229 color: theme.palette.primary.contrastText, 230 color: theme.palette.selection.contrastText,
230 }, 231 },
231 }, 232 },
232 }, 233 },
@@ -237,11 +238,11 @@ export default styled('div', {
237 textAlign: 'center', 238 textAlign: 'center',
238 }, 239 },
239 ...codeMirrorLintStyle, 240 ...codeMirrorLintStyle,
240 '.cm-problem-write': {
241 background: 'rgba(255, 255, 128, 0.3)',
242 },
243 '.cm-problem-read': { 241 '.cm-problem-read': {
244 background: 'rgba(255, 255, 255, 0.15)', 242 background: theme.palette.highlight.occurences.read,
243 },
244 '.cm-problem-write': {
245 background: theme.palette.highlight.occurences.write,
245 }, 246 },
246 }; 247 };
247}); 248});
diff --git a/subprojects/frontend/src/theme/ThemeProvider.tsx b/subprojects/frontend/src/theme/ThemeProvider.tsx
index cf18e21c..1b8e49f0 100644
--- a/subprojects/frontend/src/theme/ThemeProvider.tsx
+++ b/subprojects/frontend/src/theme/ThemeProvider.tsx
@@ -5,27 +5,70 @@ import {
5 ThemeProvider as MaterialUiThemeProvider, 5 ThemeProvider as MaterialUiThemeProvider,
6} from '@mui/material/styles'; 6} from '@mui/material/styles';
7import { observer } from 'mobx-react-lite'; 7import { observer } from 'mobx-react-lite';
8import React, { type ReactNode } from 'react'; 8import React, { type CSSProperties, type ReactNode } from 'react';
9 9
10import { useRootStore } from '../RootStore'; 10import { useRootStore } from '../RootStore';
11 11
12import EditorTheme from './EditorTheme'; 12import EditorTheme from './EditorTheme';
13 13
14interface HighlightStyles {
15 number: CSSProperties['color'];
16 parameter: CSSProperties['color'];
17 occurences: {
18 read: CSSProperties['color'];
19 write: CSSProperties['color'];
20 };
21}
22
23declare module '@mui/material/styles' {
24 interface Palette {
25 selection: Palette['primary'];
26 highlight: HighlightStyles;
27 }
28
29 interface PaletteOptions {
30 selection: PaletteOptions['primary'];
31 highlight: HighlightStyles;
32 }
33}
34
14function getMUIThemeOptions(currentTheme: EditorTheme): ThemeOptions { 35function getMUIThemeOptions(currentTheme: EditorTheme): ThemeOptions {
15 switch (currentTheme) { 36 switch (currentTheme) {
16 case EditorTheme.Light: 37 case EditorTheme.Light:
17 return { 38 return {
18 palette: { 39 palette: {
19 primary: { 40 mode: 'light',
20 main: '#56b6c2', 41 primary: { main: '#0097a7' },
42 selection: {
43 main: '#c8e4fb',
44 contrastText: '#000',
45 },
46 highlight: {
47 number: '#1976d2',
48 parameter: '#6a3e3e',
49 occurences: {
50 read: '#ceccf7',
51 write: '#f0d8a8',
52 },
21 }, 53 },
22 }, 54 },
23 }; 55 };
24 case EditorTheme.Dark: 56 case EditorTheme.Dark:
25 return { 57 return {
26 palette: { 58 palette: {
27 primary: { 59 mode: 'dark',
28 main: '#56b6c2', 60 primary: { main: '#56b6c2' },
61 selection: {
62 main: '#3e4453',
63 contrastText: '#fff',
64 },
65 highlight: {
66 number: '#6188a6',
67 parameter: '#c8ae9d',
68 occurences: {
69 read: 'rgba(255, 255, 255, 0.15)',
70 write: 'rgba(255, 255, 128, 0.4)',
71 },
29 }, 72 },
30 }, 73 },
31 }; 74 };
@@ -36,19 +79,11 @@ function getMUIThemeOptions(currentTheme: EditorTheme): ThemeOptions {
36 79
37function ThemeProvider({ children }: { children?: ReactNode }) { 80function ThemeProvider({ children }: { children?: ReactNode }) {
38 const { 81 const {
39 themeStore: { currentTheme, darkMode }, 82 themeStore: { currentTheme },
40 } = useRootStore(); 83 } = useRootStore();
41 84
42 const themeOptions = getMUIThemeOptions(currentTheme); 85 const themeOptions = getMUIThemeOptions(currentTheme);
43 const theme = responsiveFontSizes( 86 const theme = responsiveFontSizes(createTheme(themeOptions));
44 createTheme({
45 ...themeOptions,
46 palette: {
47 mode: darkMode ? 'dark' : 'light',
48 ...(themeOptions.palette ?? {}),
49 },
50 }),
51 );
52 87
53 return ( 88 return (
54 <MaterialUiThemeProvider theme={theme}>{children}</MaterialUiThemeProvider> 89 <MaterialUiThemeProvider theme={theme}>{children}</MaterialUiThemeProvider>