~/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" + ] +}