From f9cd68181137c72e92c6951efd9b8d29c4b73bc1 Mon Sep 17 00:00:00 2001 From: Tom van der Lee Date: Tue, 25 Jan 2022 21:42:51 +0100 Subject: Added dark mode --- src/components/App/App.tsx | 94 +++++++++++++++++++++++++++++++++----- src/components/Content/Content.tsx | 6 +-- src/components/Icons/Moon.tsx | 11 +++++ src/components/Icons/Sliders.tsx | 10 ++++ src/components/Icons/Sun.tsx | 9 ++++ src/components/Icons/Trash.tsx | 13 ++++++ src/hooks/useDarkMode.tsx | 21 +++++++++ src/hooks/useRequests.tsx | 5 ++ src/index.scss | 4 ++ src/index.tsx | 2 - 10 files changed, 158 insertions(+), 17 deletions(-) create mode 100644 src/components/Icons/Moon.tsx create mode 100644 src/components/Icons/Sliders.tsx create mode 100644 src/components/Icons/Sun.tsx create mode 100644 src/components/Icons/Trash.tsx create mode 100644 src/hooks/useDarkMode.tsx (limited to 'src') diff --git a/src/components/App/App.tsx b/src/components/App/App.tsx index cb82abc..bbab612 100644 --- a/src/components/App/App.tsx +++ b/src/components/App/App.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import {useEffect, useMemo, useState} from "react"; +import {ReactElement, useEffect, useMemo, useState} from "react"; import useRequests, { ReadyState, RequestResponse @@ -9,13 +9,24 @@ import styles from './App.module.scss'; import Details from "../Details/Details"; import RequestSummary from "../RequestSummary/RequestSummary"; import {getHost} from "../../utils"; -import {Container, ListGroup, Navbar} from "react-bootstrap"; +import {Container, ListGroup, Nav, Navbar, NavDropdown} from "react-bootstrap"; import classNames from "classnames"; +import useDarkMode from "../../hooks/useDarkMode"; +import {Sliders} from "../Icons/Sliders"; +import {Sun} from "../Icons/Sun"; +import {Moon} from "../Icons/Moon"; +import Trash from "../Icons/Trash"; interface Config { url: string } +interface SettingsMenu { + icon: ReactElement, + label: string, + onClick: () => void, +} + type ReadyStateMap = { [ReadyState.CONNECTING]: string, [ReadyState.OPEN]: string, @@ -23,18 +34,25 @@ type ReadyStateMap = { [ReadyState.CLOSED]: string, } -const statusMap: ReadyStateMap = { +const statusIconMap: ReadyStateMap = { [ReadyState.CONNECTING]: '🔴', [ReadyState.OPEN]: '🟢', [ReadyState.CLOSING]: '🔴', [ReadyState.CLOSED]: '🔴', } -export default function App() { +const statusTextMap: ReadyStateMap = { + [ReadyState.CONNECTING]: 'Connecting...', + [ReadyState.OPEN]: 'Connected', + [ReadyState.CLOSING]: 'Closing...', + [ReadyState.CLOSED]: 'Closed', +} +export default function App() { + const { darkMode, toggle } = useDarkMode(); const [config, setConfig]= useState(null) - const { calls, readyState } = useRequests({ + const { calls, readyState, clear } = useRequests({ onConnect: async () => { const response = await fetch(`http://${getHost()}/config/`) const config = await response.json() @@ -44,7 +62,7 @@ export default function App() { useEffect(() => { const url = new URL(config?.url ?? 'https://loading...'); - document.title = `${statusMap[readyState]} ${url.host} | TTUN`; + document.title = `${statusIconMap[readyState]} ${url.host} | TTUN`; }, [readyState, config?.url]) const [selectedRequestIndex, setSelectedRequestIndex] = useState(null); @@ -54,6 +72,23 @@ export default function App() { : calls[selectedRequestIndex] ), [selectedRequestIndex, calls]); + const settingsMenu: (SettingsMenu | null)[] = [ + { + onClick: toggle, + icon: darkMode ? : , + label: darkMode ? "Light mode" : "DarkMode", + }, + null, + { + onClick: () => { + setSelectedRequestIndex(null); + clear(); + }, + icon: , + label: "Clear" + } + ]; + return config && (
- - {statusMap[readyState]} TTUN - - - {config.url} - +
+ + TTUN + + + {`${statusIconMap[readyState]} ${statusTextMap[readyState]}`} + +
+
+ + {config.url} + + + + + +
diff --git a/src/components/Content/Content.tsx b/src/components/Content/Content.tsx index 0e63f30..95ee444 100644 --- a/src/components/Content/Content.tsx +++ b/src/components/Content/Content.tsx @@ -30,9 +30,9 @@ export default function Content({ raw, setRaw, data }: ContentProps): JSX.Elemen
- - setRaw(!raw)}/> - + + setRaw(!raw)}/> + { diff --git a/src/components/Icons/Moon.tsx b/src/components/Icons/Moon.tsx new file mode 100644 index 0000000..7e3e680 --- /dev/null +++ b/src/components/Icons/Moon.tsx @@ -0,0 +1,11 @@ +import * as React from "react"; + +export function Moon() { + return + + ; +} diff --git a/src/components/Icons/Sliders.tsx b/src/components/Icons/Sliders.tsx new file mode 100644 index 0000000..9feef34 --- /dev/null +++ b/src/components/Icons/Sliders.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; + +export function Sliders() { + return + + ; +} diff --git a/src/components/Icons/Sun.tsx b/src/components/Icons/Sun.tsx new file mode 100644 index 0000000..93a5187 --- /dev/null +++ b/src/components/Icons/Sun.tsx @@ -0,0 +1,9 @@ +import * as React from "react"; + +export function Sun() { + return + + ; +} diff --git a/src/components/Icons/Trash.tsx b/src/components/Icons/Trash.tsx new file mode 100644 index 0000000..b1fb2c3 --- /dev/null +++ b/src/components/Icons/Trash.tsx @@ -0,0 +1,13 @@ +import * as React from "react"; + +export default function Trash() { + return ( + + + + + ) +} diff --git a/src/hooks/useDarkMode.tsx b/src/hooks/useDarkMode.tsx new file mode 100644 index 0000000..fe4ce95 --- /dev/null +++ b/src/hooks/useDarkMode.tsx @@ -0,0 +1,21 @@ +import {useEffect, useMemo, useState} from "react"; +import {ThemeConfig} from "bootstrap-darkmode"; + +export interface UseDarkMode { + darkMode: boolean + toggle: () => void +} + +export default function useDarkMode() { + const themeConfig = useMemo(() => new ThemeConfig(), []); + const [darkMode, setDarkMode] = useState(() => themeConfig.getTheme() === 'dark') + + useEffect(() => { + themeConfig.setTheme(darkMode ? 'dark' : 'light'); + }, [darkMode]) + + return { + darkMode, + toggle: () => setDarkMode(dm => !dm), + } +} diff --git a/src/hooks/useRequests.tsx b/src/hooks/useRequests.tsx index 5ac70a4..cb85162 100644 --- a/src/hooks/useRequests.tsx +++ b/src/hooks/useRequests.tsx @@ -57,6 +57,7 @@ export interface useRequestsProps { export interface UseRequests { calls: RequestResponse[] readyState: ReadyState + clear: () => void } export default function useRequests({ onConnect }: useRequestsProps): UseRequests { @@ -124,5 +125,9 @@ export default function useRequests({ onConnect }: useRequestsProps): UseRequest response: responses.find(({id}) => id === request.id) })), [requests, responses]), readyState, + clear: () => { + setRequests([]) + setResponses([]) + } } } diff --git a/src/index.scss b/src/index.scss index 13d82ca..e8236c1 100644 --- a/src/index.scss +++ b/src/index.scss @@ -1,3 +1,7 @@ +@import "../node_modules/bootstrap/scss/bootstrap"; +@import "../node_modules/bootstrap-icons/font/bootstrap-icons"; +@import "../node_modules/bootstrap-darkmode/scss/darktheme"; + * { box-sizing: border-box; } diff --git a/src/index.tsx b/src/index.tsx index c381d4a..a6c4952 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,8 +2,6 @@ import * as React from "react"; import * as ReactDOM from "react-dom"; import App from "./components/App/App"; -import 'bootstrap/dist/css/bootstrap.min.css'; - import './index.scss'; ReactDOM.render(, document.getElementById("root")); -- cgit v1.2.3