Init
This commit is contained in:
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
121
README.md
Normal file
121
README.md
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
# React + TypeScript + Vite
|
||||||
|
|
||||||
|
# React UI-kit
|
||||||
|
|
||||||
|
## Создание проекта
|
||||||
|
|
||||||
|
```js
|
||||||
|
npm create vite@latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Подключение tailwindcss
|
||||||
|
|
||||||
|
```js
|
||||||
|
npm install tailwindcss postcss autoprefixer
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
npx tailwindcss init -p
|
||||||
|
```
|
||||||
|
|
||||||
|
Отредактируйте **tailwind.config.js**, чтобы включить:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: ["./src/**/*.{js,jsx,ts,tsx}"],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
src/index.css
|
||||||
|
|
||||||
|
```css
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Оптимизация настроек Tailwind для производства
|
||||||
|
|
||||||
|
Tailwind позволяет вам удалить все неиспользуемые CSS, чтобы вы могли отправлять свой проект без каких-либо дополнительных наворотов.
|
||||||
|
|
||||||
|
Чтобы настроить это, отредактируйте свой **postcss.config.js** с помощью:
|
||||||
|
|
||||||
|
```js
|
||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
...(process.env.NODE_ENV === "production"
|
||||||
|
? {
|
||||||
|
cssnano: {},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
# Добавление темной темы
|
||||||
|
|
||||||
|
## Добавление различного представления цветов
|
||||||
|
|
||||||
|
Создаем файл **./src/styles/palette/theme-[тип темы].css** добавляем переменные палитры
|
||||||
|
|
||||||
|
```css
|
||||||
|
@import 'tailwindcss/base';
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root[data-theme~="dark"] {
|
||||||
|
--color-primary: #43ee00;
|
||||||
|
--color-primary-100: #cce3fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
и для базового типа
|
||||||
|
```css
|
||||||
|
@import 'tailwindcss/base';
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
--color-primary: #006FEE;
|
||||||
|
--color-primary-100: #cce3fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Далее добавляем файл **./src/config/colors.ts**
|
||||||
|
Далее этот объект будет разименован в theme.extend.colors
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
primary: {
|
||||||
|
DEFAULT: "var(--color-primary)",
|
||||||
|
100: "var(--color-primary-100)",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
В файле tailwind.config.js добавляем следующий фрагмент
|
||||||
|
```js
|
||||||
|
import customColors from "./src/config/colors.ts";
|
||||||
|
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
export default {
|
||||||
|
darkMode: "data-theme",
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
...customColors,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
28
eslint.config.js
Normal file
28
eslint.config.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import js from '@eslint/js'
|
||||||
|
import globals from 'globals'
|
||||||
|
import reactHooks from 'eslint-plugin-react-hooks'
|
||||||
|
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||||
|
import tseslint from 'typescript-eslint'
|
||||||
|
|
||||||
|
export default tseslint.config(
|
||||||
|
{ ignores: ['dist'] },
|
||||||
|
{
|
||||||
|
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
globals: globals.browser,
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
'react-hooks': reactHooks,
|
||||||
|
'react-refresh': reactRefresh,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
...reactHooks.configs.recommended.rules,
|
||||||
|
'react-refresh/only-export-components': [
|
||||||
|
'warn',
|
||||||
|
{ allowConstantExport: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
16
index.html
Normal file
16
index.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vite + React + TS</title>
|
||||||
|
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Source+Code+Pro&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4452
package-lock.json
generated
Normal file
4452
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
39
package.json
Normal file
39
package.json
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"name": "react-kit",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc -b && vite build",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@reduxjs/toolkit": "^2.2.7",
|
||||||
|
"@types/react-redux": "^7.1.33",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"framer-motion": "^11.9.0",
|
||||||
|
"postcss": "^8.4.47",
|
||||||
|
"react": "^18.3.1",
|
||||||
|
"react-dom": "^18.3.1",
|
||||||
|
"react-redux": "^9.1.2",
|
||||||
|
"tailwind-cn": "^1.0.2",
|
||||||
|
"tailwind-merge": "^1.14.0",
|
||||||
|
"tailwindcss": "^3.4.12"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.9.0",
|
||||||
|
"@types/react": "^18.3.3",
|
||||||
|
"@types/react-dom": "^18.3.0",
|
||||||
|
"@vitejs/plugin-react": "^4.3.1",
|
||||||
|
"autoprefixer": "^10.4.20",
|
||||||
|
"eslint": "^9.9.0",
|
||||||
|
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.9",
|
||||||
|
"globals": "^15.9.0",
|
||||||
|
"typescript": "^5.5.3",
|
||||||
|
"typescript-eslint": "^8.0.1",
|
||||||
|
"vite": "^5.4.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export default {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
1
public/vite.svg
Normal file
1
public/vite.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
98
src/App.tsx
Normal file
98
src/App.tsx
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import { PrimaryButton } from "./components/button/PrimaryButton";
|
||||||
|
import { SecondaryButton } from "./components/button/SecondaryButton";
|
||||||
|
import { Checkbox } from "./components/checkbox/Checkbox";
|
||||||
|
import { Input } from "./components/input/Input";
|
||||||
|
import { Switch } from "./components/switch/Switch";
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<div className="flex py-[100px] w-full h-full">
|
||||||
|
<Switch
|
||||||
|
className=" fixed top-0 left-0 z-full"
|
||||||
|
variant="theme"
|
||||||
|
color="secondary"
|
||||||
|
onChange={(state: boolean) => {
|
||||||
|
document.documentElement.setAttribute(
|
||||||
|
"data-theme",
|
||||||
|
state ? "dark" : "light"
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="">
|
||||||
|
<Input
|
||||||
|
id="first_name"
|
||||||
|
label="Фамилия"
|
||||||
|
variant="bordered"
|
||||||
|
//placeholder="test"
|
||||||
|
radius="sm"
|
||||||
|
className="m-2"
|
||||||
|
required
|
||||||
|
onChange={(state: string) => {
|
||||||
|
console.log(state);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
variant="flat"
|
||||||
|
id="given_name"
|
||||||
|
label="Имя"
|
||||||
|
//placeholder="test"
|
||||||
|
radius="sm"
|
||||||
|
className="m-2"
|
||||||
|
required
|
||||||
|
onChange={(state: string) => {
|
||||||
|
console.log(state);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
variant="faded"
|
||||||
|
type="email"
|
||||||
|
label="Почта"
|
||||||
|
radius="sm"
|
||||||
|
className="m-2"
|
||||||
|
required
|
||||||
|
onChange={(state: string) => {
|
||||||
|
console.log(state);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
labelType="in-fixed"
|
||||||
|
type="password"
|
||||||
|
label="Пароль"
|
||||||
|
radius="sm"
|
||||||
|
className="m-2"
|
||||||
|
required
|
||||||
|
onChange={(state: string) => {
|
||||||
|
console.log(state);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Checkbox onChange={() => { }} label="test" color="default" defaultState={true}/>
|
||||||
|
<Checkbox onChange={() => { }} label="test" color="primary" defaultState={true}/>
|
||||||
|
<Checkbox onChange={() => { }} label="test" color="secondary" defaultState={true}/>
|
||||||
|
<Checkbox onChange={() => { }} label="test" color="success" defaultState={true}/>
|
||||||
|
<Checkbox onChange={() => { }} label="test" color="warning" defaultState={true}/>
|
||||||
|
<Checkbox onChange={() => { }} label="test" color="danger" defaultState={true}/>
|
||||||
|
<Switch onChange={() => { }} color="default" defaultState={true}/>
|
||||||
|
<Switch onChange={() => { }} color="primary" defaultState={true}/>
|
||||||
|
<Switch onChange={() => { }} color="secondary" defaultState={true}/>
|
||||||
|
<Switch onChange={() => { }} color="success" defaultState={true}/>
|
||||||
|
<Switch onChange={() => { }} color="warning" defaultState={true}/>
|
||||||
|
<Switch onChange={() => { }} color="danger" defaultState={true}/>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="grid grid-rows-3 grid-cols-2 grid-flow-col">
|
||||||
|
|
||||||
|
<PrimaryButton onClick={() => { }} text="Button" className="m-5" />
|
||||||
|
<PrimaryButton onClick={() => { }} text="Button" className="m-5" />
|
||||||
|
<PrimaryButton onClick={() => { }} text="Button" disabled className="m-5" />
|
||||||
|
<SecondaryButton onClick={() => { }} text="Button" className="m-5" />
|
||||||
|
<SecondaryButton onClick={() => { }} text="Button" className="m-5" />
|
||||||
|
<SecondaryButton onClick={() => { }} text="Button" disabled className="m-5" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="w-full"></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
69
src/components/button/PrimaryButton.tsx
Normal file
69
src/components/button/PrimaryButton.tsx
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { cn } from "../../lib/cn";
|
||||||
|
|
||||||
|
interface ButtonProps {
|
||||||
|
disabled?: boolean;
|
||||||
|
text?: string;
|
||||||
|
className?: string;
|
||||||
|
onClick: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PrimaryButton: React.FC<ButtonProps> = ({
|
||||||
|
disabled = false,
|
||||||
|
text = "",
|
||||||
|
className,
|
||||||
|
onClick,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<label
|
||||||
|
className={cn(
|
||||||
|
"grid relative cursor-pointer select-none group w-fit box-border",
|
||||||
|
disabled && "pointer-events-none",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
onClick={() => onClick()}
|
||||||
|
>
|
||||||
|
{/* Основной контейнер, */}
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"group-active:scale-90 flex items-center justify-center box-border z-10 relative transition-all duration-300",
|
||||||
|
"rounded-[10px]",
|
||||||
|
"group-hover:bg-liquid-lighter group-hover:ring-[1px] group-hover:ring-liquid-darkmain group-hover:ring-inset",
|
||||||
|
"px-[16px] py-[8px]",
|
||||||
|
"bg-liquid-darkmain",
|
||||||
|
disabled && "bg-liquid-lighter"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{/* Скрытый button */}
|
||||||
|
<button
|
||||||
|
className={cn(
|
||||||
|
"absolute opacity-0 -z-10 h-0 w-0",
|
||||||
|
"[&:focus-visible+*]:outline-liquid-brightmain",
|
||||||
|
)}
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={() => {}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Граница при выделении через tab */}
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"absolute outline-offset-[2.5px] border-[2px] border-transparent outline-[2.5px] outline outline-transparent transition-all duration-300 text-transparent box-border text-[18px] font-bold p-0 ,m-0 leading-[23px]",
|
||||||
|
"rounded-[10px]",
|
||||||
|
"px-[16px] py-[8px]",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"transition-all duration-300 text-liquid-white text-[18px] font-bold p-0 m-0 leading-[23px]",
|
||||||
|
"group-hover:text-liquid-brightmain ",
|
||||||
|
disabled && "text-liquid-light"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
};
|
||||||
67
src/components/button/SecondaryButton.tsx
Normal file
67
src/components/button/SecondaryButton.tsx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { cn } from "../../lib/cn";
|
||||||
|
|
||||||
|
interface ButtonProps {
|
||||||
|
disabled?: boolean;
|
||||||
|
text?: string;
|
||||||
|
className?: string;
|
||||||
|
onClick: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SecondaryButton: React.FC<ButtonProps> = ({
|
||||||
|
disabled = false,
|
||||||
|
text = "",
|
||||||
|
className,
|
||||||
|
onClick,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<label
|
||||||
|
className={cn(
|
||||||
|
"grid relative cursor-pointer select-none group w-fit box-border",
|
||||||
|
disabled && "pointer-events-none",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
onClick={() => onClick()}
|
||||||
|
>
|
||||||
|
{/* Основной контейнер, */}
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"group-active:scale-90 flex items-center justify-center box-border z-10 relative transition-all duration-300",
|
||||||
|
"rounded-[10px]",
|
||||||
|
"group-hover:bg-liquid-background",
|
||||||
|
"px-[16px] py-[8px]",
|
||||||
|
"bg-liquid-lighter"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{/* Скрытый button */}
|
||||||
|
<button
|
||||||
|
className={cn(
|
||||||
|
"absolute opacity-0 -z-10 h-0 w-0",
|
||||||
|
"[&:focus-visible+*]:outline-liquid-brightmain",
|
||||||
|
)}
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={() => {}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Граница при выделении через tab */}
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"absolute outline-offset-[2.5px] border-[2px] border-transparent outline-[2.5px] outline outline-transparent transition-all duration-300 text-transparent box-border text-[18px] font-bold p-0 ,m-0 leading-[23px]",
|
||||||
|
"rounded-[10px]",
|
||||||
|
"px-[16px] py-[8px]",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"transition-all duration-300 text-liquid-white text-[18px] font-bold p-0 m-0 leading-[23px]",
|
||||||
|
disabled && "text-liquid-light"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
};
|
||||||
157
src/components/checkbox/Checkbox.tsx
Normal file
157
src/components/checkbox/Checkbox.tsx
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { cn } from "../../lib/cn";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
|
||||||
|
const pathVariants = {
|
||||||
|
hidden: {
|
||||||
|
opacity: 0,
|
||||||
|
pathLength: 0,
|
||||||
|
},
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
pathLength: 1,
|
||||||
|
transition: {
|
||||||
|
delay: 0.15,
|
||||||
|
duration: 0.4,
|
||||||
|
ease: "easeInOut",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const sizeVariants = {
|
||||||
|
sm: "h-4 w-4",
|
||||||
|
md: "h-5 w-5",
|
||||||
|
lg: "h-6 w-6",
|
||||||
|
};
|
||||||
|
|
||||||
|
const colorsVariants = {
|
||||||
|
default: "bg-default",
|
||||||
|
primary: "bg-liquid-brightmain",
|
||||||
|
secondary: "bg-liquid-darkmain",
|
||||||
|
success: "bg-liquid-green",
|
||||||
|
warning: "bg-liquid-orange",
|
||||||
|
danger: "bg-liquid-red",
|
||||||
|
};
|
||||||
|
|
||||||
|
const focuseOutlineVariants = {
|
||||||
|
default: "[&:focus-visible+*]:outline-default",
|
||||||
|
primary: "[&:focus-visible+*]:outline-liquid-brightmain",
|
||||||
|
secondary: "[&:focus-visible+*]:outline-liquid-darkmain",
|
||||||
|
success: "[&:focus-visible+*]:outline-liquid-green",
|
||||||
|
warning: "[&:focus-visible+*]:outline-liquid-orange",
|
||||||
|
danger: "[&:focus-visible+*]:outline-liquid-red",
|
||||||
|
};
|
||||||
|
|
||||||
|
const radiusVraiants = {
|
||||||
|
none: "",
|
||||||
|
sm: "rounded-[3.5px]",
|
||||||
|
md: "rounded-[5px]",
|
||||||
|
lg: "rounded-[7px]",
|
||||||
|
full: "rounded-full",
|
||||||
|
};
|
||||||
|
|
||||||
|
interface CheckboxProps {
|
||||||
|
size?: "sm" | "md" | "lg";
|
||||||
|
radius?: "none" | "sm" | "md" | "lg" | "full";
|
||||||
|
disabled?: boolean;
|
||||||
|
color?:
|
||||||
|
| "default"
|
||||||
|
| "primary"
|
||||||
|
| "secondary"
|
||||||
|
| "success"
|
||||||
|
| "warning"
|
||||||
|
| "danger";
|
||||||
|
label?: string;
|
||||||
|
variant?: "default" | "label";
|
||||||
|
className?: string;
|
||||||
|
defaultState?: boolean;
|
||||||
|
onChange: (state: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Checkbox: React.FC<CheckboxProps> = ({
|
||||||
|
size = "md",
|
||||||
|
radius = "md",
|
||||||
|
disabled = false,
|
||||||
|
color = "primary",
|
||||||
|
label = "",
|
||||||
|
variant = "label",
|
||||||
|
className,
|
||||||
|
onChange,
|
||||||
|
defaultState = false,
|
||||||
|
}) => {
|
||||||
|
const [active, setActive] = React.useState<boolean>(defaultState);
|
||||||
|
|
||||||
|
React.useEffect(() => onChange(active), [active]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<motion.label
|
||||||
|
className={cn(
|
||||||
|
variant == "label" && "grid-cols-[auto_1fr] items-center gap-2",
|
||||||
|
"grid relative cursor-pointer p-2 select-none group ",
|
||||||
|
className,
|
||||||
|
disabled && "pointer-events-none opacity-50",
|
||||||
|
variant == "default" && ""
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"group-hover:bg-default-100 group-active:scale-90 flex items-center justify-center bg-transparent hover:bg-default-100 box-border border-solid border-[2px] border-default z-10 relative transition-all duration-300",
|
||||||
|
sizeVariants[size],
|
||||||
|
radiusVraiants[radius]
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className={cn(
|
||||||
|
"absolute opacity-0 -z-10 h-0 w-0",
|
||||||
|
focuseOutlineVariants[color]
|
||||||
|
)}
|
||||||
|
disabled={disabled}
|
||||||
|
type="checkbox"
|
||||||
|
onChange={() => {
|
||||||
|
setActive(!active);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"absolute outline-offset-[2.5px] outline-[2.5px] outline outline-transparent transition-all duration-200",
|
||||||
|
sizeVariants[size],
|
||||||
|
radiusVraiants[radius]
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
<span
|
||||||
|
className={cn(
|
||||||
|
"absolute transition-all duration-300",
|
||||||
|
sizeVariants[size],
|
||||||
|
colorsVariants[color],
|
||||||
|
radiusVraiants[radius],
|
||||||
|
active && "opacity-100 scale-100",
|
||||||
|
!active && "opacity-0 scale-0"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
{active && (
|
||||||
|
<motion.path
|
||||||
|
strokeWidth="1.5"
|
||||||
|
d="M5 8.22L7.66571 10.44L11.22 6"
|
||||||
|
stroke="white"
|
||||||
|
strokeLinecap="round"
|
||||||
|
variants={pathVariants}
|
||||||
|
initial="hidden"
|
||||||
|
animate="visible"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{variant == "label" && (
|
||||||
|
<div className="select-none text-layout-foeground transition-all duration-200">
|
||||||
|
{label}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</motion.label>
|
||||||
|
);
|
||||||
|
};
|
||||||
142
src/components/input/Input.tsx
Normal file
142
src/components/input/Input.tsx
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { cn } from "../../lib/cn";
|
||||||
|
|
||||||
|
/* Варианты для скользящего шарика */
|
||||||
|
const inputVariants = {
|
||||||
|
size: {
|
||||||
|
sm: "h-[3rem] w-[27rem]",
|
||||||
|
md: "h-[3.5rem] w-[27rem]",
|
||||||
|
lg: "h-[4rem] w-[27rem]",
|
||||||
|
},
|
||||||
|
colors: {
|
||||||
|
default: "text-default-600 bg-default-200 placeholder-default-600",
|
||||||
|
primary: "text-liquid-brightmain bg-liquid-brightmain placeholder-liquid-brightmain",
|
||||||
|
secondary: "text-secondary bg-secondary-100 placeholder-secondary",
|
||||||
|
success: "text-success bg-success-100 placeholder-success",
|
||||||
|
warning: "text-warning bg-warning-100 placeholder-warning",
|
||||||
|
danger: "text-danger bg-danger-100 placeholder-danger",
|
||||||
|
},
|
||||||
|
radius: {
|
||||||
|
none: "rounded-none",
|
||||||
|
sm: "rounded-[8px]",
|
||||||
|
md: "rounded-[12px]",
|
||||||
|
lg: "rounded-[16px]",
|
||||||
|
full: "rounded-full",
|
||||||
|
},
|
||||||
|
colorsHovered: {
|
||||||
|
default: "focus:bg-default-200 hover:bg-default-300",
|
||||||
|
primary: "focus:bg-liquid-brightmain hover:bg-liquid-brightmain",
|
||||||
|
secondary: "focus:bg-secondary-100 hover:bg-secondary-200",
|
||||||
|
success: "focus:bg-success-100 hover:bg-success-200",
|
||||||
|
warning: "focus:bg-warning-100 hover:bg-warning-200",
|
||||||
|
danger: "focus:bg-danger-100 hover:bg-danger-200",
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
default: "text-default-600",
|
||||||
|
primary: "text-liquid-brightmain",
|
||||||
|
secondary: "text-secondary",
|
||||||
|
success: "text-success",
|
||||||
|
warning: "text-warning",
|
||||||
|
danger: "text-dange",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
interface SwitchProps {
|
||||||
|
size?: "sm" | "md" | "lg";
|
||||||
|
radius?: "sm" | "md" | "lg" | "none" | "full";
|
||||||
|
disabled?: boolean;
|
||||||
|
placeholder?: string;
|
||||||
|
type?: "text" | "email" | "password" | "first_name";
|
||||||
|
color?:
|
||||||
|
| "default"
|
||||||
|
| "primary"
|
||||||
|
| "secondary"
|
||||||
|
| "success"
|
||||||
|
| "warning"
|
||||||
|
| "danger";
|
||||||
|
id?: string;
|
||||||
|
required?: boolean;
|
||||||
|
label?: string;
|
||||||
|
labelType?: "none" | "in" | "out" | "left" | "in-fixed" | "out-fixed";
|
||||||
|
variant?: "flat" | "faded" | "bordered" | "underlined";
|
||||||
|
className?: string;
|
||||||
|
defaultState?: string;
|
||||||
|
onChange: (state: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Input: React.FC<SwitchProps> = ({
|
||||||
|
size = "sm",
|
||||||
|
// radius = "md",
|
||||||
|
type = "text",
|
||||||
|
id = "",
|
||||||
|
disabled = false,
|
||||||
|
required = false,
|
||||||
|
// color = "default",
|
||||||
|
label = "",
|
||||||
|
labelType = "in",
|
||||||
|
placeholder = "",
|
||||||
|
variant = "flat",
|
||||||
|
className,
|
||||||
|
onChange,
|
||||||
|
defaultState = "",
|
||||||
|
}) => {
|
||||||
|
const [value, setValue] = React.useState<string>(defaultState);
|
||||||
|
|
||||||
|
React.useEffect(() => onChange(value), [value]);
|
||||||
|
|
||||||
|
if (labelType == "in" || labelType == "in-fixed")
|
||||||
|
return (
|
||||||
|
<label
|
||||||
|
className={cn(
|
||||||
|
"grid relative select-none group cursor-text overflow-hidden",
|
||||||
|
disabled && "pointer-events-none opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{/* Основной контейнер, */}
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"box-border z-10 relative transition-all duration-300 h-fit flex items-center px-3 rounded-[12px] overflow-hidden ",
|
||||||
|
inputVariants.size[size],
|
||||||
|
variant == "flat" &&
|
||||||
|
"group-hover:bg-default-300 group-focus-within:bg-default-300 bg-default-200",
|
||||||
|
variant == "faded" &&
|
||||||
|
"group-hover:bg-default-300 group-focus-within:bg-default-300 bg-default-200 border-[2px] border-default-300 group-focus-within:border-default group-hover:border-default",
|
||||||
|
variant == "bordered" &&
|
||||||
|
"border-[2px] border-default-300 group-focus-within:border-default group-hover:border-default"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
id={type == "password" ? type : id}
|
||||||
|
type={type}
|
||||||
|
className={cn(
|
||||||
|
"outline outline-transparent transition-all duration-300 bg-transparent absolute left-0 bottom-0 placeholder-default-500 text-layout-foreground w-full px-3 pt-[10px] h-full",
|
||||||
|
placeholder == "" && value == ""
|
||||||
|
? "opacity-0 focus:opacity-100"
|
||||||
|
: " [&:-webkit-autofill+*]:text-white"
|
||||||
|
)}
|
||||||
|
value={value}
|
||||||
|
placeholder={placeholder}
|
||||||
|
disabled={disabled}
|
||||||
|
onChange={(e) => {
|
||||||
|
setValue(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"absolute text-default-600 transition-all duration-300 my-[2px]",
|
||||||
|
placeholder == "" && value == "" && labelType != "in-fixed"
|
||||||
|
? "top-[20%] text-[16px] group-focus-within:top-0 group-focus-within:text-[12px] group-focus-within:text-default-700"
|
||||||
|
: "top-0 text-[12px] text-default-700"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
{required && <span className="text-danger m-[2px]">*</span>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
};
|
||||||
187
src/components/switch/Switch.tsx
Normal file
187
src/components/switch/Switch.tsx
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { cn } from "../../lib/cn";
|
||||||
|
|
||||||
|
/* Варианты размера контейнера */
|
||||||
|
const sizeVariants = {
|
||||||
|
sm: "h-6 w-10",
|
||||||
|
md: "h-7 w-12",
|
||||||
|
lg: "h-8 w-14",
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Варианты для скользящего шарика */
|
||||||
|
const switchVariants = {
|
||||||
|
size: {
|
||||||
|
sm: "h-4 w-4",
|
||||||
|
md: "h-5 w-5",
|
||||||
|
lg: "h-6 w-6",
|
||||||
|
},
|
||||||
|
activeSize: {
|
||||||
|
sm: "group-active:w-5",
|
||||||
|
md: "group-active:w-6",
|
||||||
|
lg: "group-active:w-7",
|
||||||
|
},
|
||||||
|
iconSize: {
|
||||||
|
sm: "h-3 w-3",
|
||||||
|
md: "h-[0.875rem] w-[0.875rem]",
|
||||||
|
lg: "h-4 w-4",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const colorsVariants = {
|
||||||
|
default: "bg-default",
|
||||||
|
primary: "bg-liquid-brightmain",
|
||||||
|
secondary: "bg-liquid-darkmain",
|
||||||
|
success: "bg-liquid-green",
|
||||||
|
warning: "bg-liquid-orange",
|
||||||
|
danger: "bg-liquid-red",
|
||||||
|
};
|
||||||
|
|
||||||
|
const focuseOutlineVariants = {
|
||||||
|
default: "[&:focus-visible+*]:outline-default",
|
||||||
|
primary: "[&:focus-visible+*]:outline-liquid-brightmain",
|
||||||
|
secondary: "[&:focus-visible+*]:outline-liquid-darkmain",
|
||||||
|
success: "[&:focus-visible+*]:outline-liquid-green",
|
||||||
|
warning: "[&:focus-visible+*]:outline-liquid-orange",
|
||||||
|
danger: "[&:focus-visible+*]:outline-liquid-red",
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Иконка солнца
|
||||||
|
*/
|
||||||
|
const sun = (
|
||||||
|
<svg viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M6 9.5C7.933 9.5 9.5 7.933 9.5 6C9.5 4.067 7.933 2.5 6 2.5C4.067 2.5 2.5 4.067 2.5 6C2.5 7.933 4.067 9.5 6 9.5Z"
|
||||||
|
fill="#292D32"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M6 11.48C5.725 11.48 5.5 11.275 5.5 11V10.96C5.5 10.685 5.725 10.46 6 10.46C6.275 10.46 6.5 10.685 6.5 10.96C6.5 11.235 6.275 11.48 6 11.48ZM9.57 10.07C9.44 10.07 9.315 10.02 9.215 9.925L9.15 9.86C8.955 9.665 8.955 9.35 9.15 9.155C9.345 8.96 9.66 8.96 9.855 9.155L9.92 9.22C10.115 9.415 10.115 9.73 9.92 9.925C9.825 10.02 9.7 10.07 9.57 10.07ZM2.43 10.07C2.3 10.07 2.175 10.02 2.075 9.925C1.88 9.73 1.88 9.415 2.075 9.22L2.14 9.155C2.335 8.96 2.65 8.96 2.845 9.155C3.04 9.35 3.04 9.665 2.845 9.86L2.78 9.925C2.685 10.02 2.555 10.07 2.43 10.07ZM11 6.5H10.96C10.685 6.5 10.46 6.275 10.46 6C10.46 5.725 10.685 5.5 10.96 5.5C11.235 5.5 11.48 5.725 11.48 6C11.48 6.275 11.275 6.5 11 6.5ZM1.04 6.5H1C0.725 6.5 0.5 6.275 0.5 6C0.5 5.725 0.725 5.5 1 5.5C1.275 5.5 1.52 5.725 1.52 6C1.52 6.275 1.315 6.5 1.04 6.5ZM9.505 2.995C9.375 2.995 9.25 2.945 9.15 2.85C8.955 2.655 8.955 2.34 9.15 2.145L9.215 2.08C9.41 1.885 9.725 1.885 9.92 2.08C10.115 2.275 10.115 2.59 9.92 2.785L9.855 2.85C9.76 2.945 9.635 2.995 9.505 2.995ZM2.495 2.995C2.365 2.995 2.24 2.945 2.14 2.85L2.075 2.78C1.88 2.585 1.88 2.27 2.075 2.075C2.27 1.88 2.585 1.88 2.78 2.075L2.845 2.14C3.04 2.335 3.04 2.65 2.845 2.845C2.75 2.945 2.62 2.995 2.495 2.995ZM6 1.52C5.725 1.52 5.5 1.315 5.5 1.04V1C5.5 0.725 5.725 0.5 6 0.5C6.275 0.5 6.5 0.725 6.5 1C6.5 1.275 6.275 1.52 6 1.52Z"
|
||||||
|
fill="#292D32"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Иконка луны
|
||||||
|
*/
|
||||||
|
const moon = (
|
||||||
|
<svg viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M10.765 7.965C10.685 7.83 10.46 7.62 9.89999 7.72C9.58999 7.775 9.27499 7.8 8.95999 7.785C7.79499 7.735 6.73999 7.2 6.00499 6.375C5.35499 5.65 4.95499 4.705 4.94999 3.685C4.94999 3.115 5.05999 2.565 5.28499 2.045C5.50499 1.54 5.34999 1.275 5.23999 1.165C5.12499 1.05 4.85499 0.890001 4.32499 1.11C2.27999 1.97 1.01499 4.02 1.16499 6.215C1.31499 8.28 2.76499 10.045 4.68499 10.71C5.14499 10.87 5.62999 10.965 6.12999 10.985C6.20999 10.99 6.28999 10.995 6.36999 10.995C8.04499 10.995 9.61499 10.205 10.605 8.86C10.94 8.395 10.85 8.1 10.765 7.965Z"
|
||||||
|
fill="#292D32"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
interface SwitchProps {
|
||||||
|
size?: "sm" | "md" | "lg";
|
||||||
|
disabled?: boolean;
|
||||||
|
color?:
|
||||||
|
| "default"
|
||||||
|
| "primary"
|
||||||
|
| "secondary"
|
||||||
|
| "success"
|
||||||
|
| "warning"
|
||||||
|
| "danger";
|
||||||
|
label?: string;
|
||||||
|
variant?: "default" | "label" | "icon" | "theme";
|
||||||
|
className?: string;
|
||||||
|
defaultState?: boolean;
|
||||||
|
onChange: (state: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Switch: React.FC<SwitchProps> = ({
|
||||||
|
size = "sm",
|
||||||
|
disabled = false,
|
||||||
|
color = "primary",
|
||||||
|
label = "",
|
||||||
|
variant = "default",
|
||||||
|
className,
|
||||||
|
onChange,
|
||||||
|
defaultState = false,
|
||||||
|
}) => {
|
||||||
|
const [active, setActive] = React.useState<boolean>(defaultState);
|
||||||
|
|
||||||
|
React.useEffect(() => onChange(active), [active]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<label
|
||||||
|
className={cn(
|
||||||
|
variant == "label" && "grid-cols-[auto_1fr] items-center gap-2",
|
||||||
|
"grid relative cursor-pointer p-2 select-none group",
|
||||||
|
disabled && "pointer-events-none opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{/* Основной контейнер, */}
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
" flex items-center justify-center box-border z-10 relative transition-all duration-300 rounded-full",
|
||||||
|
sizeVariants[size],
|
||||||
|
active ? colorsVariants[color] : "bg-default-200"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{/* Скрытый checkbox */}
|
||||||
|
<input
|
||||||
|
className={cn(
|
||||||
|
"absolute opacity-0 -z-10 h-0 w-0",
|
||||||
|
focuseOutlineVariants[color]
|
||||||
|
)}
|
||||||
|
disabled={disabled}
|
||||||
|
type="checkbox"
|
||||||
|
onChange={() => {
|
||||||
|
setActive(!active);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"absolute outline-offset-[2.5px] outline-[2.5px] outline outline-transparent transition-all duration-300 rounded-full",
|
||||||
|
sizeVariants[size]
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
|
||||||
|
{/* Шарик */}
|
||||||
|
<span
|
||||||
|
className={cn(
|
||||||
|
"bg-white rounded-full absolute transition-all duration-300 m-1 flex items-center justify-center",
|
||||||
|
switchVariants.size[size],
|
||||||
|
switchVariants.activeSize[size],
|
||||||
|
active
|
||||||
|
? "right-[0%]"
|
||||||
|
: "right-[calc(50%-0.25rem)] group-active:right-[calc(50%-0.5rem)]"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{variant == "theme" && (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"absolute transition-all duration-300",
|
||||||
|
switchVariants.iconSize[size],
|
||||||
|
active ? "opacity-100 scale-100" : "opacity-0 scale-50"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{moon}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"absolute transition-all duration-300",
|
||||||
|
switchVariants.iconSize[size],
|
||||||
|
active ? "opacity-0 scale-50" : "opacity-100 scale-100"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{sun}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{variant == "label" && (
|
||||||
|
<div className="select-none text-layout-foreground transition-all duration-200">
|
||||||
|
{label}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
};
|
||||||
14
src/config/colors.ts
Normal file
14
src/config/colors.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
export default {
|
||||||
|
liquid: {
|
||||||
|
brightmain: "var(--color-liquid-brightmain)",
|
||||||
|
darkmain: "var(--color-liquid-darkmain)",
|
||||||
|
darker: "var(--color-liquid-darker)",
|
||||||
|
background: "var(--color-liquid-background)",
|
||||||
|
lighter: "var(--color-liquid-lighter)",
|
||||||
|
white: "var(--color-liquid-white)",
|
||||||
|
red: "var(--color-liquid-red)",
|
||||||
|
green: "var(--color-liquid-green)",
|
||||||
|
light: "var(--color-liquid-light)",
|
||||||
|
orange: "var(--color-liquid-orange)",
|
||||||
|
}
|
||||||
|
};
|
||||||
6
src/lib/cn.ts
Normal file
6
src/lib/cn.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { ClassValue, clsx } from "clsx";
|
||||||
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs));
|
||||||
|
}
|
||||||
12
src/main.tsx
Normal file
12
src/main.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { StrictMode } from "react";
|
||||||
|
import { createRoot } from "react-dom/client";
|
||||||
|
import App from "./App.tsx";
|
||||||
|
import "./styles/index.css";
|
||||||
|
import "./styles/palette/theme-dark.css";
|
||||||
|
import "./styles/palette/theme-light.css";
|
||||||
|
|
||||||
|
createRoot(document.getElementById("root")!).render(
|
||||||
|
<StrictMode>
|
||||||
|
<App />
|
||||||
|
</StrictMode>
|
||||||
|
);
|
||||||
15
src/redux/store.ts
Normal file
15
src/redux/store.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { configureStore } from "@reduxjs/toolkit";
|
||||||
|
//import { userReducer } from "./slices/user";
|
||||||
|
|
||||||
|
//import { useDispatch } from "react-redux";
|
||||||
|
//const dispatch = useDispatch();
|
||||||
|
//dispatch(loginUser({ login: "123", password: "pas" }));
|
||||||
|
// useSelector((state: any) => state.user.isAuthorized.status);
|
||||||
|
|
||||||
|
const store = configureStore({
|
||||||
|
reducer: {
|
||||||
|
//user: userReducer,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default store;
|
||||||
37
src/styles/index.css
Normal file
37
src/styles/index.css
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
@import 'tailwindcss/base';
|
||||||
|
@import 'tailwindcss/components';
|
||||||
|
@import 'tailwindcss/utilities';
|
||||||
|
|
||||||
|
* {
|
||||||
|
-webkit-tap-highlight-color: transparent; /* Отключаем выделение синим при тапе на телефоне*/
|
||||||
|
/* outline: 1px solid green; */
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
color-scheme: light dark;
|
||||||
|
width: 100%;
|
||||||
|
height: 100svh;
|
||||||
|
/* @apply bg-layout-background; */
|
||||||
|
transition: all linear 200ms;
|
||||||
|
|
||||||
|
font-family: 'Source Code Pro', monospace;
|
||||||
|
|
||||||
|
/* font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; */
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: rgba(255, 255, 255, 0.87);
|
||||||
|
}
|
||||||
|
|
||||||
|
#root {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
16
src/styles/palette/theme-dark.css
Normal file
16
src/styles/palette/theme-dark.css
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
@import 'tailwindcss/base';
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root[data-theme~="dark"] {
|
||||||
|
--color-liquid-brightmain: #00DBD9;
|
||||||
|
--color-liquid-darkmain: #075867;
|
||||||
|
--color-liquid-darker: #141515;
|
||||||
|
--color-liquid-background: #202222;
|
||||||
|
--color-liquid-lighter: #2A2E2F;
|
||||||
|
--color-liquid-white: #EDF6F7;
|
||||||
|
--color-liquid-red: #F13E5F;
|
||||||
|
--color-liquid-green: #10BE59;
|
||||||
|
--color-liquid-light: #576466;
|
||||||
|
--color-liquid-orange: #FF951B;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/styles/palette/theme-light.css
Normal file
16
src/styles/palette/theme-light.css
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
@import 'tailwindcss/base';
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
--color-liquid-brightmain: #00DBD9;
|
||||||
|
--color-liquid-darkmain: #075867;
|
||||||
|
--color-liquid-darker: #141515;
|
||||||
|
--color-liquid-background: #202222;
|
||||||
|
--color-liquid-lighter: #2A2E2F;
|
||||||
|
--color-liquid-white: #EDF6F7;
|
||||||
|
--color-liquid-red: #F13E5F;
|
||||||
|
--color-liquid-green: #10BE59;
|
||||||
|
--color-liquid-light: #576466;
|
||||||
|
--color-liquid-orange: #FF951B;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/vite-env.d.ts
vendored
Normal file
1
src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
15
tailwind.config.js
Normal file
15
tailwind.config.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import customColors from "./src/config/colors.ts";
|
||||||
|
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
export default {
|
||||||
|
darkMode: "data-theme",
|
||||||
|
content: ["./src/**/*.{js,jsx,ts,tsx}"],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
...customColors,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
||||||
24
tsconfig.app.json
Normal file
24
tsconfig.app.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
||||||
1
tsconfig.app.tsbuildinfo
Normal file
1
tsconfig.app.tsbuildinfo
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"root":["./src/app.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/button/button.tsx","./src/components/checkbox/checkbox.tsx","./src/components/checkbox-group/chexkboxgroup.tsx","./src/components/input/input.tsx","./src/components/switch/switch.tsx","./src/config/colors.ts","./src/lib/cn.ts","./src/redux/store.ts"],"version":"5.6.2"}
|
||||||
7
tsconfig.json
Normal file
7
tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{ "path": "./tsconfig.app.json" },
|
||||||
|
{ "path": "./tsconfig.node.json" }
|
||||||
|
]
|
||||||
|
}
|
||||||
22
tsconfig.node.json
Normal file
22
tsconfig.node.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"lib": ["ES2023"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
1
tsconfig.node.tsbuildinfo
Normal file
1
tsconfig.node.tsbuildinfo
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"root":["./vite.config.ts"],"version":"5.6.2"}
|
||||||
7
vite.config.ts
Normal file
7
vite.config.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user