Skip to content

Commit

Permalink
app: Add basic dark/light mode support
Browse files Browse the repository at this point in the history
  • Loading branch information
evanpurkhiser committed Dec 30, 2020
1 parent c0c0b45 commit 6883e5f
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 5 deletions.
10 changes: 8 additions & 2 deletions src/main/main.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'regenerator-runtime/runtime';
import 'main/menu';

import {app, BrowserWindow, shell} from 'electron';
import {app, BrowserWindow, nativeTheme, shell} from 'electron';
import isDev from 'electron-is-dev';
import {set} from 'mobx';
import {reaction, set} from 'mobx';
import {bringOnline, NetworkState, ProlinkNetwork} from 'prolink-connect';

import * as path from 'path';
Expand Down Expand Up @@ -121,3 +121,9 @@ app.on('activate', () => {
createWindow();
}
});

reaction(
() => store.config.theme,
theme => (nativeTheme.themeSource = theme),
{fireImmediately: true}
);
16 changes: 15 additions & 1 deletion src/main/menu.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import {app, Menu, shell} from 'electron';
import {set} from 'mobx';

import store from 'src/shared/store';

const isMac = process.platform === 'darwin';

Expand Down Expand Up @@ -37,7 +40,18 @@ const template: Electron.MenuItemConstructorOptions[] = [
},
{
label: 'View',
submenu: [{role: 'reload'}, {role: 'forceReload'}, {role: 'togglefullscreen'}],
submenu: [
{role: 'reload'},
{role: 'forceReload'},
{role: 'togglefullscreen'},
{
visible: false,
accelerator: 'cmd + l',
label: 'Toggle UI Theme',
click: () =>
set(store.config, {theme: store.config.theme === 'light' ? 'dark' : 'light'}),
},
],
},
{
label: 'Window',
Expand Down
5 changes: 3 additions & 2 deletions src/renderer/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as Sentry from '@sentry/browser';
import {when} from 'mobx';

import Application from 'app/views/Application';
import ThemeProvider from 'src/shared/components/ThemeProvider';
import globalCss, {noSelect} from 'src/shared/globalCss';
import store from 'src/shared/store';
import {registerRendererConfigIpc, registerRendererIpc} from 'src/shared/store/ipc';
Expand All @@ -17,10 +18,10 @@ const mainElement = document.createElement('div');
document.body.appendChild(mainElement);

const main = (
<React.Fragment>
<ThemeProvider>
<Global styles={[globalCss, noSelect]} />
<Application />
</React.Fragment>
</ThemeProvider>
);

ReactDOM.render(main, mainElement);
Expand Down
15 changes: 15 additions & 0 deletions src/shared/components/ThemeProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {useMedia} from 'react-use';
import {ThemeProvider as EmotionThemeProvider} from '@emotion/react';

import theme from 'src/theme';

type Props = Omit<React.ComponentProps<typeof EmotionThemeProvider>, 'theme'>;

const ThemeProvider = (props: Props) => (
<EmotionThemeProvider
theme={theme[useMedia('(prefers-color-scheme: dark)') ? 'dark' : 'light']}
{...props}
/>
);

export default ThemeProvider;
6 changes: 6 additions & 0 deletions src/shared/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ export class AppConfig {
@serializable
@observable
idMarker = '[ID]';
/**
* The theme to ues in the app
*/
@serializable
@observable
theme: 'light' | 'dark' | 'system' = 'light';
}

export class AppStore {
Expand Down
51 changes: 51 additions & 0 deletions src/theme.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {mergeWith} from 'lodash';

export type ProlinkTheme = typeof light;

declare module '@emotion/react' {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface Theme extends ProlinkTheme {}
}

const colors = {
white: '#fff',
};

const light = {
background: colors.white,
backgroundSecondary: '#fafafa',
border: '#eee',

control: {
border: '#ccc',
borderFocus: '#aaa',
placeholderText: '#737386',
},

primaryText: '#28272b',
subText: '#888',

button: {
primary: {
backgroundHover: '#000',
background: '#28272b',
color: colors.white,
},
muted: {
backgroundHover: '#e5e5e5',
background: '#eee',
color: 'inherit',
},
},
};

const dark = mergeWith(
{
background: '#28272b',
primaryText: '#fff',
},
light,
(value, srcValue) => (value !== undefined ? value : srcValue)
);

export default {light, dark};

0 comments on commit 6883e5f

Please sign in to comment.