From bdbca36b8cc5e2f05ded0a4d37506be25fc278fa Mon Sep 17 00:00:00 2001 From: katspaugh <381895+katspaugh@users.noreply.github.com> Date: Mon, 10 Jan 2022 13:31:15 +0100 Subject: [PATCH] Feature: dark mode --- .../AppLayout/Header/components/Layout.tsx | 2 +- src/components/AppLayout/index.tsx | 2 + src/components/Root/index.module.scss | 11 ++++- src/logic/hooks/useDarkMode.ts | 18 ++++++++ .../components/Settings/Appearance/index.tsx | 44 ++++++++++++------- 5 files changed, 60 insertions(+), 17 deletions(-) create mode 100644 src/logic/hooks/useDarkMode.ts diff --git a/src/components/AppLayout/Header/components/Layout.tsx b/src/components/AppLayout/Header/components/Layout.tsx index ad919233ec..5af95122d1 100644 --- a/src/components/AppLayout/Header/components/Layout.tsx +++ b/src/components/AppLayout/Header/components/Layout.tsx @@ -100,7 +100,7 @@ const Layout = ({ classes, providerDetails, providerInfo }) => { - Gnosis Safe + diff --git a/src/components/AppLayout/index.tsx b/src/components/AppLayout/index.tsx index 49c6a2a68a..094e0e26d4 100644 --- a/src/components/AppLayout/index.tsx +++ b/src/components/AppLayout/index.tsx @@ -9,6 +9,7 @@ import Footer from './Footer' import Sidebar from './Sidebar' import { MobileNotSupported } from './MobileNotSupported' import { SAFE_ROUTES, WELCOME_ROUTE } from 'src/routes/routes' +import useDarkMode from 'src/logic/hooks/useDarkMode' const Container = styled.div` height: 100vh; @@ -92,6 +93,7 @@ const Layout: React.FC = ({ }): React.ReactElement => { const [mobileNotSupportedClosed, setMobileNotSupportedClosed] = useState(false) const { pathname } = useLocation() + useDarkMode() const closeMobileNotSupported = () => setMobileNotSupportedClosed(true) diff --git a/src/components/Root/index.module.scss b/src/components/Root/index.module.scss index c1f1221dd7..09d7cdc167 100644 --- a/src/components/Root/index.module.scss +++ b/src/components/Root/index.module.scss @@ -44,4 +44,13 @@ body { body > div:first-child { display: flex; min-height: 100%; -} \ No newline at end of file +} + +html[class="darkMode"] { + filter: invert(1) hue-rotate(180deg); +} + +html[class="darkMode"] div[style*="background-image"], +html[class="darkMode"] img:not([id="safe-logo"]) { + filter: invert(1) hue-rotate(180deg); +} diff --git a/src/logic/hooks/useDarkMode.ts b/src/logic/hooks/useDarkMode.ts new file mode 100644 index 0000000000..6e0f49cf5a --- /dev/null +++ b/src/logic/hooks/useDarkMode.ts @@ -0,0 +1,18 @@ +import { useEffect } from 'react' +import useCachedState from 'src/utils/storage/useCachedState' + +const useDarkMode = (): [boolean, (mode: boolean) => void] => { + const [darkMode = false, setDarkMode] = useCachedState('darkMode') + + const toggleDarkMode = (toggle: boolean): void => { + document.documentElement.className = toggle ? 'darkMode' : '' + } + + useEffect(() => { + toggleDarkMode(darkMode) + }, [darkMode]) + + return [darkMode, setDarkMode] +} + +export default useDarkMode diff --git a/src/routes/safe/components/Settings/Appearance/index.tsx b/src/routes/safe/components/Settings/Appearance/index.tsx index 919d8bfe98..72c131aa47 100644 --- a/src/routes/safe/components/Settings/Appearance/index.tsx +++ b/src/routes/safe/components/Settings/Appearance/index.tsx @@ -15,6 +15,7 @@ import { setCopyShortName } from 'src/logic/appearance/actions/setCopyShortName' import { extractSafeAddress } from 'src/routes/routes' import PrefixedEthHashInfo from 'src/components/PrefixedEthHashInfo' import { useAnalytics, SETTINGS_EVENTS } from 'src/utils/googleAnalytics' +import useDarkMode from 'src/logic/hooks/useDarkMode' // Other settings sections use MUI createStyles .container // will adjust that during dark mode implementation @@ -31,6 +32,7 @@ const Appearance = (): ReactElement => { const copyShortName = useSelector(copyShortNameSelector) const showShortName = useSelector(showShortNameSelector) const safeAddress = extractSafeAddress() + const [darkMode, setDarkMode] = useDarkMode() const { trackEvent } = useAnalytics() @@ -48,21 +50,33 @@ const Appearance = (): ReactElement => { dispatch(setCopyShortName({ copyShortName: checked })) return ( - - Use Chain-Specific Addresses - You can choose whether to prepend EIP-3770 short chain names accross Safes. - - - } - label="Prepend addresses with chain prefix." - /> - } - label="Copy addresses with chain prefix." - /> - - + <> + + Use Chain-Specific Addresses + You can choose whether to prepend EIP-3770 short chain names accross Safes. + + + } + label="Prepend addresses with chain prefix." + /> + } + label="Copy addresses with chain prefix." + /> + + + + + Dark mode (experimental) + + setDarkMode(!darkMode)} name="showShortName" />} + label={`Switch to ${darkMode ? 'light' : 'dark'} mode`} + /> + + + ) }