使用 MUI v5 做出反应的黑暗模式
Dark Mode in react using MUI v5
在 v5 中尝试创建一个切换以从暗模式切换到亮模式对我来说相当困难。
直接使用来自 MUI Sandbox MUI darkmode 的代码,我试图将代码分开以在 app.js 和我的 Navbarpractice.js 中工作。
App.js
import React from "react";
import useMediaQuery from '@mui/material/useMediaQuery';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import { Paper } from "@mui/material";
import BasicCard from "./components /Card.js";
import Navbarpractice from "./components /Navbar/Navbarpractice"
const ColorModeContext = React.createContext({ toggleColorMode: () => {} });
function App() {
const [mode, setMode] = React.useState('light');
const colorMode = React.useMemo(
() => ({
toggleColorMode: () => {
setMode((prevMode) => (prevMode === 'light' ? 'dark' : 'light'));
},
}),
[],
);
const theme = React.useMemo(
() =>
createTheme({
palette: {
mode,
},
}),
[mode],
);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
<div className="App">
<Navbarpractice/>
<BasicCard/>
</div>
</ThemeProvider>
</ColorModeContext.Provider>
);
}
export default App;
Navbarpractice.js
import React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import MenuIcon from '@mui/icons-material/Menu';
import { useTheme, ThemeProvider, createTheme } from '@mui/material/styles';
import { teal } from '@mui/material/colors';
import { withStyles } from '@mui/styles';
import { Switch } from '@mui/material';
import Brightness4Icon from '@mui/icons-material/Brightness4';
import Brightness7Icon from '@mui/icons-material/Brightness7';
const label = { inputProps: { 'aria-label': 'Switch' } };
const ColorModeContext = React.createContext({ toggleColorMode: () => {} });
const theme = createTheme({
Navbar: {
primary: {
// Purple and green play nicely together.
main: teal[500],
},
secondary: {
// This is green.A700 as hex.
main: '#11cb5f',
},
},
});
const TealTextTypography = withStyles({
root: {
color: "#008080"
}
})(Typography);
function Navbar() {
const theme = useTheme();
const colorMode = React.useContext(ColorModeContext);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>\
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static"
style={{ background: 'transparent', boxShadow: 'none'}}>
<Toolbar>
<IconButton
size="large"
edge="start"
aria-label="menu"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<TealTextTypography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Mentors
</TealTextTypography>
<TealTextTypography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Mentees
</TealTextTypography>
<Box
sx={{
display: 'flex',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
bgcolor: 'background.default',
color: 'text.primary',
borderRadius: 1,
p: 3,
}}
>
<IconButton sx={{ ml: 1 }} onClick={colorMode.toggleColorMode} color="inherit">
{ theme.palette.mode === 'dark' ? <Brightness7Icon /> : <Brightness4Icon />}
</IconButton>
</Box>
</Toolbar>
</AppBar>
</Box>
</ThemeProvider>
</ColorModeContext.Provider>
);
}
export default Navbar;
我确定我混淆了我的常量。并将它们放在错误的地方。虽然我是 React 和 Mui 的新手,但我确实设法让它静态工作,但是,切换被证明是困难的。
这似乎对我有用
App.js
import React from 'react';
import {
ThemeProvider,
createTheme,
responsiveFontSizes,
} from '@mui/material/styles';
import { deepmerge } from '@mui/utils';
import useMediaQuery from '@mui/material/useMediaQuery';
import { getDesignTokens, getThemedComponents } from 'theme/Theme';
import { ColorModeContext } from 'config/color-context';
export default function App() {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const [mode, setMode] = React.useState();
React.useEffect(() => {
setMode(prefersDarkMode ? 'dark' : 'light');
}, [prefersDarkMode]);
const colorMode = React.useMemo(
() => ({
toggleColorMode: () => {
setMode((prevMode) => (prevMode === 'light' ? 'dark' : 'light'));
},
}),
[]
);
let theme = React.useMemo(
() =>
createTheme(deepmerge(getDesignTokens(mode), getThemedComponents(mode))),
[mode]
);
theme = responsiveFontSizes(theme);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
...
</ThemeProvider>
</ColorModeContext.Provider>
);
}
Theme.js
import { amber, deepOrange, grey, blue, common } from '@mui/material/colors';
const palette = {
light: {
primary: {
main: '#34C0AC',
light: '#B1DED3',
dark: '#00765A',
},
},
};
export const getDesignTokens = (mode) => ({
palette: {
mode,
...(mode === 'light'
? {
primary: {
main: palette.light.primary.main,
light: palette.light.primary.light,
dark: palette.light.primary.dark,
},
divider: amber[200],
text: {
primary: grey[900],
secondary: grey[800],
},
}
: {
primary: deepOrange,
divider: deepOrange[700],
background: {
default: deepOrange[900],
paper: deepOrange[900],
},
text: {
primary: '#fff',
secondary: grey[500],
},
}),
},
typography: {
fontFamily: [
'Oswald',
'Roboto',
'"Helvetica Neue"',
'Arial',
'sans-serif',
].join(','),
body1: {
fontFamily: 'Poppins, Arial, sans-serif',
},
},
});
export const getThemedComponents = (mode) => ({
components: {
...(mode === 'light'
? {
MuiAppBar: {
styleOverrides: {
colorPrimary: {
backgroundColor: grey[800],
},
},
},
MuiLink: {
variant: 'h3',
},
MuiButton: {
styleOverrides: {
root: {
borderRadius: 0,
color: common.white,
fontFamily:
"Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
fontSize: 20,
borderWidth: 2,
'&:hover': {
borderWidth: 2,
},
},
},
variants: [
{
props: { variant: 'contained' },
style: {
fontFamily:
"Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
},
},
{
props: { variant: 'outlined' },
style: {
color: palette.light.primary.main,
},
},
{
props: { variant: 'primary', color: 'primary' },
style: {
border: '4px dashed blue',
},
},
],
},
MuiList: {
styleOverrides: {
root: {},
},
},
MuiMenuItem: {
styleOverrides: {
root: {
color: common.white,
alignItems: 'stretch',
fontFamily:
"Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
},
},
},
MuiAccordion: {
styleOverrides: {
root: {
color: common.white,
fontFamily:
"Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
},
},
},
}
: {
MuiAppBar: {
styleOverrides: {
colorPrimary: {
backgroundColor: blue[800],
},
},
},
}),
},
});
color-context.js
import React from 'react';
export const ColorModeContext = React.createContext({
toggleColorMode: () => {
// This is intentional
},
});
ThemeToggler.js
import React from 'react';
import { IconButton, Box } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import Brightness4Icon from '@mui/icons-material/Brightness4';
import Brightness7Icon from '@mui/icons-material/Brightness7';
import { ColorModeContext } from 'config/color-context';
export default function SubHeaderNavigation() {
const theme = useTheme();
const colorMode = React.useContext(ColorModeContext);
return (
<Box
sx={{
display: 'flex',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
bgcolor: 'background.default',
color: 'text.primary',
borderRadius: 1,
p: 3,
}}
>
{theme.palette.mode} mode
<IconButton
sx={{ ml: 1 }}
onClick={colorMode.toggleColorMode}
color="inherit"
>
{theme.palette.mode === 'dark' ? (
<Brightness7Icon />
) : (
<Brightness4Icon />
)}
</IconButton>
</Box>
);
}
在 v5 中尝试创建一个切换以从暗模式切换到亮模式对我来说相当困难。
直接使用来自 MUI Sandbox MUI darkmode 的代码,我试图将代码分开以在 app.js 和我的 Navbarpractice.js 中工作。
App.js
import React from "react";
import useMediaQuery from '@mui/material/useMediaQuery';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import { Paper } from "@mui/material";
import BasicCard from "./components /Card.js";
import Navbarpractice from "./components /Navbar/Navbarpractice"
const ColorModeContext = React.createContext({ toggleColorMode: () => {} });
function App() {
const [mode, setMode] = React.useState('light');
const colorMode = React.useMemo(
() => ({
toggleColorMode: () => {
setMode((prevMode) => (prevMode === 'light' ? 'dark' : 'light'));
},
}),
[],
);
const theme = React.useMemo(
() =>
createTheme({
palette: {
mode,
},
}),
[mode],
);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
<div className="App">
<Navbarpractice/>
<BasicCard/>
</div>
</ThemeProvider>
</ColorModeContext.Provider>
);
}
export default App;
Navbarpractice.js
import React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import MenuIcon from '@mui/icons-material/Menu';
import { useTheme, ThemeProvider, createTheme } from '@mui/material/styles';
import { teal } from '@mui/material/colors';
import { withStyles } from '@mui/styles';
import { Switch } from '@mui/material';
import Brightness4Icon from '@mui/icons-material/Brightness4';
import Brightness7Icon from '@mui/icons-material/Brightness7';
const label = { inputProps: { 'aria-label': 'Switch' } };
const ColorModeContext = React.createContext({ toggleColorMode: () => {} });
const theme = createTheme({
Navbar: {
primary: {
// Purple and green play nicely together.
main: teal[500],
},
secondary: {
// This is green.A700 as hex.
main: '#11cb5f',
},
},
});
const TealTextTypography = withStyles({
root: {
color: "#008080"
}
})(Typography);
function Navbar() {
const theme = useTheme();
const colorMode = React.useContext(ColorModeContext);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>\
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static"
style={{ background: 'transparent', boxShadow: 'none'}}>
<Toolbar>
<IconButton
size="large"
edge="start"
aria-label="menu"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<TealTextTypography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Mentors
</TealTextTypography>
<TealTextTypography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Mentees
</TealTextTypography>
<Box
sx={{
display: 'flex',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
bgcolor: 'background.default',
color: 'text.primary',
borderRadius: 1,
p: 3,
}}
>
<IconButton sx={{ ml: 1 }} onClick={colorMode.toggleColorMode} color="inherit">
{ theme.palette.mode === 'dark' ? <Brightness7Icon /> : <Brightness4Icon />}
</IconButton>
</Box>
</Toolbar>
</AppBar>
</Box>
</ThemeProvider>
</ColorModeContext.Provider>
);
}
export default Navbar;
我确定我混淆了我的常量。并将它们放在错误的地方。虽然我是 React 和 Mui 的新手,但我确实设法让它静态工作,但是,切换被证明是困难的。
这似乎对我有用
App.js
import React from 'react';
import {
ThemeProvider,
createTheme,
responsiveFontSizes,
} from '@mui/material/styles';
import { deepmerge } from '@mui/utils';
import useMediaQuery from '@mui/material/useMediaQuery';
import { getDesignTokens, getThemedComponents } from 'theme/Theme';
import { ColorModeContext } from 'config/color-context';
export default function App() {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const [mode, setMode] = React.useState();
React.useEffect(() => {
setMode(prefersDarkMode ? 'dark' : 'light');
}, [prefersDarkMode]);
const colorMode = React.useMemo(
() => ({
toggleColorMode: () => {
setMode((prevMode) => (prevMode === 'light' ? 'dark' : 'light'));
},
}),
[]
);
let theme = React.useMemo(
() =>
createTheme(deepmerge(getDesignTokens(mode), getThemedComponents(mode))),
[mode]
);
theme = responsiveFontSizes(theme);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
...
</ThemeProvider>
</ColorModeContext.Provider>
);
}
Theme.js
import { amber, deepOrange, grey, blue, common } from '@mui/material/colors';
const palette = {
light: {
primary: {
main: '#34C0AC',
light: '#B1DED3',
dark: '#00765A',
},
},
};
export const getDesignTokens = (mode) => ({
palette: {
mode,
...(mode === 'light'
? {
primary: {
main: palette.light.primary.main,
light: palette.light.primary.light,
dark: palette.light.primary.dark,
},
divider: amber[200],
text: {
primary: grey[900],
secondary: grey[800],
},
}
: {
primary: deepOrange,
divider: deepOrange[700],
background: {
default: deepOrange[900],
paper: deepOrange[900],
},
text: {
primary: '#fff',
secondary: grey[500],
},
}),
},
typography: {
fontFamily: [
'Oswald',
'Roboto',
'"Helvetica Neue"',
'Arial',
'sans-serif',
].join(','),
body1: {
fontFamily: 'Poppins, Arial, sans-serif',
},
},
});
export const getThemedComponents = (mode) => ({
components: {
...(mode === 'light'
? {
MuiAppBar: {
styleOverrides: {
colorPrimary: {
backgroundColor: grey[800],
},
},
},
MuiLink: {
variant: 'h3',
},
MuiButton: {
styleOverrides: {
root: {
borderRadius: 0,
color: common.white,
fontFamily:
"Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
fontSize: 20,
borderWidth: 2,
'&:hover': {
borderWidth: 2,
},
},
},
variants: [
{
props: { variant: 'contained' },
style: {
fontFamily:
"Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
},
},
{
props: { variant: 'outlined' },
style: {
color: palette.light.primary.main,
},
},
{
props: { variant: 'primary', color: 'primary' },
style: {
border: '4px dashed blue',
},
},
],
},
MuiList: {
styleOverrides: {
root: {},
},
},
MuiMenuItem: {
styleOverrides: {
root: {
color: common.white,
alignItems: 'stretch',
fontFamily:
"Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
},
},
},
MuiAccordion: {
styleOverrides: {
root: {
color: common.white,
fontFamily:
"Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
},
},
},
}
: {
MuiAppBar: {
styleOverrides: {
colorPrimary: {
backgroundColor: blue[800],
},
},
},
}),
},
});
color-context.js
import React from 'react';
export const ColorModeContext = React.createContext({
toggleColorMode: () => {
// This is intentional
},
});
ThemeToggler.js
import React from 'react';
import { IconButton, Box } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import Brightness4Icon from '@mui/icons-material/Brightness4';
import Brightness7Icon from '@mui/icons-material/Brightness7';
import { ColorModeContext } from 'config/color-context';
export default function SubHeaderNavigation() {
const theme = useTheme();
const colorMode = React.useContext(ColorModeContext);
return (
<Box
sx={{
display: 'flex',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
bgcolor: 'background.default',
color: 'text.primary',
borderRadius: 1,
p: 3,
}}
>
{theme.palette.mode} mode
<IconButton
sx={{ ml: 1 }}
onClick={colorMode.toggleColorMode}
color="inherit"
>
{theme.palette.mode === 'dark' ? (
<Brightness7Icon />
) : (
<Brightness4Icon />
)}
</IconButton>
</Box>
);
}