Add dark mode

This commit is contained in:
Peizhi Zheng 2021-01-12 15:55:56 -08:00 committed by Ken Hibino
parent 60391cdfc3
commit b15fa59cf9
6 changed files with 218 additions and 176 deletions

View File

@ -2,7 +2,7 @@ import React, { useState } from "react";
import { connect, ConnectedProps } from "react-redux";
import clsx from "clsx";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { makeStyles } from "@material-ui/core/styles";
import { makeStyles, ThemeProvider } from "@material-ui/core/styles";
import AppBar from "@material-ui/core/AppBar";
import Drawer from "@material-ui/core/Drawer";
import Toolbar from "@material-ui/core/Toolbar";
@ -26,6 +26,7 @@ import DoubleArrowIcon from "@material-ui/icons/DoubleArrow";
import CloseIcon from "@material-ui/icons/Close";
import { AppState } from "./store";
import { paths } from "./paths";
import { makeTheme } from "./theme";
import { closeSnackbar } from "./actions/snackbarActions";
import ListItemLink from "./components/ListItemLink";
import SchedulersView from "./views/SchedulersView";
@ -125,7 +126,10 @@ const useStyles = makeStyles((theme) => ({
}));
function mapStateToProps(state: AppState) {
return { snackbar: state.snackbar };
return {
snackbar: state.snackbar,
isDarkTheme: state.settings.isDarkTheme,
};
}
const mapDispatchToProps = {
@ -141,10 +145,10 @@ function SlideUpTransition(props: TransitionProps) {
function App(props: ConnectedProps<typeof connector>) {
const classes = useStyles();
const [open, setOpen] = useState(true);
const toggleDrawer = () => {
setOpen(!open);
};
const toggleDrawer = () => setOpen(!open);
const theme = makeTheme(props.isDarkTheme);
return (
<ThemeProvider theme={theme}>
<Router>
<div className={classes.root}>
<AppBar
@ -286,6 +290,7 @@ function App(props: ConnectedProps<typeof connector>) {
</div>
</div>
</Router>
</ThemeProvider>
);
}

View File

@ -1,13 +1,18 @@
// List of settings related action types.
export const POLL_INTERVAL_CHANGE = "POLL_INTERVAL_CHANGE";
export const POLL_INTERVAL_CHANGE = 'POLL_INTERVAL_CHANGE';
export const TOGGLE_DARK_THEME = 'TOGGLE_DARK_THEME';
interface PollIntervalChangeAction {
type: typeof POLL_INTERVAL_CHANGE;
value: number; // new poll interval value in seconds
}
interface ToggleDarkThemeAction {
type: typeof TOGGLE_DARK_THEME;
}
// Union of all settings related action types.
export type SettingsActionTypes = PollIntervalChangeAction;
export type SettingsActionTypes = PollIntervalChangeAction | ToggleDarkThemeAction;
export function pollIntervalChange(value: number) {
return {
@ -15,3 +20,10 @@ export function pollIntervalChange(value: number) {
value,
};
}
export function toggleDarkTheme() {
return {
type: TOGGLE_DARK_THEME
}
}

View File

@ -2,19 +2,15 @@ import React from "react";
import ReactDOM from "react-dom";
import CssBaseline from "@material-ui/core/CssBaseline";
import { Provider } from "react-redux";
import { ThemeProvider } from "@material-ui/core/styles";
import App from "./App";
import store from "./store";
import theme from "./theme";
import * as serviceWorker from "./serviceWorker";
ReactDOM.render(
<React.StrictMode>
<CssBaseline />
<Provider store={store}>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</Provider>
</React.StrictMode>,
document.getElementById("root")

View File

@ -1,23 +1,24 @@
import {
POLL_INTERVAL_CHANGE,
SettingsActionTypes,
} from "../actions/settingsActions";
import {POLL_INTERVAL_CHANGE, SettingsActionTypes, TOGGLE_DARK_THEME,} from '../actions/settingsActions';
interface SettingsState {
pollInterval: number;
isDarkTheme: boolean;
}
const initialState: SettingsState = {
pollInterval: 8,
isDarkTheme: false,
};
function settingsReducer(
state = initialState,
action: SettingsActionTypes
): SettingsState {
state = initialState, action: SettingsActionTypes): SettingsState {
switch (action.type) {
case POLL_INTERVAL_CHANGE:
return { ...state, pollInterval: action.value };
return {...state, pollInterval: action.value};
case TOGGLE_DARK_THEME:
return {
...state, isDarkTheme: !state.isDarkTheme
}
default:
return state;
}

View File

@ -1,7 +1,8 @@
import { createMuiTheme } from "@material-ui/core/styles";
import { createMuiTheme, Theme } from "@material-ui/core/styles";
// Got color palette from https://htmlcolors.com/palette/31/stripe
const theme = createMuiTheme({
export function makeTheme(isDarkTheme: boolean): Theme {
return createMuiTheme({
// Got color palette from https://htmlcolors.com/palette/31/stripe
palette: {
primary: {
main: "#4379FF",
@ -12,7 +13,7 @@ const theme = createMuiTheme({
background: {
default: "#f5f7f9",
},
type: isDarkTheme ? "dark" : "light",
},
});
export default theme;
});
}

View File

@ -5,8 +5,14 @@ import { makeStyles } from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
import Slider from "@material-ui/core/Slider/Slider";
import { pollIntervalChange } from "../actions/settingsActions";
import Switch from "@material-ui/core/Switch";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import FormGroup from "@material-ui/core/FormGroup";
import Slider from "@material-ui/core/Slider";
import {
pollIntervalChange,
toggleDarkTheme,
} from "../actions/settingsActions";
import { AppState } from "../store";
const useStyles = makeStyles((theme) => ({
@ -25,10 +31,11 @@ const useStyles = makeStyles((theme) => ({
function mapStateToProps(state: AppState) {
return {
pollInterval: state.settings.pollInterval,
isDarkTheme: state.settings.isDarkTheme,
};
}
const mapDispatchToProps = { pollIntervalChange };
const mapDispatchToProps = { pollIntervalChange, toggleDarkTheme };
const connector = connect(mapStateToProps, mapDispatchToProps);
@ -46,6 +53,9 @@ function SettingsView(props: PropsFromRedux) {
props.pollIntervalChange(val as number);
};
const handleThemeChange = (event: React.ChangeEvent<HTMLElement>) => {
props.toggleDarkTheme();
};
return (
<Container maxWidth="lg" className={classes.container}>
<Grid container spacing={3}>
@ -75,6 +85,23 @@ function SettingsView(props: PropsFromRedux) {
/>
</Paper>
</Grid>
<Grid item xs={5}>
<Paper>
<Typography color="textPrimary">theme switch</Typography>
<FormGroup row>
<FormControlLabel
control={
<Switch
checked={props.isDarkTheme}
onChange={handleThemeChange}
name="DarkTheme"
/>
}
label="🌛"
/>
</FormGroup>
</Paper>
</Grid>
</Grid>
</Container>
);