|
|
@@ -1,45 +1,86 @@
|
|
|
-import React, { useState } from "react";
|
|
|
-import { createTheme } from "@material-ui/core/styles";
|
|
|
-import { ThemeProvider } from "@material-ui/styles";
|
|
|
-import { CssBaseline } from "@material-ui/core";
|
|
|
-import blue from "@material-ui/core/colors/blue";
|
|
|
-import green from "@material-ui/core/colors/green";
|
|
|
+import React, { useState,useEffect } from 'react';
|
|
|
+import { createTheme } from '@material-ui/core/styles';
|
|
|
+import { ThemeProvider } from '@material-ui/styles';
|
|
|
|
|
|
+const ToggleButton = styled.button`
|
|
|
+ --toggle-width: 80px;
|
|
|
+ --toggle-height: 38px;
|
|
|
+ --toggle-padding: 4px;
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-around;
|
|
|
+ font-size: 1.5rem;
|
|
|
+ line-height: 1;
|
|
|
+ width: var(--toggle-width);
|
|
|
+ height: var(--toggle-height);
|
|
|
+ padding: var(--toggle-padding);
|
|
|
+ border: 0;
|
|
|
+ border-radius: calc(var(--toggle-width) / 2);
|
|
|
+ cursor: pointer;
|
|
|
+ background: var(--color-bg-toggle);
|
|
|
+ transition: background 0.25s ease-in-out, box-shadow 0.25s ease-in-out;
|
|
|
+ &:focus {
|
|
|
+ outline-offset: 5px;
|
|
|
+ }
|
|
|
+ &:focus:not(:focus-visible) {
|
|
|
+ outline: none;
|
|
|
+ }
|
|
|
+ &:hover {
|
|
|
+ box-shadow: 0 0 5px 2px var(--color-bg-toggle);
|
|
|
+ },
|
|
|
+`;
|
|
|
|
|
|
+const ToggleThumb = styled.span`
|
|
|
+ position: absolute;
|
|
|
+ top: var(--toggle-padding);
|
|
|
+ left: var(--toggle-padding);
|
|
|
+ width: calc(var(--toggle-height) - (var(--toggle-padding) * 2));
|
|
|
+ height: calc(var(--toggle-height) - (var(--toggle-padding) * 2));
|
|
|
+ border-radius: 50%;
|
|
|
+ background: white;
|
|
|
+ transition: transform 0.25s ease-in-out;
|
|
|
+ transform: ${(p) =>
|
|
|
+ p.activeTheme === "dark"
|
|
|
+ ? "translate3d(calc(var(--toggle-width) - var(--toggle-height)), 0, 0)"
|
|
|
+ : "none"};
|
|
|
+`;
|
|
|
const light = createTheme({
|
|
|
palette: {
|
|
|
- type: "light",
|
|
|
- primary: blue,
|
|
|
- secondary: green,
|
|
|
+ mode: 'light',
|
|
|
},
|
|
|
});
|
|
|
|
|
|
const dark = createTheme({
|
|
|
palette: {
|
|
|
- type: "dark",
|
|
|
- primary: green,
|
|
|
- secondary: blue,
|
|
|
+ mode: 'dark',
|
|
|
},
|
|
|
});
|
|
|
-const Theme = ({ children, theme, ...rest }) =>
|
|
|
- (
|
|
|
- <ThemeProvider theme={theme?light:dark}>
|
|
|
- <CssBaseline />
|
|
|
- {children}
|
|
|
- </ThemeProvider>
|
|
|
- )
|
|
|
-
|
|
|
-export const withTheme = (Component) => {
|
|
|
- return (props) => {
|
|
|
- const [theme, setTheme] = useState(!Theme);
|
|
|
+function activeTheme(themeMode){
|
|
|
+ return themeMode === 'light'? light : dark;
|
|
|
+}
|
|
|
+export const toggleTheme = () => {
|
|
|
+ const [activeTheme, setTheme] = useState("light");
|
|
|
+ const altheme = activeTheme === "light" ? "dark" : "light";
|
|
|
+ useEffect(() => {
|
|
|
+ const savedTheme = window.localStorage.getItem("theme");
|
|
|
+ savedTheme && setActiveTheme(savedTheme);
|
|
|
+ }, []);
|
|
|
+ useEffect(() => {
|
|
|
+ document.body.dataset.theme = activeTheme;
|
|
|
+ window.localStorage.setItem("theme", activeTheme);
|
|
|
+ }, [activeTheme]);
|
|
|
|
|
|
- const handleChange = (c) => {
|
|
|
- setTheme(c)
|
|
|
- }
|
|
|
return (
|
|
|
- <Theme theme={theme}>
|
|
|
- <Component {...props} theme={Theme} onThemeChange={setTheme} />
|
|
|
- </Theme>
|
|
|
+ <ToggleButton
|
|
|
+ aria-label={`Change to ${altheme} mode`}
|
|
|
+ title={`Change to ${altheme} mode`}
|
|
|
+ type="button"
|
|
|
+ onClick={() => setActiveTheme(altheme)}
|
|
|
+ >
|
|
|
+ <ToggleThumb activeTheme={activeTheme} />
|
|
|
+ <span>🌙</span>
|
|
|
+ <span>☀️</span>
|
|
|
+ </ToggleButton>
|
|
|
);
|
|
|
};
|
|
|
-};
|