From 765418d3d24b5d88b7552c98699f1e5a39822c0e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 May 2021 18:30:06 +0200 Subject: [PATCH] Theme changing. Simple routing --- client/package-lock.json | 130 ++++++++++++++++++ client/package.json | 4 + client/src/App.css | 38 ----- client/src/App.module.css | 19 +++ client/src/App.tsx | 19 ++- client/src/components/Apps/Apps.module.css | 0 client/src/components/Apps/Apps.tsx | 17 +++ client/src/components/Settings/Settings.tsx | 15 ++ .../components/Themer/ThemePreview.module.css | 27 ++++ client/src/components/Themer/ThemePreview.tsx | 27 +++- .../src/components/Themer/Themer.module.css | 12 ++ client/src/components/Themer/Themer.tsx | 39 +++++- .../UI/Headline/Headline.module.css | 7 + .../src/components/UI/Headline/Headline.tsx | 18 +++ client/src/components/UI/Icon/Icon.module.css | 4 + client/src/components/UI/Icon/Icon.tsx | 25 ++++ .../components/UI/Layout/Layout.module.css | 4 + client/src/components/UI/Layout/Layout.tsx | 9 ++ client/src/index.css | 23 ++-- 19 files changed, 378 insertions(+), 59 deletions(-) delete mode 100644 client/src/App.css create mode 100644 client/src/App.module.css create mode 100644 client/src/components/Apps/Apps.module.css create mode 100644 client/src/components/Apps/Apps.tsx create mode 100644 client/src/components/Settings/Settings.tsx create mode 100644 client/src/components/Themer/ThemePreview.module.css create mode 100644 client/src/components/Themer/Themer.module.css create mode 100644 client/src/components/UI/Headline/Headline.module.css create mode 100644 client/src/components/UI/Headline/Headline.tsx create mode 100644 client/src/components/UI/Icon/Icon.module.css create mode 100644 client/src/components/UI/Icon/Icon.tsx create mode 100644 client/src/components/UI/Layout/Layout.module.css create mode 100644 client/src/components/UI/Layout/Layout.tsx diff --git a/client/package-lock.json b/client/package-lock.json index e8c2dc6..c8b05b0 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1805,6 +1805,16 @@ } } }, + "@mdi/js": { + "version": "5.9.55", + "resolved": "https://registry.npmjs.org/@mdi/js/-/js-5.9.55.tgz", + "integrity": "sha512-BbeHMgeK2/vjdJIRnx12wvQ6s8xAYfvMmEAVsUx9b+7GiQGQ9Za8jpwp17dMKr9CgKRvemlAM4S7S3QOtEbp4A==" + }, + "@mdi/react": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@mdi/react/-/react-1.5.0.tgz", + "integrity": "sha512-NztRgUxSYD+ImaKN94Tg66VVVqXj4SmlDGzZoz48H9riJ+Awha56sfXH2fegw819NWo7KI3oeS1Es0lNQqwr0w==" + }, "@nodelib/fs.scandir": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", @@ -2275,6 +2285,11 @@ "@types/node": "*" } }, + "@types/history": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz", + "integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==" + }, "@types/html-minifier-terser": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", @@ -2373,6 +2388,25 @@ "@types/react": "*" } }, + "@types/react-router": { + "version": "5.1.14", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.14.tgz", + "integrity": "sha512-LAJpqYUaCTMT2anZheoidiIymt8MuX286zoVFPM3DVb23aQBH0mAkFvzpd4LKqiolV8bBtZWT5Qp7hClCNDENw==", + "requires": { + "@types/history": "*", + "@types/react": "*" + } + }, + "@types/react-router-dom": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.7.tgz", + "integrity": "sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==", + "requires": { + "@types/history": "*", + "@types/react": "*", + "@types/react-router": "*" + } + }, "@types/resolve": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", @@ -7164,6 +7198,19 @@ "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -7174,6 +7221,14 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, "hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -10041,6 +10096,15 @@ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" }, + "mini-create-react-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "requires": { + "@babel/runtime": "^7.12.1", + "tiny-warning": "^1.0.3" + } + }, "mini-css-extract-plugin": { "version": "0.11.3", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz", @@ -12482,6 +12546,52 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", "integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==" }, + "react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "react-router-dom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", + "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, "react-scripts": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.3.tgz", @@ -12918,6 +13028,11 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -14569,6 +14684,16 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" }, + "tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, "tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", @@ -15047,6 +15172,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/client/package.json b/client/package.json index dec67c0..cb7757f 100644 --- a/client/package.json +++ b/client/package.json @@ -3,6 +3,8 @@ "version": "0.1.0", "private": true, "dependencies": { + "@mdi/js": "^5.9.55", + "@mdi/react": "^1.5.0", "@testing-library/jest-dom": "^5.12.0", "@testing-library/react": "^11.2.6", "@testing-library/user-event": "^12.8.3", @@ -10,8 +12,10 @@ "@types/node": "^12.20.12", "@types/react": "^17.0.5", "@types/react-dom": "^17.0.3", + "@types/react-router-dom": "^5.1.7", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", "typescript": "^4.2.4", "web-vitals": "^1.1.2" diff --git a/client/src/App.css b/client/src/App.css deleted file mode 100644 index 74b5e05..0000000 --- a/client/src/App.css +++ /dev/null @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/client/src/App.module.css b/client/src/App.module.css new file mode 100644 index 0000000..6fd7c5f --- /dev/null +++ b/client/src/App.module.css @@ -0,0 +1,19 @@ +.SettingsButton { + width: 35px; + height: 35px; + background-color: var(--color-accent); + border-radius: 50%; + position: absolute; + bottom: 10px; + left: 10px; + display: flex; + justify-content: center; + align-items: center; + opacity: 0.25; + transition: all 0.3s; +} + +.SettingsButton:hover { + cursor: pointer; + opacity: 1; +} \ No newline at end of file diff --git a/client/src/App.tsx b/client/src/App.tsx index eb3e5ef..bcd1d24 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,10 +1,23 @@ -import './App.css'; -import Themer from './components/Themer/Themer'; +import { BrowserRouter, Route, Switch, Link } from 'react-router-dom'; +import classes from './App.module.css'; + +import Apps from './components/Apps/Apps'; +import Settings from './components/Settings/Settings'; + +import Icon from './components/UI/Icon/Icon'; const App = (): JSX.Element => { return ( - + + + + + + + + + ); } diff --git a/client/src/components/Apps/Apps.module.css b/client/src/components/Apps/Apps.module.css new file mode 100644 index 0000000..e69de29 diff --git a/client/src/components/Apps/Apps.tsx b/client/src/components/Apps/Apps.tsx new file mode 100644 index 0000000..a8d16da --- /dev/null +++ b/client/src/components/Apps/Apps.tsx @@ -0,0 +1,17 @@ +import { Link } from 'react-router-dom'; + +import classes from './Apps.module.css'; + +import { Container } from '../UI/Layout/Layout'; +import Headline from '../UI/Headline/Headline'; + +const Apps = (): JSX.Element => { + return ( + + + settings + + ) +} + +export default Apps; \ No newline at end of file diff --git a/client/src/components/Settings/Settings.tsx b/client/src/components/Settings/Settings.tsx new file mode 100644 index 0000000..00a5caf --- /dev/null +++ b/client/src/components/Settings/Settings.tsx @@ -0,0 +1,15 @@ +import { Link } from 'react-router-dom'; + +import Themer from '../Themer/Themer'; + +const Settings = (): JSX.Element => { + return ( +
+

settings

+ Home + +
+ ) +} + +export default Settings; \ No newline at end of file diff --git a/client/src/components/Themer/ThemePreview.module.css b/client/src/components/Themer/ThemePreview.module.css new file mode 100644 index 0000000..c9c1189 --- /dev/null +++ b/client/src/components/Themer/ThemePreview.module.css @@ -0,0 +1,27 @@ +.ThemePreview { + width: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.ThemePreview:hover { + cursor: pointer; +} + +.ThemePreview p { + text-transform: capitalize; + margin: 8px 0; + /* align-self: flex-start; */ +} + +.ColorsPreview { + display: flex; + border: 1px solid silver; +} + +.ColorPreview { + width: 50px; + height: 50px; +} \ No newline at end of file diff --git a/client/src/components/Themer/ThemePreview.tsx b/client/src/components/Themer/ThemePreview.tsx index ff14e75..b390184 100644 --- a/client/src/components/Themer/ThemePreview.tsx +++ b/client/src/components/Themer/ThemePreview.tsx @@ -1,10 +1,29 @@ import { Theme } from '../../interfaces/Theme'; +import classes from './ThemePreview.module.css'; -const ThemePreview = (theme: Theme): JSX.Element => { +interface ComponentProps { + theme: Theme; + applyTheme: Function; +} + +const ThemePreview = (props: ComponentProps): JSX.Element => { return ( -
-

Theme: {theme.name}

-

{theme.colors.background}

+
props.applyTheme(props.theme.name)}> +
+
+
+
+
+

{props.theme.name}

) } diff --git a/client/src/components/Themer/Themer.module.css b/client/src/components/Themer/Themer.module.css new file mode 100644 index 0000000..6473c62 --- /dev/null +++ b/client/src/components/Themer/Themer.module.css @@ -0,0 +1,12 @@ +.ThemerGrid { + width: 100%; + display: grid; + grid-template-columns: 1fr 1fr; + grid-auto-rows: 100px; +} + +@media (min-width: 900px) { + .ThemerGrid { + grid-template-columns: 1fr 1fr 1fr; + } +} \ No newline at end of file diff --git a/client/src/components/Themer/Themer.tsx b/client/src/components/Themer/Themer.tsx index ce8bec5..31cf847 100644 --- a/client/src/components/Themer/Themer.tsx +++ b/client/src/components/Themer/Themer.tsx @@ -1,13 +1,44 @@ +import { useEffect } from 'react'; + +import classes from './Themer.module.css'; + import { themes } from './themes.json'; import { Theme } from '../../interfaces/Theme'; import ThemePreview from './ThemePreview'; +import { Container } from '../UI/Layout/Layout'; +import Headline from '../UI/Headline/Headline'; const Themer = (): JSX.Element => { + useEffect((): void => { + if (localStorage.theme) { + applyTheme(localStorage.theme); + } + }, []); + + const applyTheme = (themeName: string): void => { + const newTheme = themes.find((theme: Theme) => theme.name === themeName); + + if (newTheme) { + for (const [key, value] of Object.entries(newTheme.colors)) { + document.body.style.setProperty(`--color-${key}`, value); + } + localStorage.setItem('theme', themeName); + } + } + return ( -
-

Themes

- {themes.map((theme: Theme): JSX.Element => )} -
+ +
+ +
+ {themes.map((theme: Theme): JSX.Element => )} +
+
+
+ ) } diff --git a/client/src/components/UI/Headline/Headline.module.css b/client/src/components/UI/Headline/Headline.module.css new file mode 100644 index 0000000..f2646fb --- /dev/null +++ b/client/src/components/UI/Headline/Headline.module.css @@ -0,0 +1,7 @@ +.HeadlineTitle { + color: var(--color-primary); +} + +.HeadlineSubtitle { + color: var(--color-primary); +} \ No newline at end of file diff --git a/client/src/components/UI/Headline/Headline.tsx b/client/src/components/UI/Headline/Headline.tsx new file mode 100644 index 0000000..10276e9 --- /dev/null +++ b/client/src/components/UI/Headline/Headline.tsx @@ -0,0 +1,18 @@ +import { Fragment } from 'react'; +import classes from './Headline.module.css'; + +interface ComponentProps { + title: string; + subtitle?: string; +} + +const Headline = (props: ComponentProps): JSX.Element => { + return ( + +

{props.title}

+ {props.subtitle &&

{props.subtitle}

} +
+ ) +} + +export default Headline; \ No newline at end of file diff --git a/client/src/components/UI/Icon/Icon.module.css b/client/src/components/UI/Icon/Icon.module.css new file mode 100644 index 0000000..871f07e --- /dev/null +++ b/client/src/components/UI/Icon/Icon.module.css @@ -0,0 +1,4 @@ +.Icon { + color: var(--color-primary); + width: 90%; +} \ No newline at end of file diff --git a/client/src/components/UI/Icon/Icon.tsx b/client/src/components/UI/Icon/Icon.tsx new file mode 100644 index 0000000..3bdc420 --- /dev/null +++ b/client/src/components/UI/Icon/Icon.tsx @@ -0,0 +1,25 @@ +import classes from './Icon.module.css'; + +import { Icon as MDIcon } from '@mdi/react'; + +interface ComponentProps { + icon: string; +} + +const Icon = (props: ComponentProps): JSX.Element => { + const MDIcons = require('@mdi/js'); + let iconPath = MDIcons[props.icon]; + + if (!iconPath) { + console.log('icon not found'); + iconPath = MDIcons.mdiCancel; + } + + return ( + + ) +} + +export default Icon; \ No newline at end of file diff --git a/client/src/components/UI/Layout/Layout.module.css b/client/src/components/UI/Layout/Layout.module.css new file mode 100644 index 0000000..0688765 --- /dev/null +++ b/client/src/components/UI/Layout/Layout.module.css @@ -0,0 +1,4 @@ +.Container { + width: 100%; + padding: var(--space-p-x); +} \ No newline at end of file diff --git a/client/src/components/UI/Layout/Layout.tsx b/client/src/components/UI/Layout/Layout.tsx new file mode 100644 index 0000000..03a20fc --- /dev/null +++ b/client/src/components/UI/Layout/Layout.tsx @@ -0,0 +1,9 @@ +import classes from './Layout.module.css'; + +export const Container = (props: any): JSX.Element => { + return ( +
+ {props.children} +
+ ) +} \ No newline at end of file diff --git a/client/src/index.css b/client/src/index.css index ec2585e..4c67514 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -1,13 +1,16 @@ -body { +* { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + padding: 0; + box-sizing: border-box; } -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} +body { + --color-background: #2B2C56; + --color-primary: #EFF1FC; + --color-accent: #6677EB; + + --space-p-x: 16px; + + background-color: var(--color-background); + font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Roboto, sans-serif; +} \ No newline at end of file