aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--subprojects/frontend/src/editor/EditorButtons.tsx2
-rw-r--r--subprojects/frontend/src/editor/EditorTheme.ts5
-rw-r--r--subprojects/frontend/src/editor/GenerateButton.tsx4
-rw-r--r--subprojects/frontend/src/editor/SearchToolbar.tsx2
-rw-r--r--subprojects/frontend/src/theme/ThemeProvider.tsx346
5 files changed, 225 insertions, 134 deletions
diff --git a/subprojects/frontend/src/editor/EditorButtons.tsx b/subprojects/frontend/src/editor/EditorButtons.tsx
index bed6afa8..735531e8 100644
--- a/subprojects/frontend/src/editor/EditorButtons.tsx
+++ b/subprojects/frontend/src/editor/EditorButtons.tsx
@@ -53,7 +53,7 @@ function EditorButtons(): JSX.Element {
53 > 53 >
54 <RedoIcon fontSize="small" /> 54 <RedoIcon fontSize="small" />
55 </IconButton> 55 </IconButton>
56 <ToggleButtonGroup size="small" sx={{ mx: 1 }}> 56 <ToggleButtonGroup size="small" className="rounded" sx={{ mx: 1 }}>
57 <ToggleButton 57 <ToggleButton
58 selected={editorStore.showLineNumbers} 58 selected={editorStore.showLineNumbers}
59 onClick={() => editorStore.toggleLineNumbers()} 59 onClick={() => editorStore.toggleLineNumbers()}
diff --git a/subprojects/frontend/src/editor/EditorTheme.ts b/subprojects/frontend/src/editor/EditorTheme.ts
index fe5ba58e..d8680070 100644
--- a/subprojects/frontend/src/editor/EditorTheme.ts
+++ b/subprojects/frontend/src/editor/EditorTheme.ts
@@ -95,7 +95,8 @@ export default styled('div', {
95 fontStyle: 'italic', 95 fontStyle: 'italic',
96 }, 96 },
97 '.tok-problem-containment': { 97 '.tok-problem-containment': {
98 fontWeight: 700, 98 fontWeight: theme.typography.fontWeightBold,
99 textDecorationSkipInk: 'none',
99 }, 100 },
100 '.tok-problem-error': { 101 '.tok-problem-error': {
101 '&, & .tok-typeName': { 102 '&, & .tok-typeName': {
@@ -278,7 +279,7 @@ export default styled('div', {
278 '&[aria-selected="true"]': { 279 '&[aria-selected="true"]': {
279 color: theme.palette.text.primary, 280 color: theme.palette.text.primary,
280 background: 'transparent', 281 background: 'transparent',
281 fontWeight: 700, 282 fontWeight: theme.typography.fontWeightMedium,
282 }, 283 },
283 ':hover': { 284 ':hover': {
284 background: alpha( 285 background: alpha(
diff --git a/subprojects/frontend/src/editor/GenerateButton.tsx b/subprojects/frontend/src/editor/GenerateButton.tsx
index 14258723..4b998af6 100644
--- a/subprojects/frontend/src/editor/GenerateButton.tsx
+++ b/subprojects/frontend/src/editor/GenerateButton.tsx
@@ -24,8 +24,9 @@ function GenerateButton(): JSX.Element {
24 return ( 24 return (
25 <Button 25 <Button
26 aria-label={`Select next diagnostic out of ${summary}`} 26 aria-label={`Select next diagnostic out of ${summary}`}
27 color="error"
28 onClick={() => editorStore.nextDiagnostic()} 27 onClick={() => editorStore.nextDiagnostic()}
28 color="error"
29 className="rounded"
29 > 30 >
30 {summary} 31 {summary}
31 </Button> 32 </Button>
@@ -35,6 +36,7 @@ function GenerateButton(): JSX.Element {
35 return ( 36 return (
36 <Button 37 <Button
37 color={warningCount > 0 ? 'warning' : 'primary'} 38 color={warningCount > 0 ? 'warning' : 'primary'}
39 className="rounded"
38 startIcon={<PlayArrowIcon />} 40 startIcon={<PlayArrowIcon />}
39 > 41 >
40 {summary === '' ? GENERATE_LABEL : `${GENERATE_LABEL} (${summary})`} 42 {summary === '' ? GENERATE_LABEL : `${GENERATE_LABEL} (${summary})`}
diff --git a/subprojects/frontend/src/editor/SearchToolbar.tsx b/subprojects/frontend/src/editor/SearchToolbar.tsx
index a5925328..45f1336d 100644
--- a/subprojects/frontend/src/editor/SearchToolbar.tsx
+++ b/subprojects/frontend/src/editor/SearchToolbar.tsx
@@ -181,7 +181,7 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
181 aria-label="Show replace options" 181 aria-label="Show replace options"
182 aria-controls={replaceId} 182 aria-controls={replaceId}
183 size="small" 183 size="small"
184 sx={{ borderRadius: '100%' }} 184 className="iconOnly"
185 > 185 >
186 <FindReplaceIcon fontSize="small" /> 186 <FindReplaceIcon fontSize="small" />
187 </ToggleButton> 187 </ToggleButton>
diff --git a/subprojects/frontend/src/theme/ThemeProvider.tsx b/subprojects/frontend/src/theme/ThemeProvider.tsx
index 82b8dfa9..5bc14704 100644
--- a/subprojects/frontend/src/theme/ThemeProvider.tsx
+++ b/subprojects/frontend/src/theme/ThemeProvider.tsx
@@ -4,13 +4,15 @@ import {
4 type Components, 4 type Components,
5 type CSSObject, 5 type CSSObject,
6 responsiveFontSizes, 6 responsiveFontSizes,
7 type Theme,
7 type ThemeOptions, 8 type ThemeOptions,
8 ThemeProvider as MaterialUiThemeProvider, 9 ThemeProvider as MaterialUiThemeProvider,
9 type TypographyStyle, 10 type TypographyStyle,
10 type TypographyVariantsOptions, 11 type TypographyVariantsOptions,
12 useTheme,
11} from '@mui/material/styles'; 13} from '@mui/material/styles';
12import { observer } from 'mobx-react-lite'; 14import { observer } from 'mobx-react-lite';
13import React, { type ReactNode } from 'react'; 15import React, { type ReactNode, createContext, useContext } from 'react';
14 16
15import { useRootStore } from '../RootStore'; 17import { useRootStore } from '../RootStore';
16 18
@@ -60,34 +62,44 @@ declare module '@mui/material/styles' {
60 } 62 }
61} 63}
62 64
63function getMUIThemeOptions(darkMode: boolean): ThemeOptions { 65const typography: TypographyVariantsOptions = {
64 const typography: TypographyVariantsOptions = { 66 editor: {
65 editor: { 67 fontFamily: '"JetBrains MonoVariable", "JetBrains Mono", monospace',
66 fontFamily: '"JetBrains MonoVariable", "JetBrains Mono", monospace', 68 fontFeatureSettings: '"liga", "calt"',
67 fontFeatureSettings: '"liga", "calt"', 69 fontSize: '1rem',
68 fontSize: '1rem', 70 fontWeight: 400,
69 fontWeight: 400, 71 lineHeight: 1.5,
70 lineHeight: 1.5, 72 letterSpacing: 0,
71 letterSpacing: 0, 73 textRendering: 'optimizeLegibility',
72 textRendering: 'optimizeLegibility', 74 },
73 }, 75};
74 };
75 76
76 const components: Components = { 77const components: Components = {
77 MuiButton: { 78 MuiButton: {
78 styleOverrides: { 79 styleOverrides: {
79 root: { borderRadius: '50em' }, 80 root: { '&.rounded': { borderRadius: '50em' } },
80 text: { padding: '6px 16px' }, 81 text: { '&.rounded': { padding: '6px 16px' } },
81 textSizeSmall: { padding: '4px 10px' }, 82 textSizeSmall: { '&.rounded': { padding: '4px 10px' } },
82 textSizeLarge: { padding: '8px 22px' }, 83 textSizeLarge: { '&.rounded': { padding: '8px 22px' } },
83 },
84 }, 84 },
85 MuiToggleButtonGroup: { 85 },
86 styleOverrides: { 86 MuiToggleButton: {
87 groupedHorizontal: { 87 styleOverrides: {
88 borderRadius: '50em', 88 root: { '&.iconOnly': { borderRadius: '100%' } },
89 ':first-of-type': { paddingLeft: 15 }, 89 },
90 ':last-of-type': { paddingRight: 15 }, 90 },
91 MuiToggleButtonGroup: {
92 styleOverrides: {
93 root: {
94 '&.rounded .MuiToggleButtonGroup-groupedHorizontal': {
95 ':first-of-type': {
96 paddingLeft: 15,
97 borderRadius: '50em 0 0 50em',
98 },
99 ':last-of-type': {
100 paddingRight: 15,
101 borderRadius: '0 50em 50em 0',
102 },
91 '&.MuiToggleButton-sizeSmall': { 103 '&.MuiToggleButton-sizeSmall': {
92 ':first-of-type': { paddingLeft: 9 }, 104 ':first-of-type': { paddingLeft: 9 },
93 ':last-of-type': { paddingRight: 9 }, 105 ':last-of-type': { paddingRight: 9 },
@@ -99,122 +111,198 @@ function getMUIThemeOptions(darkMode: boolean): ThemeOptions {
99 }, 111 },
100 }, 112 },
101 }, 113 },
114 },
115 MuiTooltip: {
116 styleOverrides: {
117 tooltip: {
118 background: alpha('#212121', 0.93),
119 color: '#fff',
120 },
121 arrow: {
122 color: alpha('#212121', 0.93),
123 },
124 },
125 },
126};
127
128function createResponsiveTheme(options: ThemeOptions): Theme {
129 return responsiveFontSizes(createTheme(options));
130}
131
132const lightTheme = createResponsiveTheme({
133 typography,
134 components,
135 palette: {
136 mode: 'light',
137 primary: { main: '#038a99' },
138 secondary: { main: '#e45649' },
139 error: { main: '#ca1243' },
140 warning: { main: '#c18401' },
141 success: { main: '#50a14f' },
142 info: { main: '#4078f2' },
143 background: {
144 default: '#ffffff',
145 paper: '#ffffff',
146 },
147 text: {
148 primary: '#35373e',
149 secondary: '#696c77',
150 disabled: '#8e8f97',
151 },
152 divider: alpha('#35373e', 0.21),
153 outer: {
154 background: '#fafafa',
155 border: '#d4d4d6',
156 },
157 highlight: {
158 number: '#0084bc',
159 parameter: '#6a3e3e',
160 comment: '#8e8f97',
161 activeLine: '#fafafa',
162 selection: '#c8e4fb',
163 lineNumber: '#8e8f97',
164 foldPlaceholder: alpha('#35373e', 0.08),
165 activeLintRange: alpha('#f2a60d', 0.28),
166 occurences: {
167 read: alpha('#35373e', 0.16),
168 write: alpha('#35373e', 0.16),
169 },
170 search: {
171 match: '#00bcd4',
172 selected: '#d500f9',
173 contrastText: '#ffffff',
174 },
175 },
176 },
177});
178
179const darkTheme = createResponsiveTheme({
180 typography,
181 components: {
182 ...components,
183 MuiSnackbarContent: {
184 styleOverrides: {
185 root: {
186 color: '#f00',
187 backgroundColor: '#000',
188 border: `10px solid #ff0`,
189 },
190 },
191 },
102 MuiTooltip: { 192 MuiTooltip: {
193 ...(components.MuiTooltip || {}),
103 styleOverrides: { 194 styleOverrides: {
195 ...(components.MuiTooltip?.styleOverrides || {}),
104 tooltip: { 196 tooltip: {
105 background: alpha('#212121', 0.93), 197 ...((components.MuiTooltip?.styleOverrides?.tooltip as
106 color: '#fff', 198 | CSSObject
107 }, 199 | undefined) || {}),
108 arrow: { 200 color: '#ebebff',
109 color: alpha('#212121', 0.93),
110 }, 201 },
111 }, 202 },
112 }, 203 },
113 }; 204 },
205 palette: {
206 mode: 'dark',
207 primary: { main: '#56b6c2' },
208 secondary: { main: '#be5046' },
209 error: { main: '#e06c75' },
210 warning: { main: '#e5c07b' },
211 success: { main: '#98c379' },
212 info: { main: '#61afef' },
213 background: {
214 default: '#282c34',
215 paper: '#21252b',
216 },
217 text: {
218 primary: '#ebebff',
219 secondary: '#abb2bf',
220 disabled: '#828997',
221 },
222 divider: alpha('#abb2bf', 0.24),
223 outer: {
224 background: '#21252b',
225 border: '#181a1f',
226 },
227 highlight: {
228 number: '#6188a6',
229 parameter: '#c8ae9d',
230 comment: '#828997',
231 activeLine: '#21252b',
232 selection: '#3e4453',
233 lineNumber: '#828997',
234 foldPlaceholder: alpha('#ebebff', 0.12),
235 activeLintRange: alpha('#fbc346', 0.28),
236 occurences: {
237 read: alpha('#ebebff', 0.24),
238 write: alpha('#ebebff', 0.24),
239 },
240 search: {
241 match: '#33eaff',
242 selected: '#dd33fa',
243 contrastText: '#21252b',
244 },
245 },
246 },
247});
114 248
115 return darkMode 249const ContrastThemeContext = createContext<Theme | undefined>(undefined);
116 ? { 250
117 typography, 251function ThemeAndContrastThemeProvider({
118 components: { 252 theme,
119 ...components, 253 contrastTheme,
120 MuiTooltip: { 254 children,
121 ...(components.MuiTooltip || {}), 255}: {
122 styleOverrides: { 256 theme: Theme;
123 ...(components.MuiTooltip?.styleOverrides || {}), 257 contrastTheme: Theme;
124 tooltip: { 258 children?: ReactNode;
125 ...((components.MuiTooltip?.styleOverrides?.tooltip as 259}): JSX.Element {
126 | CSSObject 260 return (
127 | undefined) || {}), 261 <MaterialUiThemeProvider theme={theme}>
128 color: '#ebebff', 262 <ContrastThemeContext.Provider value={contrastTheme}>
129 }, 263 {children}
130 }, 264 </ContrastThemeContext.Provider>
131 }, 265 </MaterialUiThemeProvider>
132 }, 266 );
133 palette: {
134 mode: 'dark',
135 primary: { main: '#56b6c2' },
136 error: { main: '#e06c75' },
137 warning: { main: '#e5c07b' },
138 success: { main: '#57a470' },
139 info: { main: '#52b8ff' },
140 background: {
141 default: '#282c34',
142 paper: '#21252b',
143 },
144 text: {
145 primary: '#ebebff',
146 secondary: '#abb2bf',
147 disabled: '#4b5263',
148 },
149 divider: alpha('#abb2bf', 0.16),
150 outer: {
151 background: '#21252b',
152 border: '#181a1f',
153 },
154 highlight: {
155 number: '#6188a6',
156 parameter: '#c8ae9d',
157 comment: '#6b717d',
158 activeLine: '#21252b',
159 selection: '#3e4453',
160 lineNumber: '#4b5263',
161 foldPlaceholder: alpha('#ebebff', 0.12),
162 activeLintRange: alpha('#fbc346', 0.28),
163 occurences: {
164 read: alpha('#ebebff', 0.24),
165 write: alpha('#ebebff', 0.24),
166 },
167 search: {
168 match: '#33eaff',
169 selected: '#dd33fa',
170 contrastText: '#21252b',
171 },
172 },
173 },
174 }
175 : {
176 typography,
177 components,
178 palette: {
179 mode: 'light',
180 primary: { main: '#0398a8' },
181 outer: {
182 background: '#f5f5f5',
183 border: '#cacaca',
184 },
185 highlight: {
186 number: '#3d79a2',
187 parameter: '#6a3e3e',
188 comment: 'rgba(0, 0, 0, 0.38)',
189 activeLine: '#f5f5f5',
190 selection: '#c8e4fb',
191 lineNumber: 'rgba(0, 0, 0, 0.38)',
192 foldPlaceholder: 'rgba(0, 0, 0, 0.12)',
193 activeLintRange: alpha('#ed6c02', 0.24),
194 occurences: {
195 read: 'rgba(0, 0, 0, 0.12)',
196 write: 'rgba(0, 0, 0, 0.12)',
197 },
198 search: {
199 match: '#00bcd4',
200 selected: '#d500f9',
201 contrastText: '#ffffff',
202 },
203 },
204 },
205 };
206} 267}
207 268
208function ThemeProvider({ children }: { children?: ReactNode }) { 269ThemeAndContrastThemeProvider.defaultProps = {
270 children: undefined,
271};
272
273export function ContrastThemeProvider({
274 children,
275}: {
276 children?: ReactNode;
277}): JSX.Element {
278 const theme = useTheme();
279 const contrastTheme = useContext(ContrastThemeContext);
280 if (!contrastTheme) {
281 throw new Error('ContrastThemeProvider must be used within ThemeProvider');
282 }
283 return (
284 <ThemeAndContrastThemeProvider theme={contrastTheme} contrastTheme={theme}>
285 {children}
286 </ThemeAndContrastThemeProvider>
287 );
288}
289
290ContrastThemeProvider.defaultProps = {
291 children: undefined,
292};
293
294function ThemeProvider({ children }: { children?: ReactNode }): JSX.Element {
209 const { 295 const {
210 themeStore: { darkMode }, 296 themeStore: { darkMode },
211 } = useRootStore(); 297 } = useRootStore();
212 298
213 const themeOptions = getMUIThemeOptions(darkMode);
214 const theme = responsiveFontSizes(createTheme(themeOptions));
215
216 return ( 299 return (
217 <MaterialUiThemeProvider theme={theme}>{children}</MaterialUiThemeProvider> 300 <ThemeAndContrastThemeProvider
301 theme={darkMode ? darkTheme : lightTheme}
302 contrastTheme={darkMode ? lightTheme : darkTheme}
303 >
304 {children}
305 </ThemeAndContrastThemeProvider>
218 ); 306 );
219} 307}
220 308