Liu Song’s Projects


~/Projects/ui

git clone https://code.lsong.org/ui

Commit

Commit
1338aaaa9c0352e62e986f16cf0bcaa985f9f88d
Author
David Mraz <[email protected]>
Date
2022-11-03 12:06:23 +0100 +0100
Diffstat
 README.md | 2 +
 components/ThemeButton.tsx | 45 +++++++++++++++++++++++++++
 components/ThemeSwitcher.module.scss | 48 ++++++++++++++++++++++++++++
 components/ThemeSwitcher.tsx | 47 ++++++++++++++++++++++++++++
 lib/utils.tsx | 24 ++++++++++++++
 next-env.d.ts | 5 +++
 package.json | 31 ++++++++++++++++++
 pages/_app.tsx | 21 ++++++++++++
 pages/theme-switcher.tsx | 10 ++++++
 public/icons/dark.svg | 3 +
 public/icons/light.svg | 3 +
 tsconfig.json | 50 ++++++++++++++++++++++++++++++

feat: initial repo


diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..dca0e5e78ef387005253df7ed1c61001adb5d67d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+This is repository with React examples of simple UI components. The repository is based on Next.js and React.js. 
+




diff --git a/components/ThemeButton.tsx b/components/ThemeButton.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..9305fad99551ea002b32b847cac78bb9c1aa2d2a
--- /dev/null
+++ b/components/ThemeButton.tsx
@@ -0,0 +1,45 @@
+import React from 'react';
+import classnames from 'classnames';
+import s from './ThemeSwitcher.module.scss';
+
+const ThemeButton = (
+    {
+        id,
+        name,
+        iconSrc,
+        activeTheme,
+        setTheme
+    }
+) => {
+    return (
+        <button
+            className={
+                classnames({
+                    [s['theme-button']]: true,
+                    [s['theme-button--dark']]:
+                        activeTheme === 'DARK',
+                    [s['theme-button--unactive']]:
+                        activeTheme !== id,
+                })
+            }
+            onClick={
+                () => {
+                    setTheme(id)
+                }
+            }
+        >
+            <img
+                className={classnames({
+                    [s['theme-icon']]: true,
+                    [s['theme-icon--dark']]:
+                        activeTheme === 'DARK'
+                })}
+                src={iconSrc}
+                alt={id}
+            />
+            {name}
+        </button>
+    )
+};
+
+export default ThemeButton;
\ No newline at end of file




diff --git a/components/ThemeSwitcher.module.scss b/components/ThemeSwitcher.module.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e00b432bd34757028dc7ea359612368e741ee8bc
--- /dev/null
+++ b/components/ThemeSwitcher.module.scss
@@ -0,0 +1,48 @@
+.theme-button {
+    background-color: #FFF;
+    color: #464A51;
+    border-radius: 8px;
+    display: flex;
+    align-items: center;
+    width: 125px;
+    height: 50px;
+    border: 0px;
+    padding-left: 16px;
+    cursor: pointer;
+    font-weight: 400;
+    font-size: 22px;
+    transition: 0.5s;
+    box-shadow: 0px 4px 8px #DBE0EE;
+    &--dark {
+        background-color: #464A51;
+        color: #C0C4CA;
+        box-shadow: none;
+    }
+
+    &--unactive {
+        background-color: inherit;
+        box-shadow: none;
+    }
+}
+
+.theme-switcher {
+    padding: 6px;
+    height: 50px;
+    width: 250px;
+    display: flex;
+    gap: 8px;
+    border-radius: 8px;
+    background-color: #E9EDF8;
+    &--dark {
+        background-color: #222126;
+    }
+}
+
+.theme-icon {
+    width: 30px;
+    height: 30px;
+    margin-right: 8px;
+    &--dark {
+        filter: brightness(0) invert(1);
+    }
+}
\ No newline at end of file




diff --git a/components/ThemeSwitcher.tsx b/components/ThemeSwitcher.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..ed844556bb6d75d6a970d409b9849a1a0a96c553
--- /dev/null
+++ b/components/ThemeSwitcher.tsx
@@ -0,0 +1,47 @@
+import React, { useState } from 'react';
+import classnames from 'classnames';
+import s from '@components/ThemeSwitcher.module.scss';
+import ThemeButton from '@components/ThemeButton';
+
+const themes = [
+    {
+        id: 'LIGHT',
+        name: 'Light',
+        iconSrc: '/icons/light.svg'
+    },
+    {
+        id: 'DARK',
+        name: 'Dark',
+        iconSrc: '/icons/dark.svg',
+    }
+];
+
+const ThemeSwitcher = () => {
+    const [activeTheme, setTheme] = useState('LIGHT');
+
+    return <>
+        <span
+            className={
+                classnames({
+                    [s['theme-switcher']]: true,
+                    [s['theme-switcher--dark']]: 
+                        activeTheme === 'DARK'
+                })
+            }
+        >
+            {
+                themes.map((themeButtonProps) => {
+                    return (
+                        <ThemeButton
+                            setTheme={setTheme}
+                            activeTheme={activeTheme}
+                            {...themeButtonProps}
+                        />
+                    )
+                })
+            }
+        </span>
+    </>
+};
+
+export default ThemeSwitcher;
\ No newline at end of file




diff --git a/lib/utils.tsx b/lib/utils.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..20e19ebee518fbb945f844e8090bc631b17f66d9
--- /dev/null
+++ b/lib/utils.tsx
@@ -0,0 +1,24 @@
+export const get = (obj: Record<string, any>, path: string, def?: any): any => {
+    if (obj == null) {
+      return def;
+    }
+    const fullPath = path
+      .replace(/\[/g, '.')
+      .replace(/]/g, '')
+      .split('.')
+      .filter(Boolean);
+  
+    if (obj == null) {
+      return def || null;
+    }
+  
+    function everyFunc(step) {
+      if (obj[step] !== null) {
+        const resultEveryFunc = !(step && (obj = obj[step]) === undefined);
+        return resultEveryFunc;
+      }
+      return null;
+    }
+  
+    return fullPath.every(everyFunc) ? obj : def;
+};
\ No newline at end of file




diff --git a/next-env.d.ts b/next-env.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4f11a03dc6cc37f2b5105c08f2e7b24c603ab2f4
--- /dev/null
+++ b/next-env.d.ts
@@ -0,0 +1,5 @@
+/// <reference types="next" />
+/// <reference types="next/image-types/global" />
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.




diff --git a/package.json b/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..2c71ef51ba2371f4b6fc34c97ac494a88f82654b
--- /dev/null
+++ b/package.json
@@ -0,0 +1,31 @@
+{
+  "name": "react",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "dev": "next dev",
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "classnames": "^2.3.1",
+    "next": "^12.2.3",
+    "react": "^18.2.0",
+    "sass": "^1.54.0"
+  },
+  "devDependencies": {
+    "@types/node": "^18.6.3",
+    "@types/react": "^18.0.15",
+    "eslint": "^8.24.0",
+    "eslint-config-airbnb": "^19.0.4",
+    "eslint-plugin-import": "^2.26.0",
+    "eslint-plugin-jsx-a11y": "^6.6.1",
+    "eslint-plugin-prettier": "^4.2.1",
+    "eslint-plugin-react": "^7.31.8",
+    "eslint-plugin-security": "^1.5.0",
+    "prettier": "^2.7.1",
+    "typescript": "^4.7.4"
+  }
+}




diff --git a/pages/_app.tsx b/pages/_app.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b19db0a476aa6785819da22958607abdc31485de
--- /dev/null
+++ b/pages/_app.tsx
@@ -0,0 +1,21 @@
+import React from 'react';
+import globalStyle from '../components/global.scss';
+
+interface IAppProps {
+  Component: React.FunctionComponent;
+  pageProps: Record<string, unknown>;
+}
+
+const App: React.FunctionComponent<IAppProps> = ({
+  Component,
+  pageProps,
+}: IAppProps) => {
+
+  return (
+    <div className={globalStyle.Global}>
+        <Component {...pageProps} />
+    </div>
+  );
+};
+
+export default App;




diff --git a/pages/theme-switcher.tsx b/pages/theme-switcher.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..16232d4920a7d4cdc1328d6cfc894fedb3ab95a2
--- /dev/null
+++ b/pages/theme-switcher.tsx
@@ -0,0 +1,10 @@
+import React from 'react';
+import ThemeSwitcher from '@components/ThemeSwitcher';
+
+const ThemeSwitcherPage = () => {
+    return <>
+        <ThemeSwitcher />
+    </>
+}
+
+export default ThemeSwitcherPage;
\ No newline at end of file




diff --git a/public/icons/dark.svg b/public/icons/dark.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4d6c15c9c27bfd3a6beccc575d3a082e30f74b59
--- /dev/null
+++ b/public/icons/dark.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
+  <path fill-rule="evenodd" d="M9.528 1.718a.75.75 0 01.162.819A8.97 8.97 0 009 6a9 9 0 009 9 8.97 8.97 0 003.463-.69.75.75 0 01.981.98 10.503 10.503 0 01-9.694 6.46c-5.799 0-10.5-4.701-10.5-10.5 0-4.368 2.667-8.112 6.46-9.694a.75.75 0 01.818.162z" clip-rule="evenodd" />
+</svg>




diff --git a/public/icons/light.svg b/public/icons/light.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8426958b523bbe66b9c9f71078555044d0e25ec3
--- /dev/null
+++ b/public/icons/light.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor" class="w-6 h-6">
+  <path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z" />
+</svg>




diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..5fb9a8b75e8a1fa3543ad8f826c95a237b7d0c3d
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,50 @@
+{
+  "compilerOptions": {
+    "baseUrl": ".",
+    "checkJs": false,
+    "lib": [
+      "dom",
+      "dom.iterable",
+      "esnext"
+    ],
+    "paths": {
+      "@components/*": [
+        "./components/*"
+      ],
+      "@lib/*": [
+        "./lib/*"
+      ],
+      "@assets/*": [
+        "./assets/*"
+      ],
+      "@design-system/*": [
+        "./design-system/*"
+      ]
+    },
+    "typeRoots": [
+      "src/customTypings",
+      "node_modules/@types"
+    ],
+    "allowJs": true,
+    "skipLibCheck": true,
+    "strict": false,
+    "forceConsistentCasingInFileNames": true,
+    "noEmit": true,
+    "incremental": true,
+    "esModuleInterop": true,
+    "module": "esnext",
+    "isolatedModules": true,
+    "jsx": "preserve",
+    "moduleResolution": "node",
+    "resolveJsonModule": true,
+    "target": "es5"
+  },
+  "include": [
+    "next-env.d.ts",
+    "**/*.ts",
+    "**/*.tsx"
+  ],
+  "exclude": [
+    "node_modules"
+  ]
+}