aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend/src/editor/EditorTheme.ts
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-08-17 21:43:29 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-08-17 21:43:29 +0200
commitbb900e1bd40a6b7efd7a538114d985ea7f7e3e88 (patch)
treebb15a937ade92313dc654a640bc1de925442eff2 /subprojects/frontend/src/editor/EditorTheme.ts
parentrefactor(frondend): improve editor store and theme (diff)
downloadrefinery-bb900e1bd40a6b7efd7a538114d985ea7f7e3e88.tar.gz
refinery-bb900e1bd40a6b7efd7a538114d985ea7f7e3e88.tar.zst
refinery-bb900e1bd40a6b7efd7a538114d985ea7f7e3e88.zip
feat(frontend): custom search panel
Also improves editor styling (to enable panel styling).
Diffstat (limited to 'subprojects/frontend/src/editor/EditorTheme.ts')
-rw-r--r--subprojects/frontend/src/editor/EditorTheme.ts433
1 files changed, 238 insertions, 195 deletions
diff --git a/subprojects/frontend/src/editor/EditorTheme.ts b/subprojects/frontend/src/editor/EditorTheme.ts
index 8d98e832..c983a378 100644
--- a/subprojects/frontend/src/editor/EditorTheme.ts
+++ b/subprojects/frontend/src/editor/EditorTheme.ts
@@ -2,7 +2,7 @@ import errorSVG from '@material-icons/svg/svg/error/baseline.svg?raw';
2import expandMoreSVG from '@material-icons/svg/svg/expand_more/baseline.svg?raw'; 2import expandMoreSVG from '@material-icons/svg/svg/expand_more/baseline.svg?raw';
3import infoSVG from '@material-icons/svg/svg/info/baseline.svg?raw'; 3import infoSVG from '@material-icons/svg/svg/info/baseline.svg?raw';
4import warningSVG from '@material-icons/svg/svg/warning/baseline.svg?raw'; 4import warningSVG from '@material-icons/svg/svg/warning/baseline.svg?raw';
5import { alpha, styled } from '@mui/material/styles'; 5import { alpha, styled, type CSSObject } from '@mui/material/styles';
6 6
7import editorClassNames from './editorClassNames'; 7import editorClassNames from './editorClassNames';
8 8
@@ -14,36 +14,178 @@ export default styled('div', {
14 name: 'EditorTheme', 14 name: 'EditorTheme',
15 shouldForwardProp: (propName) => propName !== 'showLineNumbers', 15 shouldForwardProp: (propName) => propName !== 'showLineNumbers',
16})<{ showLineNumbers: boolean }>(({ theme, showLineNumbers }) => { 16})<{ showLineNumbers: boolean }>(({ theme, showLineNumbers }) => {
17 let codeMirrorLintStyle: Record<string, unknown> = {}; 17 const generalStyle: CSSObject = {
18 ( 18 background: theme.palette.background.default,
19 [ 19 '&, .cm-editor': {
20 { 20 height: '100%',
21 severity: 'error', 21 },
22 icon: errorSVG, 22 '.cm-scroller': {
23 ...theme.typography.editor,
24 color: theme.palette.text.secondary,
25 },
26 '.cm-gutters': {
27 background: 'transparent',
28 border: 'none',
29 },
30 '.cm-content': {
31 padding: 0,
32 },
33 '.cm-activeLine': {
34 background: theme.palette.highlight.activeLine,
35 },
36 '.cm-activeLineGutter': {
37 background: 'transparent',
38 },
39 '.cm-cursor, .cm-cursor-primary': {
40 borderLeft: `2px solid ${theme.palette.primary.main}`,
41 },
42 '.cm-selectionBackground': {
43 background: theme.palette.highlight.selection,
44 },
45 '.cm-focused': {
46 outline: 'none',
47 '.cm-selectionBackground': {
48 background: theme.palette.highlight.selection,
49 },
50 },
51 };
52
53 const highlightingStyle: CSSObject = {
54 '.cm-specialChar': {
55 color: theme.palette.secondary.main,
56 },
57 '.tok-comment': {
58 fontStyle: 'italic',
59 color: theme.palette.highlight.comment,
60 },
61 '.tok-number': {
62 color: theme.palette.highlight.number,
63 },
64 '.tok-string': {
65 color: theme.palette.secondary,
66 },
67 '.tok-keyword': {
68 color: theme.palette.primary.main,
69 },
70 '.tok-typeName, .tok-atom': {
71 color: theme.palette.text.primary,
72 },
73 '.tok-variableName': {
74 color: theme.palette.highlight.parameter,
75 },
76 '.tok-problem-node': {
77 '&, & .tok-variableName': {
78 color: theme.palette.text.secondary,
79 },
80 },
81 '.tok-problem-individual': {
82 '&, & .tok-variableName': {
83 color: theme.palette.text.primary,
23 }, 84 },
24 { 85 },
25 severity: 'warning', 86 '.tok-problem-abstract, .tok-problem-new': {
26 icon: warningSVG, 87 fontStyle: 'italic',
88 },
89 '.tok-problem-containment': {
90 fontWeight: 700,
91 },
92 '.tok-problem-error': {
93 '&, & .tok-typeName': {
94 color: theme.palette.error.main,
27 }, 95 },
28 { 96 },
29 severity: 'info', 97 '.tok-problem-builtin': {
30 icon: infoSVG, 98 '&, & .tok-typeName, & .tok-atom, & .tok-variableName': {
99 color: theme.palette.primary.main,
100 fontWeight: 400,
101 fontStyle: 'normal',
31 }, 102 },
32 ] as const 103 },
33 ).forEach(({ severity, icon }) => { 104 };
105
106 const matchingStyle: CSSObject = {
107 '.cm-problem-read': {
108 background: theme.palette.highlight.occurences.read,
109 },
110 '.cm-problem-write': {
111 background: theme.palette.highlight.occurences.write,
112 },
113 '.cm-matchingBracket, .cm-nonmatchingBracket': {
114 background: 'transparent',
115 },
116 '.cm-focused .cm-matchingBracket': {
117 background: 'transparent',
118 outline: `1px solid ${alpha(theme.palette.text.primary, 0.5)}`,
119 outlineOffset: -1,
120 },
121 '.cm-focused .cm-nonmatchingBracket': {
122 background: theme.palette.error.main,
123 '&, span': {
124 color: theme.palette.error.contrastText,
125 },
126 },
127 '.cm-searchMatch': {
128 opacity: 1,
129 background: theme.palette.highlight.search.match,
130 '&, span': {
131 color: theme.palette.highlight.search.contrastText,
132 },
133 },
134 '.cm-searchMatch-selected': {
135 background: theme.palette.highlight.search.selected,
136 },
137 };
138
139 const lineNumberStyle: CSSObject = {
140 '.cm-lineNumbers': {
141 color: theme.palette.highlight.lineNumber,
142 ...(!showLineNumbers && {
143 display: 'none !important',
144 }),
145 '.cm-gutterElement': {
146 padding: '0 2px 0 6px',
147 },
148 '.cm-activeLineGutter': {
149 color: theme.palette.text.primary,
150 },
151 },
152 };
153
154 const panelStyle: CSSObject = {
155 '.cm-panels-top': {
156 color: theme.palette.text.primary,
157 borderBottom: `1px solid ${theme.palette.outer.border}`,
158 marginBottom: theme.spacing(1),
159 },
160 '.cm-panel, .cm-panel.cm-search': {
161 color: theme.palette.text.primary,
162 background: theme.palette.outer.background,
163 borderTop: `1px solid ${theme.palette.outer.border}`,
164 margin: 0,
165 padding: 0,
166 'button[name="close"]': {
167 background: 'transparent',
168 color: theme.palette.text.secondary,
169 cursor: 'pointer',
170 },
171 },
172 };
173
174 function lintSeverityStyle(
175 severity: 'error' | 'warning' | 'info',
176 icon: string,
177 ): CSSObject {
34 const palette = theme.palette[severity]; 178 const palette = theme.palette[severity];
35 const color = palette.main; 179 const color = palette.main;
36 const iconStyle = { 180 const tooltipColor = theme.palette.mode === 'dark' ? color : palette.light;
181 const iconStyle: CSSObject = {
37 background: color, 182 background: color,
38 maskImage: svgURL(icon), 183 maskImage: svgURL(icon),
39 maskSize: '16px 16px', 184 maskSize: '16px 16px',
40 height: 16, 185 height: 16,
41 width: 16, 186 width: 16,
42 }; 187 };
43 const tooltipColor = 188 return {
44 theme.palette.mode === 'dark' ? palette.main : palette.light;
45 codeMirrorLintStyle = {
46 ...codeMirrorLintStyle,
47 [`.cm-lintRange-${severity}`]: { 189 [`.cm-lintRange-${severity}`]: {
48 backgroundImage: 'none', 190 backgroundImage: 'none',
49 textDecoration: `underline wavy ${color}`, 191 textDecoration: `underline wavy ${color}`,
@@ -78,113 +220,23 @@ export default styled('div', {
78 }, 220 },
79 }, 221 },
80 }; 222 };
81 }); 223 }
82 224
83 return { 225 const lintStyle: CSSObject = {
84 background: theme.palette.background.default,
85 '&, .cm-editor': {
86 height: '100%',
87 },
88 '.cm-content': {
89 padding: 0,
90 },
91 '.cm-scroller': {
92 color: theme.palette.text.secondary,
93 },
94 '.cm-scroller, .cm-tooltip-autocomplete, .cm-completionLabel, .cm-completionDetail':
95 {
96 ...theme.typography.body1,
97 fontFamily: '"JetBrains MonoVariable", "JetBrains Mono", monospace',
98 fontFeatureSettings: '"liga", "calt"',
99 letterSpacing: 0,
100 textRendering: 'optimizeLegibility',
101 },
102 '.cm-gutters': {
103 background: 'transparent',
104 color: theme.palette.text.disabled,
105 border: 'none',
106 },
107 '.cm-specialChar': {
108 color: theme.palette.secondary.main,
109 },
110 '.cm-activeLine': {
111 background: theme.palette.highlight.activeLine,
112 },
113 '.cm-gutter-lint': { 226 '.cm-gutter-lint': {
114 width: 16, 227 width: 16,
115 '.cm-gutterElement': { 228 '.cm-gutterElement': {
116 padding: 0, 229 padding: 0,
117 }, 230 },
118 }, 231 },
119 '.cm-foldGutter': { 232 '.cm-tooltip.cm-tooltip-hover, .cm-tooltip.cm-tooltip-lint': {
120 opacity: 0, 233 ...((theme.components?.MuiTooltip?.styleOverrides?.tooltip as
121 width: 16, 234 | CSSObject
122 transition: theme.transitions.create('opacity', { 235 | undefined) || {}),
123 duration: theme.transitions.duration.short, 236 ...theme.typography.body2,
124 }), 237 borderRadius: theme.shape.borderRadius,
125 '@media (hover: none)': {
126 opacity: 1,
127 },
128 },
129 '.cm-gutters:hover .cm-foldGutter': {
130 opacity: 1,
131 },
132 [`.${editorClassNames.foldMarker}`]: {
133 display: 'block',
134 margin: '4px 0',
135 padding: 0,
136 maskImage: svgURL(expandMoreSVG),
137 maskSize: '16px 16px',
138 height: 16,
139 width: 16,
140 background: theme.palette.text.primary,
141 border: 'none',
142 cursor: 'pointer',
143 },
144 [`.${editorClassNames.foldMarkerClosed}`]: {
145 transform: 'rotate(-90deg)',
146 },
147 '.cm-activeLineGutter': {
148 background: 'transparent',
149 },
150 '.cm-lineNumbers': {
151 ...(!showLineNumbers && {
152 display: 'none !important',
153 }),
154 '.cm-activeLineGutter': {
155 color: theme.palette.text.primary,
156 },
157 },
158 '.cm-cursor, .cm-cursor-primary': {
159 borderLeft: `2px solid ${theme.palette.primary.main}`,
160 },
161 '.cm-selectionBackground': {
162 background: theme.palette.highlight.selection,
163 },
164 '.cm-focused': {
165 outline: 'none',
166 '.cm-selectionBackground': {
167 background: theme.palette.highlight.selection,
168 },
169 },
170 '.cm-panels-top': {
171 color: theme.palette.text.secondary,
172 borderBottom: `1px solid ${theme.palette.outer.border}`,
173 marginBottom: theme.spacing(1),
174 },
175 '.cm-panel': {
176 position: 'relative',
177 overflow: 'hidden', 238 overflow: 'hidden',
178 background: theme.palette.outer.background, 239 maxWidth: 400,
179 borderTop: `1px solid ${theme.palette.outer.border}`,
180 '&, & button, & input': {
181 fontFamily: theme.typography.fontFamily,
182 },
183 'button[name="close"]': {
184 background: 'transparent',
185 color: theme.palette.text.secondary,
186 cursor: 'pointer',
187 },
188 }, 240 },
189 '.cm-panel.cm-panel-lint': { 241 '.cm-panel.cm-panel-lint': {
190 borderTop: `1px solid ${theme.palette.outer.border}`, 242 borderTop: `1px solid ${theme.palette.outer.border}`,
@@ -195,7 +247,7 @@ export default styled('div', {
195 display: 'none', 247 display: 'none',
196 }, 248 },
197 ul: { 249 ul: {
198 maxHeight: 'max(112px, 20vh)', 250 maxHeight: `max(${28 * 4}px, 20vh)`,
199 li: { 251 li: {
200 cursor: 'pointer', 252 cursor: 'pointer',
201 color: theme.palette.text.primary, 253 color: theme.palette.text.primary,
@@ -216,77 +268,71 @@ export default styled('div', {
216 }, 268 },
217 }, 269 },
218 }, 270 },
219 [`.${editorClassNames.foldPlaceholder}`]: { 271 '.cm-lintRange-active': {
220 ...theme.typography.body1, 272 background: theme.palette.highlight.activeLintRange,
221 padding: 0, 273 },
222 fontFamily: 'inherit', 274 ...lintSeverityStyle('error', errorSVG),
223 fontFeatureSettings: '"liga", "calt"', 275 ...lintSeverityStyle('warning', warningSVG),
224 color: theme.palette.text.secondary, 276 ...lintSeverityStyle('info', infoSVG),
225 backgroundColor: alpha( 277 };
226 theme.palette.text.secondary, 278
227 theme.palette.action.focusOpacity, 279 const foldStyle = {
228 ), 280 '.cm-foldGutter': {
229 border: 'none', 281 opacity: 0,
230 cursor: 'pointer', 282 width: 16,
231 transition: theme.transitions.create(['background-color', 'color'], { 283 transition: theme.transitions.create('opacity', {
232 duration: theme.transitions.duration.short, 284 duration: theme.transitions.duration.short,
233 }), 285 }),
234 '&:hover': { 286 '@media (hover: none)': {
235 color: theme.palette.text.primary, 287 opacity: 1,
236 backgroundColor: alpha(
237 theme.palette.text.secondary,
238 theme.palette.action.focusOpacity + theme.palette.action.hoverOpacity,
239 ),
240 }, 288 },
241 }, 289 },
242 '.tok-comment': { 290 '.cm-gutters:hover .cm-foldGutter': {
243 fontStyle: 'italic', 291 opacity: 1,
244 color: theme.palette.highlight.comment,
245 },
246 '.tok-number': {
247 color: theme.palette.highlight.number,
248 },
249 '.tok-string': {
250 color: theme.palette.secondary,
251 },
252 '.tok-keyword': {
253 color: theme.palette.primary.main,
254 }, 292 },
255 '.tok-typeName, .tok-atom': { 293 [`.${editorClassNames.foldMarker}`]: {
256 color: theme.palette.text.primary, 294 display: 'block',
295 margin: '4px 0',
296 padding: 0,
297 maskImage: svgURL(expandMoreSVG),
298 maskSize: '16px 16px',
299 height: 16,
300 width: 16,
301 background: theme.palette.text.primary,
302 border: 'none',
303 cursor: 'pointer',
257 }, 304 },
258 '.tok-variableName': { 305 [`.${editorClassNames.foldMarkerClosed}`]: {
259 color: theme.palette.highlight.parameter, 306 transform: 'rotate(-90deg)',
260 }, 307 },
261 '.tok-problem-node': { 308 [`.${editorClassNames.foldPlaceholder}`]: {
262 '&, & .tok-variableName': { 309 ...theme.typography.editor,
310 padding: 0,
311 fontFamily: 'inherit',
312 background: 'transparent',
313 border: 'none',
314 cursor: 'pointer',
315 // Use an inner `span` element to match the height of other text highlights.
316 span: {
263 color: theme.palette.text.secondary, 317 color: theme.palette.text.secondary,
318 backgroundColor: 'transparent',
319 backgroundImage: `linear-gradient(${theme.palette.highlight.foldPlaceholder}, ${theme.palette.highlight.foldPlaceholder})`,
320 transition: theme.transitions.create('background-color', {
321 duration: theme.transitions.duration.short,
322 }),
264 }, 323 },
265 }, 324 '&:hover span': {
266 '.tok-problem-individual': { 325 backgroundColor: alpha(
267 '&, & .tok-variableName': { 326 theme.palette.highlight.foldPlaceholder,
268 color: theme.palette.text.primary, 327 theme.palette.action.hoverOpacity,
269 }, 328 ),
270 },
271 '.tok-problem-abstract, .tok-problem-new': {
272 fontStyle: 'italic',
273 },
274 '.tok-problem-containment': {
275 fontWeight: 700,
276 },
277 '.tok-problem-error': {
278 '&, & .tok-typeName': {
279 color: theme.palette.error.main,
280 },
281 },
282 '.tok-problem-builtin': {
283 '&, & .tok-typeName, & .tok-atom, & .tok-variableName': {
284 color: theme.palette.primary.main,
285 fontWeight: 400,
286 fontStyle: 'normal',
287 }, 329 },
288 }, 330 },
331 };
332
333 const completionStyle: CSSObject = {
289 '.cm-tooltip.cm-tooltip-autocomplete': { 334 '.cm-tooltip.cm-tooltip-autocomplete': {
335 ...theme.typography.editor,
290 background: theme.palette.background.paper, 336 background: theme.palette.background.paper,
291 borderRadius: theme.shape.borderRadius, 337 borderRadius: theme.shape.borderRadius,
292 overflow: 'hidden', 338 overflow: 'hidden',
@@ -300,9 +346,11 @@ export default styled('div', {
300 color: theme.palette.text.secondary, 346 color: theme.palette.text.secondary,
301 }, 347 },
302 '.cm-completionLabel': { 348 '.cm-completionLabel': {
349 ...theme.typography.editor,
303 color: theme.palette.text.primary, 350 color: theme.palette.text.primary,
304 }, 351 },
305 '.cm-completionDetail': { 352 '.cm-completionDetail': {
353 ...theme.typography.editor,
306 color: theme.palette.text.secondary, 354 color: theme.palette.text.secondary,
307 fontStyle: 'normal', 355 fontStyle: 'normal',
308 }, 356 },
@@ -316,27 +364,22 @@ export default styled('div', {
316 }, 364 },
317 }, 365 },
318 }, 366 },
319 '.cm-tooltip.cm-tooltip-hover, .cm-tooltip.cm-tooltip-lint': {
320 ...theme.typography.body2,
321 // https://github.com/mui/material-ui/blob/dee9529f7a298c54ae760761112c3ae9ba082137/packages/mui-material/src/Tooltip/Tooltip.js#L121-L125
322 background: alpha(theme.palette.grey[700], 0.92),
323 borderRadius: theme.shape.borderRadius,
324 color: theme.palette.common.white,
325 overflow: 'hidden',
326 maxWidth: 400,
327 },
328 '.cm-completionIcon': { 367 '.cm-completionIcon': {
329 width: 16, 368 width: 16,
330 padding: 0, 369 padding: 0,
331 marginRight: '0.5em', 370 marginRight: '0.5em',
332 textAlign: 'center', 371 textAlign: 'center',
333 }, 372 },
334 ...codeMirrorLintStyle, 373 };
335 '.cm-problem-read': { 374
336 background: theme.palette.highlight.occurences.read, 375 return {
337 }, 376 ...generalStyle,
338 '.cm-problem-write': { 377 ...highlightingStyle,
339 background: theme.palette.highlight.occurences.write, 378 ...matchingStyle,
340 }, 379 ...lineNumberStyle,
380 ...panelStyle,
381 ...lintStyle,
382 ...foldStyle,
383 ...completionStyle,
341 }; 384 };
342}); 385});