Skip to content

Commit 8d16b45

Browse files
jprochazkshepmaster
authored andcommitted
Allow configuring theme
1 parent 14ea535 commit 8d16b45

File tree

11 files changed

+173
-38
lines changed

11 files changed

+173
-38
lines changed

ui/frontend/.stylelintrc.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
"ignoreProperties": [
1313
"composes"
1414
]
15+
}],
16+
"at-rule-no-unknown": [true, {
17+
"ignoreAtRules": ["define-mixin", "mixin"]
1518
}]
1619
}
1720
}

ui/frontend/ConfigMenu.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
Orientation,
1515
PairCharacters,
1616
ProcessAssembly,
17+
Theme,
1718
} from './types';
1819

1920
const MONACO_THEMES = [
@@ -24,6 +25,7 @@ const ConfigMenu: React.FC = () => {
2425
const keybinding = useAppSelector((state) => state.configuration.ace.keybinding);
2526
const aceTheme = useAppSelector((state) => state.configuration.ace.theme);
2627
const monacoTheme = useAppSelector((state) => state.configuration.monaco.theme);
28+
const theme = useAppSelector((state) => state.configuration.theme);
2729
const orientation = useAppSelector((state) => state.configuration.orientation);
2830
const editorStyle = useAppSelector((state) => state.configuration.editor);
2931
const pairCharacters = useAppSelector((state) => state.configuration.ace.pairCharacters);
@@ -35,6 +37,7 @@ const ConfigMenu: React.FC = () => {
3537
const changeAceTheme = useCallback((t: string) => dispatch(config.changeAceTheme(t)), [dispatch]);
3638
const changeMonacoTheme = useCallback((t: string) => dispatch(config.changeMonacoTheme(t)), [dispatch]);
3739
const changeKeybinding = useCallback((k: string) => dispatch(config.changeKeybinding(k)), [dispatch]);
40+
const changeTheme = useCallback((t: Theme) => dispatch(config.changeTheme(t)), [dispatch]);
3841
const changeOrientation = useCallback((o: Orientation) => dispatch(config.changeOrientation(o)), [dispatch]);
3942
const changeEditorStyle = useCallback((e: Editor) => dispatch(config.changeEditor(e)), [dispatch]);
4043
const changeAssemblyFlavor =
@@ -98,6 +101,11 @@ const ConfigMenu: React.FC = () => {
98101
</MenuGroup>
99102

100103
<MenuGroup title="UI">
104+
<SelectConfig name="Theme" value={theme} onChange={changeTheme}>
105+
<option value={Theme.System}>System</option>
106+
<option value={Theme.Light}>Light</option>
107+
<option value={Theme.Dark}>Dark</option>
108+
</SelectConfig>
101109
<SelectConfig
102110
name="Orientation"
103111
value={orientation}

ui/frontend/index.module.css

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@
1111
--border: 1px solid var(--border-color);
1212
}
1313

14-
/* Light theme */
15-
/* stylelint-disable-next-line no-duplicate-selectors */
16-
:root {
14+
@define-mixin light-theme-vars {
1715
--positive-luminance: white;
1816
--negative-luminance: black;
1917

@@ -107,50 +105,62 @@
107105
--output-current-tab: #f9ffff;
108106
}
109107

110-
/* Automatic dark mode */
111-
@media (prefers-color-scheme: dark) {
112-
:root {
113-
--positive-luminance: black;
114-
--negative-luminance: white;
108+
@define-mixin dark-theme-vars {
109+
--positive-luminance: black;
110+
--negative-luminance: white;
115111

116-
/* Fonts */
117-
--font-color: #b4aea6;
118-
--font-color-high-contrast: #dcdbd8;
112+
/* Fonts */
113+
--font-color: #b4aea6;
114+
--font-color-high-contrast: #dcdbd8;
119115

120-
/* Links */
121-
--link-color: #308af2;
122-
--link-color-visited: #9f5fe1;
116+
/* Links */
117+
--link-color: #308af2;
118+
--link-color-visited: #9f5fe1;
123119

124-
/* Background */
125-
--background-color: #292c2e;
126-
--background-color-high-contrast: #17191a;
120+
/* Background */
121+
--background-color: #292c2e;
122+
--background-color-high-contrast: #17191a;
127123

128-
/* Code */
129-
--code-background-color: #3c3c3c;
124+
/* Code */
125+
--code-background-color: #3c3c3c;
130126

131-
/* Border */
132-
--border-color: #404548;
127+
/* Border */
128+
--border-color: #404548;
133129

134-
/* Header */
135-
--header-main-border: #363b3d;
136-
--header-accent-border: #bdbdbd;
130+
/* Header */
131+
--header-main-border: #363b3d;
132+
--header-accent-border: #bdbdbd;
137133

138-
/* The big red button */
139-
--button-primary-color: #dcdbd8;
140-
--button-primary-bg-color: #81331a;
141-
--button-primary-border-color: #612714;
134+
/* The big red button */
135+
--button-primary-color: #dcdbd8;
136+
--button-primary-bg-color: #81331a;
137+
--button-primary-border-color: #612714;
142138

143-
/* Not the big red button */
144-
--button-secondary-color: #b4aea6;
145-
--button-secondary-bg-color-top: #17191a;
146-
--button-secondary-bg-color-bottom: #1a1c1d;
139+
/* Not the big red button */
140+
--button-secondary-color: #b4aea6;
141+
--button-secondary-bg-color-top: #17191a;
142+
--button-secondary-bg-color-bottom: #1a1c1d;
143+
144+
/* Output tabs */
145+
--output-background-tab: #191b1c;
146+
--output-current-tab: #343434;
147+
}
148+
149+
:root,
150+
[data-theme='light']:root {
151+
@mixin light-theme-vars;
152+
}
147153

148-
/* Output tabs */
149-
--output-background-tab: #191b1c;
150-
--output-current-tab: #343434;
154+
@media (prefers-color-scheme: dark) {
155+
:root {
156+
@mixin dark-theme-vars;
151157
}
152158
}
153159

160+
[data-theme='dark']:root {
161+
@mixin dark-theme-vars;
162+
}
163+
154164
/* Modify normalized styles */
155165
button,
156166
input,

ui/frontend/index.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import { gotoPosition } from './reducers/position';
2525
import { addImport, editCode, enableFeatureGate } from './reducers/code';
2626
import { browserWidthChanged } from './reducers/browser';
2727
import { selectText } from './reducers/selection';
28+
import { useAppSelector } from './hooks';
29+
import { themeSelector } from './selectors';
30+
import { Theme } from './types';
2831

2932
const store = configureStore(window);
3033

@@ -82,13 +85,28 @@ window.rustPlayground = {
8285
},
8386
};
8487

88+
const ThemeProvider: React.FC<React.PropsWithChildren> = ({ children }) => {
89+
const theme = useAppSelector(themeSelector);
90+
React.useEffect(() => {
91+
if (theme === Theme.System) {
92+
delete document.documentElement.dataset['theme'];
93+
} else {
94+
document.documentElement.dataset['theme'] = theme;
95+
}
96+
}, [theme]);
97+
98+
return <>{children}</>;
99+
};
100+
85101
const container = document.getElementById('playground');
86102
if (container) {
87103
const root = createRoot(container);
88104
root.render(
89105
<Provider store={store}>
90106
<Router store={store} reducer={playgroundApp}>
91-
<PageSwitcher />
107+
<ThemeProvider>
108+
<PageSwitcher />
109+
</ThemeProvider>
92110
</Router>
93111
</Provider>,
94112
);

ui/frontend/local_storage.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import { State } from './reducers';
66
import {removeVersion, initializeStorage, PartialState} from './storage';
7-
import { AssemblyFlavor, DemangleAssembly, Editor, Orientation, PairCharacters, ProcessAssembly } from './types';
7+
import { AssemblyFlavor, DemangleAssembly, Editor, Orientation, PairCharacters, ProcessAssembly, Theme } from './types';
88
import { codeSelector } from './selectors';
99

1010
const CURRENT_VERSION = 2;
@@ -25,6 +25,7 @@ interface V2Configuration {
2525
monaco: {
2626
theme: string;
2727
};
28+
theme: Theme;
2829
orientation: Orientation;
2930
assemblyFlavor: AssemblyFlavor;
3031
demangleAssembly: DemangleAssembly;
@@ -70,6 +71,7 @@ export function serialize(state: State): string {
7071
monaco: {
7172
theme: state.configuration.monaco.theme,
7273
},
74+
theme: state.configuration.theme,
7375
orientation: state.configuration.orientation,
7476
assemblyFlavor: state.configuration.assemblyFlavor,
7577
demangleAssembly: state.configuration.demangleAssembly,
@@ -93,6 +95,7 @@ function migrateV1(state: V1Configuration): CurrentConfiguration {
9395
...configuration,
9496
ace: { theme, keybinding, pairCharacters },
9597
monaco: { theme: 'vscode-dark-plus' },
98+
theme: Theme.System,
9699
editor: editor === 'advanced' ? Editor.Ace : Editor.Simple,
97100
},
98101
version: 2,

ui/frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"immer": "^10.0.3",
1414
"lodash-es": "^4.17.21",
1515
"monaco-editor": "^0.50.0",
16+
"postcss-mixins": "^11.0.1",
1617
"prismjs": "^1.6.0",
1718
"qs": "^6.4.0",
1819
"react": "^18.2.0",

0 commit comments

Comments
 (0)