codies/frontend/src/index.tsx

73 lines
2.5 KiB
TypeScript

import 'typeface-roboto';
import { createMuiTheme, CssBaseline, IconButton, responsiveFontSizes, ThemeProvider } from '@material-ui/core';
import { Brightness4, Brightness7 } from '@material-ui/icons';
import { useLocalStorage } from '@rehooks/local-storage';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { App } from './app';
import { AboutButton } from './components/about';
function useTheme() {
const [themeName, setThemeName] = useLocalStorage<'light' | 'dark'>('themeName', 'dark');
// Workaround for https://github.com/mui-org/material-ui/issues/20708.
//
// When in strict mode (development only), this is required to properly allow
// the theme to be changed, as unused styles are not cleaned up. Create a new theme
// each time, so that they're forced to be injected again at the end of the existing
// block of stylesheets (as the styling library will see them as "new" styles, rather than
// assuming they can just be reused).
//
// This is gross, as it means every time the button is clicked it's a slew of extra
// stylesheets (each overriding the previous), but in production the cleanup works
// so this extra work is "only" a performance hit. If the bug is ever fixed, we can
// simply store two global themes and swap between them.
const theme = responsiveFontSizes(
createMuiTheme({
palette: {
type: themeName,
},
})
);
const toggleTheme = () => {
if (themeName === 'light') {
setThemeName('dark');
} else {
setThemeName('light');
}
};
return { theme, toggleTheme, isDark: themeName === 'dark' };
}
const Root = (_props: {}) => {
const { theme, toggleTheme, isDark } = useTheme();
return (
<React.StrictMode>
<ThemeProvider theme={theme}>
<CssBaseline />
<div
style={{
position: 'absolute',
top: 0,
right: 0,
margin: '0.5rem',
}}
>
<AboutButton style={{ marginRight: '0.5rem' }} />
<IconButton size="small" onClick={toggleTheme}>
{isDark ? <Brightness7 /> : <Brightness4 />}
</IconButton>
</div>
<App />
</ThemeProvider>
</React.StrictMode>
);
};
ReactDOM.render(<Root />, document.getElementById('root'));