aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--subprojects/frontend/index.html10
-rw-r--r--subprojects/frontend/src/Loading.tsx7
-rw-r--r--subprojects/frontend/src/editor/EditorPane.tsx23
-rw-r--r--subprojects/frontend/src/editor/EditorTheme.ts13
-rw-r--r--subprojects/frontend/src/editor/SearchToolbar.tsx32
-rw-r--r--subprojects/frontend/src/theme/ThemeProvider.tsx65
-rw-r--r--subprojects/frontend/vite.config.ts2
7 files changed, 105 insertions, 47 deletions
diff --git a/subprojects/frontend/index.html b/subprojects/frontend/index.html
index a3e52ef9..f9e87485 100644
--- a/subprojects/frontend/index.html
+++ b/subprojects/frontend/index.html
@@ -10,7 +10,7 @@
10 <link rel="icon" href="/favicon-96x96.png" type="image/png" sizes="96x96"> 10 <link rel="icon" href="/favicon-96x96.png" type="image/png" sizes="96x96">
11 <link rel="apple-touch-icon" href="/apple-touch-icon.png" type="image/png" sizes="180x180"> 11 <link rel="apple-touch-icon" href="/apple-touch-icon.png" type="image/png" sizes="180x180">
12 <link rel="mask-icon" href="/mask-icon.svg" type="image/svg+xml" color="#038a99"> 12 <link rel="mask-icon" href="/mask-icon.svg" type="image/svg+xml" color="#038a99">
13 <meta name="theme-color" media="(prefers-color-scheme:light)" content="#fafafa"> 13 <meta name="theme-color" media="(prefers-color-scheme:light)" content="#f5f5f5">
14 <meta name="theme-color" media="(prefers-color-scheme:dark)" content="#21252b"> 14 <meta name="theme-color" media="(prefers-color-scheme:dark)" content="#21252b">
15 <style> 15 <style>
16 @import '@fontsource/jetbrains-mono/variable.css'; 16 @import '@fontsource/jetbrains-mono/variable.css';
@@ -270,15 +270,15 @@
270 } 270 }
271 271
272 body { 272 body {
273 color: #35373e; 273 color: #19202b;
274 background: #ffffff; 274 background: #f5f5f5;
275 font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif; 275 font-family: 'InterVariable', 'Inter', 'Roboto', 'Helvetica', 'Arial', sans-serif;
276 } 276 }
277 277
278 @media (prefers-color-scheme: dark) { 278 @media (prefers-color-scheme: dark) {
279 body { 279 body {
280 color: #ebebff; 280 color: #ebebff;
281 background: #282c34; 281 background: #21252b;
282 } 282 }
283 } 283 }
284 </style> 284 </style>
diff --git a/subprojects/frontend/src/Loading.tsx b/subprojects/frontend/src/Loading.tsx
index 72020a43..8c293239 100644
--- a/subprojects/frontend/src/Loading.tsx
+++ b/subprojects/frontend/src/Loading.tsx
@@ -2,18 +2,19 @@ import CircularProgress from '@mui/material/CircularProgress';
2import { styled } from '@mui/material/styles'; 2import { styled } from '@mui/material/styles';
3import React from 'react'; 3import React from 'react';
4 4
5const LoadingRoot = styled('div')({ 5const LoadingRoot = styled('div')(({ theme }) => ({
6 width: '100%', 6 width: '100%',
7 height: '100%', 7 height: '100%',
8 display: 'flex', 8 display: 'flex',
9 alignItems: 'center', 9 alignItems: 'center',
10 justifyContent: 'center', 10 justifyContent: 'center',
11}); 11 background: theme.palette.outer.background,
12}));
12 13
13export default function Loading() { 14export default function Loading() {
14 return ( 15 return (
15 <LoadingRoot> 16 <LoadingRoot>
16 <CircularProgress /> 17 <CircularProgress size={60} color="inherit" />
17 </LoadingRoot> 18 </LoadingRoot>
18 ); 19 );
19} 20}
diff --git a/subprojects/frontend/src/editor/EditorPane.tsx b/subprojects/frontend/src/editor/EditorPane.tsx
index 935a84e8..df43d2c9 100644
--- a/subprojects/frontend/src/editor/EditorPane.tsx
+++ b/subprojects/frontend/src/editor/EditorPane.tsx
@@ -1,10 +1,10 @@
1import Box from '@mui/material/Box'; 1import Box from '@mui/material/Box';
2import Skeleton from '@mui/material/Skeleton';
2import Stack from '@mui/material/Stack'; 3import Stack from '@mui/material/Stack';
3import Toolbar from '@mui/material/Toolbar'; 4import Toolbar from '@mui/material/Toolbar';
4import { observer } from 'mobx-react-lite'; 5import { observer } from 'mobx-react-lite';
5import React from 'react'; 6import React, { useState } from 'react';
6 7
7import Loading from '../Loading';
8import { useRootStore } from '../RootStore'; 8import { useRootStore } from '../RootStore';
9 9
10import EditorArea from './EditorArea'; 10import EditorArea from './EditorArea';
@@ -12,6 +12,23 @@ import EditorButtons from './EditorButtons';
12import GenerateButton from './GenerateButton'; 12import GenerateButton from './GenerateButton';
13import SearchPanelPortal from './SearchPanelPortal'; 13import SearchPanelPortal from './SearchPanelPortal';
14 14
15function EditorLoading(): JSX.Element {
16 const [skeletonSizes] = useState(() =>
17 new Array(10).fill(0).map(() => Math.random() * 60 + 10),
18 );
19
20 return (
21 <Box mx={2}>
22 {skeletonSizes.map((length, i) => (
23 /* eslint-disable-next-line react/no-array-index-key --
24 Random placeholders have no identity.
25 */
26 <Skeleton key={i} width={`${length}%`} />
27 ))}
28 </Box>
29 );
30}
31
15function EditorPane(): JSX.Element { 32function EditorPane(): JSX.Element {
16 const { editorStore } = useRootStore(); 33 const { editorStore } = useRootStore();
17 34
@@ -23,7 +40,7 @@ function EditorPane(): JSX.Element {
23 </Toolbar> 40 </Toolbar>
24 <Box flexGrow={1} flexShrink={1} overflow="auto"> 41 <Box flexGrow={1} flexShrink={1} overflow="auto">
25 {editorStore === undefined ? ( 42 {editorStore === undefined ? (
26 <Loading /> 43 <EditorLoading />
27 ) : ( 44 ) : (
28 <> 45 <>
29 <SearchPanelPortal editorStore={editorStore} /> 46 <SearchPanelPortal editorStore={editorStore} />
diff --git a/subprojects/frontend/src/editor/EditorTheme.ts b/subprojects/frontend/src/editor/EditorTheme.ts
index ca07d602..dfeeb547 100644
--- a/subprojects/frontend/src/editor/EditorTheme.ts
+++ b/subprojects/frontend/src/editor/EditorTheme.ts
@@ -14,8 +14,10 @@ export default styled('div', {
14})<{ showLineNumbers: boolean }>(({ theme, showLineNumbers }) => { 14})<{ showLineNumbers: boolean }>(({ theme, showLineNumbers }) => {
15 const editorFontStyle = { 15 const editorFontStyle = {
16 ...theme.typography.editor, 16 ...theme.typography.editor,
17 fontWeight: theme.typography.fontWeightEditorNormal,
17 [theme.breakpoints.down('sm')]: { 18 [theme.breakpoints.down('sm')]: {
18 fontSize: '0.875rem', 19 // `rem` for JetBrains MonoVariable make the text too large in Safari.
20 fontSize: '14px',
19 lineHeight: 1.43, 21 lineHeight: 1.43,
20 }, 22 },
21 }; 23 };
@@ -29,7 +31,12 @@ export default styled('div', {
29 color: theme.palette.text.secondary, 31 color: theme.palette.text.secondary,
30 }, 32 },
31 '.cm-gutters': { 33 '.cm-gutters': {
32 background: theme.palette.background.default, 34 background: `linear-gradient(
35 to right,
36 ${theme.palette.background.default} 0%,
37 ${theme.palette.background.default} calc(100% - 12px),
38 transparent 100%
39 )`,
33 border: 'none', 40 border: 'none',
34 }, 41 },
35 '.cm-content': { 42 '.cm-content': {
@@ -93,7 +100,7 @@ export default styled('div', {
93 fontStyle: 'italic', 100 fontStyle: 'italic',
94 }, 101 },
95 '.tok-problem-containment': { 102 '.tok-problem-containment': {
96 fontWeight: theme.typography.fontWeightBold, 103 fontWeight: theme.typography.fontWeightEditorBold,
97 textDecorationSkipInk: 'none', 104 textDecorationSkipInk: 'none',
98 }, 105 },
99 '.tok-problem-error': { 106 '.tok-problem-error': {
diff --git a/subprojects/frontend/src/editor/SearchToolbar.tsx b/subprojects/frontend/src/editor/SearchToolbar.tsx
index 7e6ff4f7..895f1ca1 100644
--- a/subprojects/frontend/src/editor/SearchToolbar.tsx
+++ b/subprojects/frontend/src/editor/SearchToolbar.tsx
@@ -11,6 +11,7 @@ import Stack from '@mui/material/Stack';
11import TextField from '@mui/material/TextField'; 11import TextField from '@mui/material/TextField';
12import ToggleButton from '@mui/material/ToggleButton'; 12import ToggleButton from '@mui/material/ToggleButton';
13import Toolbar from '@mui/material/Toolbar'; 13import Toolbar from '@mui/material/Toolbar';
14import { styled } from '@mui/material/styles';
14import useMediaQuery from '@mui/material/useMediaQuery'; 15import useMediaQuery from '@mui/material/useMediaQuery';
15import { observer } from 'mobx-react-lite'; 16import { observer } from 'mobx-react-lite';
16import React, { useCallback, useState } from 'react'; 17import React, { useCallback, useState } from 'react';
@@ -18,7 +19,13 @@ import React, { useCallback, useState } from 'react';
18import type SearchPanelStore from './SearchPanelStore'; 19import type SearchPanelStore from './SearchPanelStore';
19 20
20const SPLIT_MEDIA_QUERY = '@media (max-width: 1200px)'; 21const SPLIT_MEDIA_QUERY = '@media (max-width: 1200px)';
21const ABBREVIATE_MEDIA_QUERY = '@media (max-width: 720px)'; 22
23const DimLabel = styled(FormControlLabel)(({ theme }) => ({
24 '.MuiFormControlLabel-label': {
25 ...theme.typography.body2,
26 color: theme.palette.text.secondary,
27 },
28}));
22 29
23function SearchToolbar({ 30function SearchToolbar({
24 searchPanelStore, 31 searchPanelStore,
@@ -31,7 +38,6 @@ function SearchToolbar({
31 invalidRegexp, 38 invalidRegexp,
32 } = searchPanelStore; 39 } = searchPanelStore;
33 const split = useMediaQuery(SPLIT_MEDIA_QUERY); 40 const split = useMediaQuery(SPLIT_MEDIA_QUERY);
34 const abbreviate = useMediaQuery(ABBREVIATE_MEDIA_QUERY);
35 const [showRepalceState, setShowReplaceState] = useState(false); 41 const [showRepalceState, setShowReplaceState] = useState(false);
36 42
37 const showReplace = !split || showRepalceState || replace !== ''; 43 const showReplace = !split || showRepalceState || replace !== '';
@@ -132,7 +138,7 @@ function SearchToolbar({
132 alignItems="center" 138 alignItems="center"
133 rowGap={0.5} 139 rowGap={0.5}
134 > 140 >
135 <FormControlLabel 141 <DimLabel
136 control={ 142 control={
137 <Checkbox 143 <Checkbox
138 checked={caseSensitive} 144 checked={caseSensitive}
@@ -144,10 +150,9 @@ function SearchToolbar({
144 size="small" 150 size="small"
145 /> 151 />
146 } 152 }
147 aria-label="Match case" 153 label="Match case"
148 label={abbreviate ? 'Case' : 'Match case'}
149 /> 154 />
150 <FormControlLabel 155 <DimLabel
151 control={ 156 control={
152 <Checkbox 157 <Checkbox
153 checked={literal} 158 checked={literal}
@@ -159,10 +164,9 @@ function SearchToolbar({
159 size="small" 164 size="small"
160 /> 165 />
161 } 166 }
162 aria-label="Literal" 167 label="Literal"
163 label={abbreviate ? 'Lit' : 'Literal'}
164 /> 168 />
165 <FormControlLabel 169 <DimLabel
166 control={ 170 control={
167 <Checkbox 171 <Checkbox
168 checked={regexp} 172 checked={regexp}
@@ -248,7 +252,15 @@ function SearchToolbar({
248 </Stack> 252 </Stack>
249 </Stack> 253 </Stack>
250 </Stack> 254 </Stack>
251 <Stack direction="row" alignSelf="stretch" alignItems="start" mt="1px"> 255 <Stack
256 direction="row"
257 alignSelf="stretch"
258 alignItems="start"
259 mt="1px"
260 sx={{
261 [SPLIT_MEDIA_QUERY]: { display: 'none' },
262 }}
263 >
252 <IconButton 264 <IconButton
253 aria-label="Close find/replace" 265 aria-label="Close find/replace"
254 onClick={() => searchPanelStore.close()} 266 onClick={() => searchPanelStore.close()}
diff --git a/subprojects/frontend/src/theme/ThemeProvider.tsx b/subprojects/frontend/src/theme/ThemeProvider.tsx
index 3a0703fe..0c780e85 100644
--- a/subprojects/frontend/src/theme/ThemeProvider.tsx
+++ b/subprojects/frontend/src/theme/ThemeProvider.tsx
@@ -43,11 +43,15 @@ interface HighlightPalette {
43 43
44declare module '@mui/material/styles' { 44declare module '@mui/material/styles' {
45 interface TypographyVariants { 45 interface TypographyVariants {
46 fontWeightEditorNormal: number;
47 fontWeightEditorBold: number;
46 editor: TypographyStyle; 48 editor: TypographyStyle;
47 } 49 }
48 50
49 // eslint-disable-next-line @typescript-eslint/no-shadow -- Augment imported interface. 51 // eslint-disable-next-line @typescript-eslint/no-shadow -- Augment imported interface.
50 interface TypographyVariantsOptions { 52 interface TypographyVariantsOptions {
53 fontWeightEditorNormal: number;
54 fontWeightEditorBold: number;
51 editor: TypographyStyle; 55 editor: TypographyStyle;
52 } 56 }
53 57
@@ -63,11 +67,14 @@ declare module '@mui/material/styles' {
63} 67}
64 68
65const typography: TypographyVariantsOptions = { 69const typography: TypographyVariantsOptions = {
70 fontWeightEditorNormal: 400,
71 fontWeightEditorBold: 600,
66 editor: { 72 editor: {
67 fontFamily: 73 fontFamily:
68 '"JetBrains MonoVariable", "JetBrains Mono", "Cascadia Code", "Fira Code", monospace', 74 '"JetBrains MonoVariable", "JetBrains Mono", "Cascadia Code", "Fira Code", monospace',
69 fontFeatureSettings: '"liga", "calt"', 75 fontFeatureSettings: '"liga", "calt"',
70 fontSize: '1rem', 76 // `rem` for JetBrains MonoVariable make the text too large in Safari.
77 fontSize: '16px',
71 fontWeight: 400, 78 fontWeight: 400,
72 lineHeight: 1.5, 79 lineHeight: 1.5,
73 letterSpacing: 0, 80 letterSpacing: 0,
@@ -78,10 +85,20 @@ const typography: TypographyVariantsOptions = {
78const components: Components = { 85const components: Components = {
79 MuiButton: { 86 MuiButton: {
80 styleOverrides: { 87 styleOverrides: {
81 root: { '&.rounded': { borderRadius: '50em' } }, 88 root: {
82 text: { '&.rounded': { padding: '6px 16px' } }, 89 '&.rounded': { borderRadius: '50em' },
83 textSizeSmall: { '&.rounded': { padding: '4px 10px' } }, 90 '.MuiButton-startIcon': { marginRight: 6 },
84 textSizeLarge: { '&.rounded': { padding: '8px 22px' } }, 91 '.MuiButton-endIcon': { marginLeft: 6 },
92 },
93 text: { '&.rounded': { padding: '6px 14px' } },
94 textSizeSmall: {
95 fontSize: '0.875rem',
96 '&.rounded': { padding: '4px 8px' },
97 },
98 textSizeLarge: {
99 fontSize: '1rem',
100 '&.rounded': { padding: '8px 20px' },
101 },
85 }, 102 },
86 }, 103 },
87 MuiToggleButton: { 104 MuiToggleButton: {
@@ -142,31 +159,31 @@ const lightTheme = createResponsiveTheme({
142 success: { main: '#50a14f' }, 159 success: { main: '#50a14f' },
143 info: { main: '#4078f2' }, 160 info: { main: '#4078f2' },
144 background: { 161 background: {
145 default: '#ffffff', 162 default: '#fff',
146 paper: '#ffffff', 163 paper: '#fff',
147 }, 164 },
148 text: { 165 text: {
149 primary: '#35373e', 166 primary: '#19202b',
150 secondary: '#696c77', 167 secondary: '#696c77',
151 disabled: '#8e8f97', 168 disabled: '#a0a1a7',
152 }, 169 },
153 divider: alpha('#35373e', 0.21), 170 divider: alpha('#19202b', 0.16),
154 outer: { 171 outer: {
155 background: '#fafafa', 172 background: '#f5f5f5',
156 border: '#d4d4d6', 173 border: '#d6d7d9',
157 }, 174 },
158 highlight: { 175 highlight: {
159 number: '#0084bc', 176 number: '#0084bc',
160 parameter: '#6a3e3e', 177 parameter: '#6a3e3e',
161 comment: '#8e8f97', 178 comment: '#a0a1a7',
162 activeLine: '#fafafa', 179 activeLine: '#f5f5f5',
163 selection: '#c8e4fb', 180 selection: '#c8e4fb',
164 lineNumber: '#8e8f97', 181 lineNumber: '#a0a1a7',
165 foldPlaceholder: alpha('#35373e', 0.08), 182 foldPlaceholder: alpha('#19202b', 0.08),
166 activeLintRange: alpha('#f2a60d', 0.28), 183 activeLintRange: alpha('#f2a60d', 0.28),
167 occurences: { 184 occurences: {
168 read: alpha('#35373e', 0.16), 185 read: alpha('#19202b', 0.16),
169 write: alpha('#35373e', 0.16), 186 write: alpha('#19202b', 0.16),
170 }, 187 },
171 search: { 188 search: {
172 match: '#00bcd4', 189 match: '#00bcd4',
@@ -178,7 +195,11 @@ const lightTheme = createResponsiveTheme({
178}); 195});
179 196
180const darkTheme = createResponsiveTheme({ 197const darkTheme = createResponsiveTheme({
181 typography, 198 typography: {
199 ...typography,
200 fontWeightEditorNormal: 350,
201 fontWeightEditorBold: 550,
202 },
182 components: { 203 components: {
183 ...components, 204 ...components,
184 MuiSnackbarContent: { 205 MuiSnackbarContent: {
@@ -218,7 +239,7 @@ const darkTheme = createResponsiveTheme({
218 text: { 239 text: {
219 primary: '#ebebff', 240 primary: '#ebebff',
220 secondary: '#abb2bf', 241 secondary: '#abb2bf',
221 disabled: '#828997', 242 disabled: '#5c6370',
222 }, 243 },
223 divider: alpha('#abb2bf', 0.24), 244 divider: alpha('#abb2bf', 0.24),
224 outer: { 245 outer: {
@@ -228,10 +249,10 @@ const darkTheme = createResponsiveTheme({
228 highlight: { 249 highlight: {
229 number: '#6188a6', 250 number: '#6188a6',
230 parameter: '#c8ae9d', 251 parameter: '#c8ae9d',
231 comment: '#828997', 252 comment: '#5c6370',
232 activeLine: '#21252b', 253 activeLine: '#21252b',
233 selection: '#3e4453', 254 selection: '#3e4453',
234 lineNumber: '#828997', 255 lineNumber: '#5c6370',
235 foldPlaceholder: alpha('#ebebff', 0.12), 256 foldPlaceholder: alpha('#ebebff', 0.12),
236 activeLintRange: alpha('#fbc346', 0.28), 257 activeLintRange: alpha('#fbc346', 0.28),
237 occurences: { 258 occurences: {
diff --git a/subprojects/frontend/vite.config.ts b/subprojects/frontend/vite.config.ts
index f2e0f15c..0c13f133 100644
--- a/subprojects/frontend/vite.config.ts
+++ b/subprojects/frontend/vite.config.ts
@@ -110,7 +110,7 @@ export default defineConfig({
110 short_name: 'Refinery', 110 short_name: 'Refinery',
111 description: 111 description:
112 'An efficient graph sovler for generating well-formed models', 112 'An efficient graph sovler for generating well-formed models',
113 theme_color: '#21252b', 113 theme_color: '#f5f5f5',
114 display_override: ['window-controls-overlay'], 114 display_override: ['window-controls-overlay'],
115 display: 'standalone', 115 display: 'standalone',
116 background_color: '#21252b', 116 background_color: '#21252b',