浏览代码

Create ColorModeContext and implement dark/light theme toggle

implement-dark-light-theme-toggle
mladen.dubovac 4 年前
父节点
当前提交
dbad104155

+ 72
- 0
src/components/MUI/Examples/Modals.js 查看文件

@@ -0,0 +1,72 @@
import React, { useState } from 'react';
import { Box, Button, Divider, Paper, Typography } from '@mui/material';
import DialogComponent from '../DialogComponent';
import DrawerComponent from '../DrawerComponent';
import PopoverComponent from '../PopoverComponent';

const Modals = () => {
const [dialogOpen, setDialogOpen] = useState(false);
const [drawerOpen, setDrawerOpen] = useState(false);
const [popoverOpen, setPopoverOpen] = useState(false);
const [anchorEl, setAnchorEl] = useState(null);

return (
<Box
sx={{
mt: 4,
ml: 4,
display: 'flex',
flexGrow: 1,
}}
>
<Paper
sx={{
p: 4,
display: 'flex',
flexDirection: 'column',
}}
>
<Typography variant="h4" gutterBottom align="center">
Modals
</Typography>
<Divider />
<Button onClick={() => setDialogOpen(true)}>Open Dialog</Button>
<Button onClick={() => setDrawerOpen(true)}>Open Drawer</Button>
<Button
onClick={(e) => {
setPopoverOpen(true);
setAnchorEl(e.currentTarget);
}}
>
Open Popover
</Button>
</Paper>
<DialogComponent
title="Dialog Title"
content={<Typography>Dialog Content</Typography>}
open={dialogOpen}
onClose={() => setDialogOpen(false)}
maxWidth="md"
fullWidth
responsive
/>
<DrawerComponent
anchor="left"
content={<Typography sx={{ p: 2 }}>Drawer Content</Typography>}
open={drawerOpen}
toggleOpen={() => setDrawerOpen(!drawerOpen)}
/>
<PopoverComponent
anchorEl={anchorEl}
open={popoverOpen}
onClose={() => {
setPopoverOpen(false);
setAnchorEl(null);
}}
content={<Typography sx={{ p: 2 }}>Popover Content</Typography>}
/>
</Box>
);
};

export default Modals;

+ 49
- 23
src/components/MUI/Navbar.js 查看文件

@@ -1,4 +1,4 @@
import React, { useState, useMemo } from 'react';
import React, { useState, useMemo, useContext } from 'react';
import {
AppBar,
Badge,
@@ -16,35 +16,52 @@ import {
import { useTheme } from '@mui/system';
import MenuOutlinedIcon from '@mui/icons-material/MenuOutlined';
import ShoppingBasketIcon from '@mui/icons-material/ShoppingBasket';
import Brightness4Icon from '@mui/icons-material/Brightness4';
import Brightness7Icon from '@mui/icons-material/Brightness7';
import MenuList from './MenuList';
import Drawer from './DrawerComponent';
import { ColorModeContext } from '../../context/ColorModeContext';

const Navbar = () => {
const [openDrawer, setOpenDrawer] = useState(false);
const theme = useTheme();
const matches = useMediaQuery(theme.breakpoints.down('sm'));
const toggleColorMode = useContext(ColorModeContext);

const handleToggleDrawer = () => {
setOpenDrawer(!openDrawer);
};

const drawerContent = useMemo(() => (
<List>
<ListItemButton divider onClick={handleToggleDrawer}>
<ListItemIcon>
<ListItemText>Link 1</ListItemText>
</ListItemIcon>
</ListItemButton>
<ListItem divider onClick={handleToggleDrawer}>
<ListItemIcon>
<ListItemText>Link 2</ListItemText>
</ListItemIcon>
</ListItem>
<ListItem divider onClick={handleToggleDrawer}>
<ListItemText>Link 3</ListItemText>
</ListItem>
</List>
), [handleToggleDrawer]);
const drawerContent = useMemo(
() => (
<List>
<ListItemButton divider onClick={handleToggleDrawer}>
<ListItemIcon>
<ListItemText>Link 1</ListItemText>
</ListItemIcon>
</ListItemButton>
<ListItem divider onClick={handleToggleDrawer}>
<ListItemIcon>
<ListItemText>Link 2</ListItemText>
</ListItemIcon>
</ListItem>
<ListItem divider onClick={handleToggleDrawer}>
<ListItemText>Link 3</ListItemText>
</ListItem>
<ListItem divider>
<IconButton onClick={toggleColorMode}>
<ListItemText>Toggle {theme.palette.mode} mode</ListItemText>
{theme.palette.mode === 'dark' ? (
<Brightness7Icon />
) : (
<Brightness4Icon />
)}
</IconButton>
</ListItem>
</List>
),
[handleToggleDrawer]
);

return (
<AppBar
@@ -118,11 +135,20 @@ const Navbar = () => {
</IconButton>
</Box>
) : (
<IconButton>
<Badge badgeContent={3} color="primary">
<ShoppingBasketIcon color="action" />
</Badge>
</IconButton>
<Box>
<IconButton>
<Badge badgeContent={3} color="primary">
<ShoppingBasketIcon color="action" />
</Badge>
</IconButton>
<IconButton sx={{ ml: 1 }} onClick={toggleColorMode}>
{theme.palette.mode === 'dark' ? (
<Brightness7Icon />
) : (
<Brightness4Icon />
)}
</IconButton>
</Box>
)}
</Box>
</Box>

+ 21
- 0
src/context/ColorModeContext.js 查看文件

@@ -0,0 +1,21 @@
import React, { createContext } from 'react';
import PropTypes from 'prop-types';
import { ThemeProvider } from '@mui/material/styles';
import useToggleColorMode from '../hooks/useToggleColorMode';

export const ColorModeContext = createContext();

const ColorModeProvider = ({ children }) => {
const [toggleColorMode, theme] = useToggleColorMode();
return (
<ColorModeContext.Provider value={toggleColorMode}>
<ThemeProvider theme={theme}>{children}</ThemeProvider>
</ColorModeContext.Provider>
);
};

ColorModeProvider.propTypes = {
children: PropTypes.node,
};

export default ColorModeProvider;

+ 31
- 0
src/hooks/useToggleColorMode.js 查看文件

@@ -0,0 +1,31 @@
import { useState, useMemo } from 'react';
import { createTheme } from '@mui/material/styles';
import {
authScopeSetHelper,
authScopeStringGetHelper,
} from '../util/helpers/authScopeHelpers';

const useToggleColorMode = () => {
const currentColorMode = authScopeStringGetHelper('colorMode') || 'light';
const [mode, setMode] = useState(currentColorMode);

const toggleColorMode = () => {
const nextMode = mode === 'light' ? 'dark' : 'light';
setMode(nextMode);
authScopeSetHelper('colorMode', nextMode);
};

const theme = useMemo(
() =>
createTheme({
palette: {
mode,
},
}),
[mode]
);

return [toggleColorMode, theme];
};

export default useToggleColorMode;

+ 5
- 2
src/index.js 查看文件

@@ -8,14 +8,17 @@ import App from './App';
import store from './store';

import './i18n';
import ColorModeProvider from './context/ColorModeContext';

ReactDOM.render(
<HelmetProvider>
<React.StrictMode>
<Provider store={store}>
<App />
<ColorModeProvider>
<App />
</ColorModeProvider>
</Provider>
</React.StrictMode>
</HelmetProvider>,
document.getElementById('root'),
);
);

+ 4
- 62
src/pages/HomePage/HomePageMUI.js 查看文件

@@ -1,72 +1,14 @@
import React, { useState } from 'react';
import { Box, Button, Divider, Paper, Typography } from '@mui/material';
import DialogComponent from '../../components/MUI/DialogComponent';
import DrawerComponent from '../../components/MUI/DrawerComponent';
import React from 'react';
import Navbar from '../../components/MUI/Navbar';
import PopoverComponent from '../../components/MUI/PopoverComponent';
import Modals from '../../components/MUI/Examples/Modals';

const HomePage = () => {
const [dialogOpen, setDialogOpen] = useState(false);
const [drawerOpen, setDrawerOpen] = useState(false);
const [popoverOpen, setPopoverOpen] = useState(false);
const [anchorEl, setAnchorEl] = useState(null);


return (
<>
<Navbar />
<Box
sx={{
mt: 4,
ml: 4,
display: 'flex',
flexGrow: 1,
}}
>
<Paper
sx={{
p: 4,
display: 'flex',
flexDirection: 'column',
}}
>
<Typography variant="h4" gutterBottom align="center">Modals</Typography>
<Divider />
<Button onClick={() => setDialogOpen(true)}>Open Dialog</Button>
<Button onClick={() => setDrawerOpen(true)}>Open Drawer</Button>
<Button
onClick={(e) => {
setPopoverOpen(true);
setAnchorEl(e.currentTarget);
}}
>
Open Popover
</Button>
</Paper>
<DialogComponent
title="Dialog Title"
content={<Typography>Dialog Content</Typography>}
open={dialogOpen}
onClose={() => setDialogOpen(false)}
maxWidth="md"
fullWidth
responsive
/>
<DrawerComponent
anchor="left"
content={<Typography sx={{ p: 2 }}>Drawer Content</Typography>}
open={drawerOpen}
toggleOpen={() => setDrawerOpen(!drawerOpen)}
/>
<PopoverComponent
anchorEl={anchorEl}
open={popoverOpen}
onClose={() => {
setPopoverOpen(false);
setAnchorEl(null);
}}
content={<Typography sx={{ p: 2 }}>Popover Content</Typography>}
/>
</Box>
<Modals />
</>
);
};

正在加载...
取消
保存