diff options
author | Kristóf Marussy <kristof@marussy.com> | 2022-08-19 15:42:58 +0200 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2022-08-19 21:38:23 +0200 |
commit | 6c32ec1af90cf7df179a688617a828eddcff8052 (patch) | |
tree | b724173cd6ef1b622f6ae86054769ecf9fca4b81 /subprojects | |
parent | feat(frontend): responsive editor styling (diff) | |
download | refinery-6c32ec1af90cf7df179a688617a828eddcff8052.tar.gz refinery-6c32ec1af90cf7df179a688617a828eddcff8052.tar.zst refinery-6c32ec1af90cf7df179a688617a828eddcff8052.zip |
refactor(frontend): update theme
Diffstat (limited to 'subprojects')
-rw-r--r-- | subprojects/frontend/src/editor/EditorButtons.tsx | 2 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/EditorTheme.ts | 5 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/GenerateButton.tsx | 4 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/SearchToolbar.tsx | 2 | ||||
-rw-r--r-- | subprojects/frontend/src/theme/ThemeProvider.tsx | 346 |
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'; |
12 | import { observer } from 'mobx-react-lite'; | 14 | import { observer } from 'mobx-react-lite'; |
13 | import React, { type ReactNode } from 'react'; | 15 | import React, { type ReactNode, createContext, useContext } from 'react'; |
14 | 16 | ||
15 | import { useRootStore } from '../RootStore'; | 17 | import { useRootStore } from '../RootStore'; |
16 | 18 | ||
@@ -60,34 +62,44 @@ declare module '@mui/material/styles' { | |||
60 | } | 62 | } |
61 | } | 63 | } |
62 | 64 | ||
63 | function getMUIThemeOptions(darkMode: boolean): ThemeOptions { | 65 | const 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 = { | 77 | const 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 | |||
128 | function createResponsiveTheme(options: ThemeOptions): Theme { | ||
129 | return responsiveFontSizes(createTheme(options)); | ||
130 | } | ||
131 | |||
132 | const 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 | |||
179 | const 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 | 249 | const ContrastThemeContext = createContext<Theme | undefined>(undefined); |
116 | ? { | 250 | |
117 | typography, | 251 | function 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 | ||
208 | function ThemeProvider({ children }: { children?: ReactNode }) { | 269 | ThemeAndContrastThemeProvider.defaultProps = { |
270 | children: undefined, | ||
271 | }; | ||
272 | |||
273 | export 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 | |||
290 | ContrastThemeProvider.defaultProps = { | ||
291 | children: undefined, | ||
292 | }; | ||
293 | |||
294 | function 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 | ||