mirror of
https://github.com/ershisan99/flashcards-example-project.git
synced 2025-12-16 20:59:27 +00:00
homework 1: components
This commit is contained in:
@@ -14,6 +14,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/roboto": "^5.0.5",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"clsx": "^2.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
|
||||
234
pnpm-lock.yaml
generated
234
pnpm-lock.yaml
generated
@@ -8,6 +8,15 @@ dependencies:
|
||||
'@fontsource/roboto':
|
||||
specifier: ^5.0.5
|
||||
version: 5.0.5
|
||||
'@radix-ui/react-checkbox':
|
||||
specifier: ^1.0.4
|
||||
version: 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-label':
|
||||
specifier: ^2.0.2
|
||||
version: 2.0.2(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0)
|
||||
clsx:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
react:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0
|
||||
@@ -1396,7 +1405,6 @@ packages:
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
regenerator-runtime: 0.13.11
|
||||
dev: true
|
||||
|
||||
/@babel/template@7.22.5:
|
||||
resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==}
|
||||
@@ -1979,6 +1987,219 @@ packages:
|
||||
tslib: 2.6.1
|
||||
dev: true
|
||||
|
||||
/@radix-ui/primitive@1.0.1:
|
||||
resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-checkbox@1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@radix-ui/primitive': 1.0.1
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.15)(react@18.2.0)
|
||||
'@radix-ui/react-context': 1.0.1(@types/react@18.2.15)(react@18.2.0)
|
||||
'@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.15)(react@18.2.0)
|
||||
'@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.15)(react@18.2.0)
|
||||
'@radix-ui/react-use-size': 1.0.1(@types/react@18.2.15)(react@18.2.0)
|
||||
'@types/react': 18.2.15
|
||||
'@types/react-dom': 18.2.7
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.15)(react@18.2.0):
|
||||
resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@types/react': 18.2.15
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-context@1.0.1(@types/react@18.2.15)(react@18.2.0):
|
||||
resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@types/react': 18.2.15
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-label@2.0.2(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@types/react': 18.2.15
|
||||
'@types/react-dom': 18.2.7
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.15)(react@18.2.0)
|
||||
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.15)(react@18.2.0)
|
||||
'@types/react': 18.2.15
|
||||
'@types/react-dom': 18.2.7
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.15)(react@18.2.0)
|
||||
'@types/react': 18.2.15
|
||||
'@types/react-dom': 18.2.7
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-slot@1.0.2(@types/react@18.2.15)(react@18.2.0):
|
||||
resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.15)(react@18.2.0)
|
||||
'@types/react': 18.2.15
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.15)(react@18.2.0):
|
||||
resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@types/react': 18.2.15
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.15)(react@18.2.0):
|
||||
resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.15)(react@18.2.0)
|
||||
'@types/react': 18.2.15
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.15)(react@18.2.0):
|
||||
resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@types/react': 18.2.15
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-previous@1.0.1(@types/react@18.2.15)(react@18.2.0):
|
||||
resolution: {integrity: sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@types/react': 18.2.15
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-size@1.0.1(@types/react@18.2.15)(react@18.2.0):
|
||||
resolution: {integrity: sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.22.6
|
||||
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.15)(react@18.2.0)
|
||||
'@types/react': 18.2.15
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@rollup/pluginutils@5.0.2:
|
||||
resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
@@ -3109,7 +3330,6 @@ packages:
|
||||
|
||||
/@types/prop-types@15.7.5:
|
||||
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
|
||||
dev: true
|
||||
|
||||
/@types/qs@6.9.7:
|
||||
resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==}
|
||||
@@ -3123,7 +3343,6 @@ packages:
|
||||
resolution: {integrity: sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==}
|
||||
dependencies:
|
||||
'@types/react': 18.2.15
|
||||
dev: true
|
||||
|
||||
/@types/react@18.2.15:
|
||||
resolution: {integrity: sha512-oEjE7TQt1fFTFSbf8kkNuc798ahTUzn3Le67/PWjE8MAfYAD/qB7O8hSTcromLFqHCt9bcdOg5GXMokzTjJ5SA==}
|
||||
@@ -3131,11 +3350,9 @@ packages:
|
||||
'@types/prop-types': 15.7.5
|
||||
'@types/scheduler': 0.16.3
|
||||
csstype: 3.1.2
|
||||
dev: true
|
||||
|
||||
/@types/scheduler@0.16.3:
|
||||
resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==}
|
||||
dev: true
|
||||
|
||||
/@types/semver@7.5.0:
|
||||
resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==}
|
||||
@@ -4046,6 +4263,11 @@ packages:
|
||||
engines: {node: '>=0.8'}
|
||||
dev: true
|
||||
|
||||
/clsx@2.0.0:
|
||||
resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==}
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/color-convert@1.9.3:
|
||||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
||||
dependencies:
|
||||
@@ -4215,7 +4437,6 @@ packages:
|
||||
|
||||
/csstype@3.1.2:
|
||||
resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
|
||||
dev: true
|
||||
|
||||
/debug@2.6.9:
|
||||
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
||||
@@ -7459,7 +7680,6 @@ packages:
|
||||
|
||||
/regenerator-runtime@0.13.11:
|
||||
resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
|
||||
dev: true
|
||||
|
||||
/regenerator-transform@0.15.1:
|
||||
resolution: {integrity: sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==}
|
||||
|
||||
21
src/assets/icons/camera.tsx
Normal file
21
src/assets/icons/camera.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { SVGProps, Ref, forwardRef, memo } from 'react'
|
||||
const SvgComponent = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) => (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={32} height={32} fill="none" ref={ref} {...props}>
|
||||
<circle cx={16} cy={16} r={15.5} fill="gray" stroke="#fff" />
|
||||
<path
|
||||
fill="#fff"
|
||||
fillRule="evenodd"
|
||||
d="M16 18.84a2.49 2.49 0 1 0 0-4.97 2.49 2.49 0 0 0 0 4.97Zm0-.62a1.87 1.87 0 1 0 0-3.73 1.87 1.87 0 0 0 0 3.73Z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
<path
|
||||
fill="#fff"
|
||||
fillRule="evenodd"
|
||||
d="M19 11.38a3.86 3.86 0 0 0-3.02-1.25c-1.59 0-2.28.56-3.02 1.25H10.4c-1.03 0-1.87.83-1.87 1.86v6.23c0 1.03.84 1.86 1.87 1.86h11.2c1.03 0 1.87-.83 1.87-1.86v-6.23c0-1.03-.84-1.86-1.87-1.86H19Zm-.25.62-.06-.06-.18-.17a5.4 5.4 0 0 0-.67-.53 3.15 3.15 0 0 0-1.86-.48c-.92 0-1.44.2-1.87.48a5.4 5.4 0 0 0-.66.53l-.18.17-.07.06h-2.8c-.69 0-1.24.56-1.24 1.24v6.23c0 .68.55 1.24 1.24 1.24h11.2c.69 0 1.24-.56 1.24-1.24v-6.23c0-.68-.55-1.24-1.24-1.24h-2.85Z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
const ForwardRef = forwardRef(SvgComponent)
|
||||
|
||||
export default memo(ForwardRef)
|
||||
20
src/assets/icons/check.tsx
Normal file
20
src/assets/icons/check.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { SVGProps, Ref, forwardRef, memo } from 'react'
|
||||
const SvgComponent = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) => (
|
||||
<svg
|
||||
width={18}
|
||||
height={18}
|
||||
viewBox="0 0 18 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M16 0H2a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V2a2 2 0 00-2-2zM7 14L2 9l1.41-1.41L7 11.17l7.59-7.59L16 5l-9 9z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
const ForwardRef = forwardRef(SvgComponent)
|
||||
|
||||
export default memo(ForwardRef)
|
||||
28
src/assets/icons/chevron-up.tsx
Normal file
28
src/assets/icons/chevron-up.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { SVGProps, Ref, forwardRef, memo } from 'react'
|
||||
const ChevronUp = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) => (
|
||||
<svg
|
||||
width={12}
|
||||
height={12}
|
||||
viewBox="0 0 12 12"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<g clipPath="url(#clip0_9209_3250)">
|
||||
<path
|
||||
d="M9.77084 7.25705C9.77107 7.37388 9.73039 7.4871 9.65584 7.57705C9.61387 7.62768 9.56232 7.66953 9.50415 7.70021C9.44597 7.73089 9.38232 7.74978 9.31683 7.75582C9.25134 7.76186 9.18531 7.75492 9.1225 7.7354C9.0597 7.71588 9.00137 7.68416 8.95084 7.64205L6.27084 5.40205L3.58584 7.56205C3.5347 7.60359 3.47585 7.6346 3.41268 7.65332C3.34951 7.67203 3.28327 7.67808 3.21775 7.67111C3.15224 7.66414 3.08875 7.64429 3.03093 7.61271C2.97311 7.58112 2.92211 7.53842 2.88084 7.48705C2.83533 7.43532 2.80099 7.37474 2.78 7.30911C2.759 7.24348 2.7518 7.17421 2.75884 7.10567C2.76589 7.03712 2.78702 6.97077 2.82092 6.91078C2.85482 6.85079 2.90076 6.79845 2.95584 6.75705L5.95584 4.34205C6.04531 4.26851 6.15753 4.22831 6.27334 4.22831C6.38916 4.22831 6.50138 4.26851 6.59084 4.34205L9.59084 6.84205C9.65135 6.89221 9.69918 6.95593 9.73046 7.02803C9.76173 7.10014 9.77557 7.1786 9.77084 7.25705Z"
|
||||
fill="white"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_9209_3250">
|
||||
<rect width={12} height={12} fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
const ForwardRef = forwardRef(ChevronUp)
|
||||
const Memo = memo(ForwardRef)
|
||||
|
||||
export default Memo
|
||||
30
src/assets/icons/close.tsx
Normal file
30
src/assets/icons/close.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { SVGProps, Ref, forwardRef, memo } from 'react'
|
||||
|
||||
const SvgComponent = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) => (
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||||
<g clipPath="url(#clip0_9883_2381)">
|
||||
<path
|
||||
d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12L19 6.41Z"
|
||||
fill="white"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_9883_2381">
|
||||
<rect width="24" height="24" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</svg>
|
||||
)
|
||||
const ForwardRef = forwardRef(SvgComponent)
|
||||
|
||||
export default memo(ForwardRef)
|
||||
32
src/assets/icons/edit.tsx
Normal file
32
src/assets/icons/edit.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { SVGProps, Ref, forwardRef, memo } from 'react'
|
||||
const SvgComponent = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) => (
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<g clipPath="url(#clip0_5918_2436)">
|
||||
<path
|
||||
d="M12.6666 13.3334H3.33329C3.15648 13.3334 2.98691 13.4036 2.86189 13.5286C2.73686 13.6537 2.66663 13.8232 2.66663 14C2.66663 14.1769 2.73686 14.3464 2.86189 14.4714C2.98691 14.5965 3.15648 14.6667 3.33329 14.6667H12.6666C12.8434 14.6667 13.013 14.5965 13.138 14.4714C13.2631 14.3464 13.3333 14.1769 13.3333 14C13.3333 13.8232 13.2631 13.6537 13.138 13.5286C13.013 13.4036 12.8434 13.3334 12.6666 13.3334Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M3.33329 12H3.39329L6.17329 11.7467C6.47782 11.7163 6.76264 11.5821 6.97995 11.3667L12.98 5.36665C13.2128 5.12063 13.3387 4.79233 13.3299 4.45368C13.3212 4.11503 13.1786 3.79366 12.9333 3.55999L11.1066 1.73332C10.8682 1.50938 10.5558 1.38089 10.2288 1.37229C9.90187 1.36368 9.58314 1.47557 9.33329 1.68665L3.33329 7.68665C3.1178 7.90396 2.98362 8.18879 2.95329 8.49332L2.66662 11.2733C2.65764 11.371 2.67031 11.4694 2.70373 11.5616C2.73715 11.6538 2.79049 11.7374 2.85995 11.8067C2.92225 11.8684 2.99612 11.9173 3.07735 11.9505C3.15857 11.9837 3.24555 12.0005 3.33329 12ZM10.18 2.66665L12 4.48665L10.6666 5.78665L8.87995 3.99999L10.18 2.66665ZM4.24662 8.60665L7.99995 4.87999L9.79995 6.67999L6.06662 10.4133L4.06662 10.6L4.24662 8.60665Z"
|
||||
fill="white"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_5918_2436">
|
||||
<rect width="16" height="16" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
const ForwardRef = forwardRef(SvgComponent)
|
||||
const Memo = memo(ForwardRef)
|
||||
|
||||
export default Memo
|
||||
74
src/assets/icons/email.tsx
Normal file
74
src/assets/icons/email.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import { SVGProps, Ref, forwardRef, memo } from 'react'
|
||||
const SvgComponent = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={96}
|
||||
height={96}
|
||||
fill="none"
|
||||
viewBox="0 0 96 96"
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fill="#8C61FF"
|
||||
fillOpacity={0.05}
|
||||
stroke="#BEA6FF"
|
||||
d="M95.5 48c0 26.234-21.266 47.5-47.5 47.5C21.767 95.5.5 74.234.5 48 .5 21.767 21.767.5 48 .5 74.234.5 95.5 21.767 95.5 48z"
|
||||
/>
|
||||
<path
|
||||
fill="#BEA6FF"
|
||||
d="M77.889 54.454a.651.651 0 0 1-.643-.643v-9.24a.643.643 0 0 1 1.285 0v9.25a.643.643 0 0 1-.641.633zM77.889 41.777a.643.643 0 0 1-.643-.643V39.24a.643.643 0 0 1 1.285 0v1.903a.634.634 0 0 1-.641.634zM25.786 32.503h-3.559a.668.668 0 0 1 0-1.335h3.56a.667.667 0 0 1 0 1.335z"
|
||||
/>
|
||||
<path
|
||||
fill="#BEA6FF"
|
||||
d="M24.007 34.282a.668.668 0 0 1-.667-.667v-3.559a.668.668 0 0 1 1.335 0v3.56c0 .367-.3.666-.668.666zM36.857 73.714a.857.857 0 1 1 0 1.715.857.857 0 0 1 0-1.715zM31.714 73.714a.857.857 0 1 1 0 1.715.857.857 0 0 1 0-1.715zM26.571 73.714a.857.857 0 1 1 0 1.715.857.857 0 0 1 0-1.715z"
|
||||
/>
|
||||
<path fill="#333" d="M47.864 23.242l-24.1 19.799 24.1 19.808 24.1-19.808-24.1-19.8z" />
|
||||
<path
|
||||
fill="#BEA6FF"
|
||||
d="M47.865 63.544a.667.667 0 0 1-.417-.195l-24.1-19.808a.698.698 0 0 1-.183-.833.725.725 0 0 1 .183-.242l24.1-19.799a.695.695 0 0 1 .926 0l24.1 19.799a.725.725 0 0 1 .25.537.695.695 0 0 1-.25.538l-24.1 19.808a.668.668 0 0 1-.51.195zM24.859 43.04l23.006 18.91L70.87 43.04l-23.006-18.9-23.006 18.9z"
|
||||
/>
|
||||
<path fill="#333" d="M65.013 28.803H30.717v40.784h34.296V28.803z" />
|
||||
<path fill="#333" d="M55.41 40.853l-11.716 9.63v19.104h21.319V40.853H55.41z" />
|
||||
<path
|
||||
fill="#BEA6FF"
|
||||
d="M65.059 70.282H30.763a.704.704 0 0 1-.695-.695V28.803a.695.695 0 0 1 .695-.677H65.06a.695.695 0 0 1 .695.696v40.784a.705.705 0 0 1-.695.676zM31.412 68.91h32.905V29.517H31.412V68.91z"
|
||||
/>
|
||||
<path
|
||||
fill="#BEA6FF"
|
||||
d="M58.987 35.06H48.17a.695.695 0 0 1 0-1.39h10.817a.696.696 0 0 1 0 1.39zM44.463 35.06h-7.721a.696.696 0 0 1 0-1.39h7.72a.696.696 0 0 1 0 1.39zM58.987 39.694h-7.11a.695.695 0 0 1 0-1.39h7.11a.695.695 0 1 1 0 1.39zM48.17 39.694H36.742a.695.695 0 0 1 0-1.39H48.17a.695.695 0 1 1 0 1.39zM58.988 44.329H46.317a.696.696 0 0 1 0-1.39h12.67a.696.696 0 0 1 0 1.39zM42.609 44.329h-5.867a.696.696 0 0 1 0-1.39h5.867a.696.696 0 0 1 0 1.39zM58.987 48.964h-6.182a.695.695 0 0 1 0-1.39h6.182a.695.695 0 1 1 0 1.39zM49.097 48.964H36.742a.695.695 0 0 1 0-1.39h12.355a.695.695 0 1 1 0 1.39zM54.047 53.598H41.682a.695.695 0 1 1 0-1.39h12.365a.695.695 0 1 1 0 1.39z"
|
||||
/>
|
||||
<path
|
||||
fill="#333"
|
||||
d="M23.765 43.04v26.547l16.147-13.273L23.765 43.04zM55.818 56.314l16.146 13.273V43.04L55.818 56.315z"
|
||||
/>
|
||||
<path
|
||||
fill="#333"
|
||||
d="M47.864 62.849l-7.952-6.535-16.147 13.273h48.2L55.816 56.314l-7.953 6.535z"
|
||||
/>
|
||||
<path
|
||||
fill="#333"
|
||||
d="M28.4 50.493v15.284l9.297-7.637-9.297-7.647zM63.196 57.88l8.768 7.212V50.678l-8.768 7.202z"
|
||||
/>
|
||||
<path
|
||||
fill="#BEA6FF"
|
||||
d="M23.765 70.282a.67.67 0 0 1-.296-.074.686.686 0 0 1-.399-.62V43.04a.685.685 0 0 1 .399-.62.695.695 0 0 1 .741.083l16.147 13.273a.704.704 0 0 1 0 1.075L24.21 70.115a.686.686 0 0 1-.445.167zm.695-25.768v23.6l14.358-11.8-14.358-11.8z"
|
||||
/>
|
||||
<path fill="#333" d="M60.424 60.095l-10.15 8.343-7.08-5.821-8.473 6.97h37.243l-11.54-9.492z" />
|
||||
<path
|
||||
fill="#BEA6FF"
|
||||
d="M71.964 70.282a.686.686 0 0 1-.445-.167L55.373 56.861a.703.703 0 0 1 0-1.076l16.174-13.282a.696.696 0 0 1 .742-.084.687.687 0 0 1 .398.621v26.547a.686.686 0 0 1-.398.621.668.668 0 0 1-.325.074zM56.911 56.314l14.358 11.8v-23.6l-14.358 11.8z"
|
||||
/>
|
||||
<path
|
||||
fill="#BEA6FF"
|
||||
d="M71.964 70.282h-48.2a.704.704 0 0 1-.657-.463.705.705 0 0 1 .213-.77l16.147-13.273a.695.695 0 0 1 .927 0l7.508 6.173 7.508-6.174a.695.695 0 0 1 .927 0L72.483 69.05a.705.705 0 0 1 .213.77.704.704 0 0 1-.732.463zm-46.262-1.371h44.325L55.79 57.212l-7.508 6.173a.695.695 0 0 1-.927 0l-7.508-6.173L25.702 68.91zM46.358 75.36h-3.56a.668.668 0 0 1 0-1.335h3.56a.668.668 0 0 1 0 1.335z"
|
||||
/>
|
||||
<path
|
||||
fill="#BEA6FF"
|
||||
d="M44.579 77.14a.668.668 0 0 1-.668-.668v-3.559a.668.668 0 0 1 1.335 0v3.56a.667.667 0 0 1-.667.666z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
const ForwardRef = forwardRef(SvgComponent)
|
||||
|
||||
export default memo(ForwardRef)
|
||||
22
src/assets/icons/eye.tsx
Normal file
22
src/assets/icons/eye.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { SVGProps, Ref, forwardRef, memo } from 'react'
|
||||
const SvgComponent = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={20}
|
||||
height={20}
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fill="#fff"
|
||||
fillRule="evenodd"
|
||||
d="M12 4.5C7 4.5 2.73 7.6 1 12a11.83 11.83 0 0 0 22 0c-1.73-4.39-6-7.5-11-7.5zM12 17a5 5 0 1 1 0-10 5 5 0 0 1 0 10zm0-8a3 3 0 1 0 0 6 3 3 0 0 0 0-6z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
const ForwardRef = forwardRef(SvgComponent)
|
||||
|
||||
export default memo(ForwardRef)
|
||||
11
src/assets/icons/index.ts
Normal file
11
src/assets/icons/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export { default as Eye } from './eye'
|
||||
export { default as VisibilityOff } from './visibility-off'
|
||||
export { default as Check } from './check'
|
||||
export { default as Email } from './email'
|
||||
export { default as Camera } from './camera'
|
||||
export { default as Logout } from './logout'
|
||||
export { default as Edit } from './edit'
|
||||
export { default as Logo } from './logo'
|
||||
export { default as PersonOutline } from './person-outline'
|
||||
export { default as ChevronUp } from './chevron-up'
|
||||
export { default as Close } from './close'
|
||||
30
src/assets/icons/logo.tsx
Normal file
30
src/assets/icons/logo.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { SVGProps } from 'react'
|
||||
const SvgComponent = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={157}
|
||||
height={36}
|
||||
fill="none"
|
||||
viewBox="0 0 157 36"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fill="#fff"
|
||||
d="M70.99 24.72a7.34 7.34 0 0 1-3.5-.83 6.43 6.43 0 0 1-2.44-2.33c-.6-1-.89-2.13-.89-3.38s.3-2.37.89-3.36c.6-1 1.41-1.77 2.45-2.32a7.25 7.25 0 0 1 3.5-.85c1.1 0 2.08.19 2.96.57.89.39 1.63.94 2.23 1.66l-1.87 1.74a4.02 4.02 0 0 0-3.17-1.48c-.78 0-1.48.17-2.09.52-.6.34-1.09.81-1.44 1.43-.33.61-.5 1.3-.5 2.1 0 .77.17 1.47.5 2.09.35.6.83 1.1 1.44 1.44.61.34 1.31.5 2.1.5a4 4 0 0 0 3.16-1.5l1.87 1.74c-.6.73-1.34 1.3-2.23 1.68a7.4 7.4 0 0 1-2.97.58zM83.66 24.72c-1.8 0-3.2-.5-4.22-1.5-1-1-1.5-2.43-1.5-4.28v-7.08h2.93v6.97c0 2.26.93 3.4 2.8 3.4.92 0 1.61-.28 2.1-.82.47-.55.71-1.41.71-2.58v-6.97h2.89v7.08c0 1.85-.5 3.28-1.52 4.28-1 1-2.4 1.5-4.2 1.5zM101.5 17.93a3.13 3.13 0 0 1 2.3 3.12c0 1.1-.42 1.96-1.29 2.56-.84.6-2.09.9-3.73.9h-6.52V11.86h6.16c1.53 0 2.7.3 3.53.89a2.8 2.8 0 0 1 1.24 2.4 3.04 3.04 0 0 1-1.68 2.78zm-6.35-3.86v2.97h2.9c.72 0 1.26-.12 1.63-.38.38-.25.56-.62.56-1.11 0-.5-.18-.86-.56-1.1a2.92 2.92 0 0 0-1.63-.38h-2.9zm3.4 8.23c.77 0 1.34-.13 1.73-.38.4-.25.6-.65.6-1.18 0-1.04-.78-1.57-2.33-1.57h-3.4v3.13h3.4zM114.32 21.8h-5.85l-1.12 2.7h-2.99l5.62-12.64h2.88l5.64 12.64h-3.07l-1.11-2.7zm-.92-2.23l-2-4.84-2 4.84h4zM121.78 14.25h-4.03v-2.39h10.98v2.39h-4.03V24.5h-2.92V14.25zM136.23 24.72a7.4 7.4 0 0 1-3.55-.85 6.39 6.39 0 0 1-2.47-2.33 6.5 6.5 0 0 1-.88-3.36 6.34 6.34 0 0 1 3.35-5.69 7.4 7.4 0 0 1 3.55-.84c1.3 0 2.48.28 3.53.85a6.35 6.35 0 0 1 3.37 5.68 6.4 6.4 0 0 1-.9 3.36 6.4 6.4 0 0 1-2.47 2.33 7.29 7.29 0 0 1-3.53.85zm0-2.5a3.69 3.69 0 0 0 3.42-1.95c.35-.6.52-1.3.52-2.09 0-.78-.17-1.48-.52-2.1a3.56 3.56 0 0 0-1.4-1.42 3.94 3.94 0 0 0-2.02-.52 3.94 3.94 0 0 0-3.44 1.95c-.34.61-.5 1.3-.5 2.1 0 .77.16 1.47.5 2.09a3.82 3.82 0 0 0 3.44 1.94zM153.35 24.5l-2.43-3.52H148.24v3.52h-2.92V11.86h5.45c1.12 0 2.09.19 2.9.56.83.38 1.47.9 1.91 1.6.44.68.67 1.49.67 2.43a4.3 4.3 0 0 1-.69 2.44 4.25 4.25 0 0 1-1.9 1.55l2.82 4.06h-3.13zm-.06-8.05c0-.71-.22-1.25-.68-1.63-.45-.38-1.11-.57-1.99-.57h-2.36v4.4h2.37c.88 0 1.54-.2 2-.58a2 2 0 0 0 .68-1.62zM0 11.88h2.91v12.6H0v-12.6zM8.5 14.25H4.49v-2.37h10.97v2.37h-4.03v10.22H8.5V14.25zM33.74 11.88h2.92v12.6h-2.92v-12.6zM51.2 11.88v12.6h-2.39l-6.28-7.65v7.64h-2.88v-12.6h2.41l6.27 7.65v-7.64h2.88z"
|
||||
/>
|
||||
<path
|
||||
fill="#FF0808"
|
||||
fillRule="evenodd"
|
||||
d="M34.99 6.53a1.96 1.96 0 1 1 0 3.93 1.96 1.96 0 0 1 0-3.93z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
<path
|
||||
fill="#fff"
|
||||
fillRule="evenodd"
|
||||
d="M19.5 16.04A2 2 0 0 1 21.5 18a2 2 0 0 1-2 1.96A2 2 0 0 1 17.46 18a2 2 0 0 1 2.02-1.96zM42.48 34.5a16.5 16.5 0 1 0 0-33 16.5 16.5 0 0 0 0 33zm0 1.5a18 18 0 1 0 0-36 18 18 0 0 0 0 36z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
|
||||
export default SvgComponent
|
||||
31
src/assets/icons/logout.tsx
Normal file
31
src/assets/icons/logout.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { SVGProps, Ref, forwardRef, memo } from 'react'
|
||||
const SvgComponent = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) => (
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<g clipPath="url(#clip0_6627_107)">
|
||||
<path
|
||||
d="M4.66663 3.99996C4.84344 3.99996 5.01301 3.92972 5.13803 3.8047C5.26305 3.67967 5.33329 3.5101 5.33329 3.33329C5.33329 3.15648 5.26305 2.98691 5.13803 2.86189C5.01301 2.73686 4.84344 2.66663 4.66663 2.66663H3.33329C3.15648 2.66663 2.98691 2.73686 2.86189 2.86189C2.73686 2.98691 2.66663 3.15648 2.66663 3.33329V12.6666C2.66663 12.8434 2.73686 13.013 2.86189 13.138C2.98691 13.2631 3.15648 13.3333 3.33329 13.3333H4.66663C4.84344 13.3333 5.01301 13.2631 5.13803 13.138C5.26305 13.013 5.33329 12.8434 5.33329 12.6666C5.33329 12.4898 5.26305 12.3202 5.13803 12.1952C5.01301 12.0702 4.84344 12 4.66663 12H3.99996V3.99996H4.66663Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M13.88 7.61338L12 4.94672C11.898 4.80299 11.7433 4.70548 11.5697 4.67549C11.396 4.64551 11.2176 4.6855 11.0733 4.78672C11.0012 4.83724 10.9399 4.90154 10.8927 4.97592C10.8456 5.05029 10.8137 5.13326 10.7988 5.22004C10.784 5.30681 10.7864 5.39568 10.8061 5.4815C10.8257 5.56732 10.8622 5.64839 10.9133 5.72005L12.06 7.33338H6.66667C6.48986 7.33338 6.32029 7.40362 6.19526 7.52864C6.07024 7.65367 6 7.82324 6 8.00005C6 8.17686 6.07024 8.34643 6.19526 8.47145C6.32029 8.59648 6.48986 8.66672 6.66667 8.66672H12L10.8 10.2667C10.7475 10.3368 10.7093 10.4165 10.6875 10.5013C10.6658 10.5861 10.661 10.6743 10.6734 10.761C10.6857 10.8477 10.7151 10.931 10.7597 11.0064C10.8043 11.0817 10.8633 11.1475 10.9333 11.2C11.0487 11.2866 11.1891 11.3334 11.3333 11.3334C11.4368 11.3334 11.5389 11.3093 11.6315 11.263C11.724 11.2167 11.8046 11.1495 11.8667 11.0667L13.8667 8.40005C13.952 8.28729 13.9994 8.15031 14.0018 8.00889C14.0041 7.86748 13.9615 7.72897 13.88 7.61338Z"
|
||||
fill="white"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_6627_107">
|
||||
<rect width="16" height="16" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
const ForwardRef = forwardRef(SvgComponent)
|
||||
|
||||
export default memo(ForwardRef)
|
||||
22
src/assets/icons/person-outline.tsx
Normal file
22
src/assets/icons/person-outline.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { SVGProps } from 'react'
|
||||
const SvgComponent = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={16}
|
||||
height={16}
|
||||
fill="none"
|
||||
viewBox="0 0 16 16"
|
||||
{...props}
|
||||
>
|
||||
<g fill="#fff" clipPath="url(#clip0_6693_1154)">
|
||||
<path d="M8 7.334a2.667 2.667 0 1 0 0-5.333 2.667 2.667 0 0 0 0 5.334zm0-4a1.333 1.333 0 1 1 0 2.667 1.333 1.333 0 0 1 0-2.666zM8 8.668a4.667 4.667 0 0 0-4.667 4.666.667.667 0 1 0 1.334 0 3.333 3.333 0 0 1 6.666 0 .667.667 0 1 0 1.334 0A4.667 4.667 0 0 0 8 8.668z" />
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_6693_1154">
|
||||
<path fill="#fff" d="M0 0h16v16H0z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
|
||||
export default SvgComponent
|
||||
20
src/assets/icons/visibility-off.tsx
Normal file
20
src/assets/icons/visibility-off.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { SVGProps, Ref, forwardRef, memo } from 'react'
|
||||
const SvgComponent = (props: SVGProps<SVGSVGElement>, ref: Ref<SVGSVGElement>) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={20}
|
||||
height={20}
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fill="#fff"
|
||||
d="M12 5.975a9.77 9.77 0 0 1 8.82 5.5 9.647 9.647 0 0 1-2.41 3.12l1.41 1.41c1.39-1.23 2.49-2.77 3.18-4.53-1.73-4.39-6-7.5-11-7.5-1.27 0-2.49.2-3.64.57l1.65 1.65c.65-.13 1.31-.22 1.99-.22zm-1.07 1.14L13 9.185c.57.25 1.03.71 1.28 1.28l2.07 2.07c.08-.34.14-.7.14-1.07.01-2.48-2.01-4.49-4.49-4.49-.37 0-.72.05-1.07.14zm-8.92-3.27l2.68 2.68A11.738 11.738 0 0 0 1 11.475c1.73 4.39 6 7.5 11 7.5 1.52 0 2.98-.29 4.32-.82l3.42 3.42 1.41-1.41L3.42 2.425l-1.41 1.42zm7.5 7.5l2.61 2.61c-.04.01-.08.02-.12.02a2.5 2.5 0 0 1-2.5-2.5c0-.05.01-.08.01-.13zm-3.4-3.4l1.75 1.75a4.6 4.6 0 0 0-.36 1.78 4.507 4.507 0 0 0 6.27 4.14l.98.98c-.88.24-1.8.38-2.75.38a9.77 9.77 0 0 1-8.82-5.5c.7-1.43 1.72-2.61 2.93-3.53z"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
const ForwardRef = forwardRef(SvgComponent)
|
||||
|
||||
export default memo(ForwardRef)
|
||||
1
src/assets/index.ts
Normal file
1
src/assets/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './icons'
|
||||
@@ -1,19 +1,102 @@
|
||||
@mixin button {
|
||||
all: unset;
|
||||
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
display: inline-flex;
|
||||
flex-shrink: 0;
|
||||
gap: 0.625rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
box-sizing: border-box;
|
||||
padding: 0.375rem 1.75rem;
|
||||
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
border-radius: 0.25rem;
|
||||
|
||||
transition:
|
||||
var(--transition-duration-basic) background-color,
|
||||
var(--transition-duration-basic) color;
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--color-info-700);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
cursor: default;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
&.fullWidth {
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.primary {
|
||||
background-color: red;
|
||||
@include button;
|
||||
|
||||
color: var(--color-light-100);
|
||||
background-color: var(--color-accent-500);
|
||||
box-shadow: 0 4px 18px rgb(140 97 255 / 35%);
|
||||
|
||||
&:hover:enabled {
|
||||
background-color: var(--color-accent-300);
|
||||
}
|
||||
|
||||
&:active:enabled {
|
||||
background-color: var(--color-accent-700);
|
||||
}
|
||||
}
|
||||
|
||||
.secondary {
|
||||
background-color: green;
|
||||
@include button;
|
||||
|
||||
color: var(--color-light-100);
|
||||
background-color: var(--color-dark-300);
|
||||
box-shadow: 0 2px 10px 0 #6d6d6d40;
|
||||
|
||||
&:hover:enabled {
|
||||
background-color: var(--color-dark-100);
|
||||
}
|
||||
|
||||
&:active:enabled {
|
||||
background-color: var(--color-dark-500);
|
||||
}
|
||||
}
|
||||
|
||||
.tertiary {
|
||||
background-color: blue;
|
||||
@include button;
|
||||
|
||||
color: var(--color-accent-500);
|
||||
background-color: var(--color-dark-900);
|
||||
border: 1px solid var(--color-accent-700);
|
||||
|
||||
&:hover:enabled {
|
||||
background-color: var(--color-dark-500);
|
||||
}
|
||||
|
||||
&:active:enabled {
|
||||
background-color: var(--color-accent-900);
|
||||
}
|
||||
}
|
||||
|
||||
.link {
|
||||
background-color: yellow;
|
||||
}
|
||||
@include button;
|
||||
|
||||
.fullWidth {
|
||||
width: 100%;
|
||||
padding: 0.375rem 0;
|
||||
|
||||
font-weight: var(--font-weight-bold);
|
||||
line-height: var(--line-height-m);
|
||||
color: var(--color-accent-500);
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
7
src/components/ui/card/card.module.scss
Normal file
7
src/components/ui/card/card.module.scss
Normal file
@@ -0,0 +1,7 @@
|
||||
.root {
|
||||
background-color: var(--color-dark-700);
|
||||
border-radius: 2px;
|
||||
box-shadow:
|
||||
1px 1px 2px rgb(0 0 0 / 10%),
|
||||
-1px -1px 2px rgb(0 0 0 / 10%);
|
||||
}
|
||||
25
src/components/ui/card/card.stories.tsx
Normal file
25
src/components/ui/card/card.stories.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import { Card } from './'
|
||||
|
||||
import { Typography } from '@/components'
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Card',
|
||||
component: Card,
|
||||
tags: ['autodocs'],
|
||||
} satisfies Meta<typeof Card>
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
children: <Typography variant={'large'}>Card</Typography>,
|
||||
style: {
|
||||
width: '300px',
|
||||
height: '300px',
|
||||
padding: '24px',
|
||||
},
|
||||
},
|
||||
}
|
||||
15
src/components/ui/card/card.tsx
Normal file
15
src/components/ui/card/card.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { ComponentPropsWithoutRef, forwardRef } from 'react'
|
||||
|
||||
import { clsx } from 'clsx'
|
||||
|
||||
import s from './card.module.scss'
|
||||
|
||||
export type CardProps = {} & ComponentPropsWithoutRef<'div'>
|
||||
|
||||
export const Card = forwardRef<HTMLDivElement, CardProps>(({ className, ...restProps }, ref) => {
|
||||
const classNames = {
|
||||
root: clsx(s.root, className),
|
||||
}
|
||||
|
||||
return <div ref={ref} className={classNames.root} {...restProps}></div>
|
||||
})
|
||||
1
src/components/ui/card/index.ts
Normal file
1
src/components/ui/card/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './card'
|
||||
80
src/components/ui/checkbox/checkbox.module.scss
Normal file
80
src/components/ui/checkbox/checkbox.module.scss
Normal file
@@ -0,0 +1,80 @@
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.label {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&.disabled {
|
||||
cursor: initial;
|
||||
color: var(--color-dark-100);
|
||||
}
|
||||
}
|
||||
|
||||
.root {
|
||||
cursor: pointer;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
||||
background-color: var(--color-dark-900);
|
||||
border: 2px solid var(--color-light-900);
|
||||
border-radius: 2px;
|
||||
|
||||
&:focus {
|
||||
background-color: var(--color-bg-focus);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
cursor: initial;
|
||||
border-color: var(--color-dark-100);
|
||||
}
|
||||
|
||||
&[data-state='checked']:disabled {
|
||||
background-color: var(--color-checkbox-disabled);
|
||||
}
|
||||
}
|
||||
|
||||
.buttonWrapper {
|
||||
cursor: pointer;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
|
||||
background-color: var(--color-dark-900);
|
||||
border-radius: 50%;
|
||||
|
||||
&.disabled {
|
||||
cursor: initial;
|
||||
}
|
||||
|
||||
&:focus-within,
|
||||
&:hover:not(.disabled),
|
||||
&:hover .root:not([data-state='checked']) {
|
||||
background-color: var(--color-dark-500);
|
||||
}
|
||||
|
||||
&:active:not(.disabled) {
|
||||
background-color: var(--color-dark-100);
|
||||
}
|
||||
|
||||
&.left {
|
||||
margin-left: -9px;
|
||||
}
|
||||
}
|
||||
|
||||
.indicator {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
35
src/components/ui/checkbox/checkbox.stories.tsx
Normal file
35
src/components/ui/checkbox/checkbox.stories.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { useState } from 'react'
|
||||
|
||||
import { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import { Checkbox } from './checkbox'
|
||||
const meta = {
|
||||
title: 'Components/Checkbox',
|
||||
component: Checkbox,
|
||||
tags: ['autodocs'],
|
||||
} satisfies Meta<typeof Checkbox>
|
||||
|
||||
export default meta
|
||||
|
||||
type Story = StoryObj<typeof meta>
|
||||
export const Uncontrolled: Story = {
|
||||
args: {
|
||||
label: 'Click here',
|
||||
disabled: false,
|
||||
},
|
||||
}
|
||||
|
||||
export const Controlled: Story = {
|
||||
render: args => {
|
||||
const [checked, setChecked] = useState(false)
|
||||
|
||||
return (
|
||||
<Checkbox
|
||||
{...args}
|
||||
label="Click here"
|
||||
checked={checked}
|
||||
onChange={() => setChecked(!checked)}
|
||||
/>
|
||||
)
|
||||
},
|
||||
}
|
||||
66
src/components/ui/checkbox/checkbox.tsx
Normal file
66
src/components/ui/checkbox/checkbox.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import { FC } from 'react'
|
||||
|
||||
import * as CheckboxRadix from '@radix-ui/react-checkbox'
|
||||
import * as LabelRadix from '@radix-ui/react-label'
|
||||
import { clsx } from 'clsx'
|
||||
|
||||
import s from './checkbox.module.scss'
|
||||
|
||||
import { Check } from '@/assets/icons'
|
||||
import { Typography } from '@/components'
|
||||
|
||||
export type CheckboxProps = {
|
||||
className?: string
|
||||
checked?: boolean
|
||||
onChange?: (checked: boolean) => void
|
||||
disabled?: boolean
|
||||
required?: boolean
|
||||
label?: string
|
||||
id?: string
|
||||
position?: 'left'
|
||||
}
|
||||
|
||||
export const Checkbox: FC<CheckboxProps> = ({
|
||||
checked,
|
||||
onChange,
|
||||
position,
|
||||
disabled,
|
||||
required,
|
||||
label,
|
||||
id,
|
||||
className,
|
||||
}) => {
|
||||
const classNames = {
|
||||
container: clsx(s.container, className),
|
||||
buttonWrapper: clsx(s.buttonWrapper, disabled && s.disabled, position === 'left' && s.left),
|
||||
root: s.root,
|
||||
indicator: s.indicator,
|
||||
label: clsx(s.label, disabled && s.disabled),
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames.container}>
|
||||
<LabelRadix.Root asChild>
|
||||
<Typography variant="body2" className={classNames.label} as={'label'}>
|
||||
<div className={classNames.buttonWrapper}>
|
||||
<CheckboxRadix.Root
|
||||
className={classNames.root}
|
||||
checked={checked}
|
||||
onCheckedChange={onChange}
|
||||
disabled={disabled}
|
||||
required={required}
|
||||
id={id}
|
||||
>
|
||||
{checked && (
|
||||
<CheckboxRadix.Indicator className={classNames.indicator} forceMount>
|
||||
<Check />
|
||||
</CheckboxRadix.Indicator>
|
||||
)}
|
||||
</CheckboxRadix.Root>
|
||||
</div>
|
||||
{label}
|
||||
</Typography>
|
||||
</LabelRadix.Root>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
1
src/components/ui/checkbox/index.ts
Normal file
1
src/components/ui/checkbox/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './checkbox'
|
||||
@@ -1 +1,4 @@
|
||||
export * from './button'
|
||||
export * from './card'
|
||||
export * from './typography'
|
||||
export * from './checkbox'
|
||||
|
||||
1
src/components/ui/text-field/index.ts
Normal file
1
src/components/ui/text-field/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './text-field'
|
||||
71
src/components/ui/text-field/text-field.module.scss
Normal file
71
src/components/ui/text-field/text-field.module.scss
Normal file
@@ -0,0 +1,71 @@
|
||||
.root {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fieldContainer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.field {
|
||||
width: 100%;
|
||||
padding: 6px 12px;
|
||||
|
||||
font-family: inherit;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
color: var(--color-light-100);
|
||||
|
||||
background: transparent;
|
||||
border: 1px solid var(--color-dark-300);
|
||||
outline: 0;
|
||||
|
||||
transition: border-color 0.2s;
|
||||
|
||||
&::placeholder {
|
||||
color: var(--color-dark-100);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
border-color: var(--color-info-700);
|
||||
outline: 1px solid var(--color-info-700);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--color-dark-700);
|
||||
}
|
||||
|
||||
&.error {
|
||||
color: var(--color-danger-300);
|
||||
border-color: var(--color-danger-300);
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
margin-bottom: 1px;
|
||||
color: var(--color-dark-100);
|
||||
}
|
||||
|
||||
.showPassword {
|
||||
cursor: pointer;
|
||||
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
bottom: 50%;
|
||||
transform: translateY(-50%);
|
||||
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 12px;
|
||||
padding: 0;
|
||||
|
||||
background: transparent;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
|
||||
&:focus-visible {
|
||||
outline: var(--outline-focus);
|
||||
}
|
||||
}
|
||||
35
src/components/ui/text-field/text-field.stories.ts
Normal file
35
src/components/ui/text-field/text-field.stories.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import { TextField } from './'
|
||||
|
||||
const meta = {
|
||||
title: 'Components/TextField',
|
||||
component: TextField,
|
||||
tags: ['autodocs'],
|
||||
} satisfies Meta<typeof TextField>
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
label: 'Label',
|
||||
placeholder: 'Placeholder',
|
||||
},
|
||||
}
|
||||
|
||||
export const Password: Story = {
|
||||
args: {
|
||||
label: 'Label',
|
||||
placeholder: 'Password',
|
||||
type: 'password',
|
||||
},
|
||||
}
|
||||
|
||||
export const Error: Story = {
|
||||
args: {
|
||||
label: 'Input with error',
|
||||
value: 'Wrong value',
|
||||
errorMessage: 'Error message',
|
||||
},
|
||||
}
|
||||
94
src/components/ui/text-field/text-field.tsx
Normal file
94
src/components/ui/text-field/text-field.tsx
Normal file
@@ -0,0 +1,94 @@
|
||||
import { ChangeEvent, ComponentProps, ComponentPropsWithoutRef, forwardRef, useState } from 'react'
|
||||
|
||||
import { clsx } from 'clsx'
|
||||
|
||||
import s from './text-field.module.scss'
|
||||
|
||||
import { VisibilityOff, Eye } from '@/assets'
|
||||
import { Typography } from '@/components'
|
||||
|
||||
export type TextFieldProps = {
|
||||
onValueChange?: (value: string) => void
|
||||
containerProps?: ComponentProps<'div'>
|
||||
labelProps?: ComponentProps<'label'>
|
||||
errorMessage?: string
|
||||
label?: string
|
||||
} & ComponentPropsWithoutRef<'input'>
|
||||
|
||||
export const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
errorMessage,
|
||||
placeholder,
|
||||
type,
|
||||
containerProps,
|
||||
labelProps,
|
||||
label,
|
||||
onChange,
|
||||
onValueChange,
|
||||
...restProps
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const [showPassword, setShowPassword] = useState(false)
|
||||
|
||||
const isShowPasswordButtonShown = type === 'password'
|
||||
|
||||
const finalType = getFinalType(type, showPassword)
|
||||
|
||||
function handleChange(e: ChangeEvent<HTMLInputElement>) {
|
||||
onChange?.(e)
|
||||
onValueChange?.(e.target.value)
|
||||
}
|
||||
|
||||
const classNames = {
|
||||
root: clsx(s.root, containerProps?.className),
|
||||
fieldContainer: clsx(s.fieldContainer),
|
||||
field: clsx(s.field, !!errorMessage && s.error, className),
|
||||
label: clsx(s.label, labelProps?.className),
|
||||
error: clsx(s.error),
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames.root}>
|
||||
{label && (
|
||||
<Typography variant="body2" as="label" className={classNames.label}>
|
||||
{label}
|
||||
</Typography>
|
||||
)}
|
||||
<div className={classNames.fieldContainer}>
|
||||
<input
|
||||
className={classNames.field}
|
||||
placeholder={placeholder}
|
||||
ref={ref}
|
||||
type={finalType}
|
||||
onChange={handleChange}
|
||||
{...restProps}
|
||||
/>
|
||||
{isShowPasswordButtonShown && (
|
||||
<button
|
||||
className={s.showPassword}
|
||||
type={'button'}
|
||||
onClick={() => setShowPassword(prev => !prev)}
|
||||
>
|
||||
{showPassword ? <VisibilityOff /> : <Eye />}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Typography variant="error" className={classNames.error}>
|
||||
{errorMessage}
|
||||
</Typography>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
function getFinalType(type: ComponentProps<'input'>['type'], showPassword: boolean) {
|
||||
if (type === 'password' && showPassword) {
|
||||
return 'text'
|
||||
}
|
||||
|
||||
return type
|
||||
}
|
||||
1
src/components/ui/typography/index.ts
Normal file
1
src/components/ui/typography/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './typography'
|
||||
72
src/components/ui/typography/typography.module.scss
Normal file
72
src/components/ui/typography/typography.module.scss
Normal file
@@ -0,0 +1,72 @@
|
||||
@mixin typography($fontSize, $lineHeight, $fontWeight) {
|
||||
margin: 0;
|
||||
|
||||
font-size: $fontSize;
|
||||
font-weight: $fontWeight;
|
||||
line-height: $lineHeight;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.large {
|
||||
@include typography(var(--font-size-xxl), var(--line-height-l), var(--font-weight-bold));
|
||||
}
|
||||
|
||||
.h1 {
|
||||
@include typography(var(--font-size-xl), var(--line-height-l), var(--font-weight-bold));
|
||||
}
|
||||
|
||||
.h2 {
|
||||
@include typography(var(--font-size-l), var(--line-height-m), var(--font-weight-bold));
|
||||
}
|
||||
|
||||
.h3 {
|
||||
@include typography(var(--font-size-m), var(--line-height-m), var(--font-weight-bold));
|
||||
}
|
||||
|
||||
.body1 {
|
||||
@include typography(var(--font-size-m), var(--line-height-m), var(--font-weight-regular));
|
||||
}
|
||||
|
||||
.subtitle1 {
|
||||
@include typography(var(--font-size-m), var(--line-height-m), var(--font-weight-bold));
|
||||
}
|
||||
|
||||
.body2 {
|
||||
@include typography(var(--font-size-s), var(--line-height-m), var(--font-weight-regular));
|
||||
}
|
||||
|
||||
.subtitle2 {
|
||||
@include typography(var(--font-size-s), var(--line-height-m), var(--font-weight-bold));
|
||||
}
|
||||
|
||||
.overline {
|
||||
@include typography(var(--font-size-xs), var(--line-height-s), var(--font-weight-bold));
|
||||
}
|
||||
|
||||
.caption {
|
||||
@include typography(var(--font-size-xs), var(--line-height-s), var(--font-weight-regular));
|
||||
}
|
||||
|
||||
.link1,
|
||||
.link1:visited {
|
||||
@include typography(var(--font-size-s), var(--line-height-m), var(--font-weight-regular));
|
||||
|
||||
cursor: pointer;
|
||||
color: var(--color-text-link);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.link2,
|
||||
.link2:visited {
|
||||
@include typography(var(--font-size-xs), var(--line-height-s), var(--font-weight-regular));
|
||||
|
||||
cursor: pointer;
|
||||
color: var(--color-text-link);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.error {
|
||||
@include typography(var(--font-size-xs), var(--line-height-m), var(--font-weight-regular));
|
||||
|
||||
color: var(--color-danger-300);
|
||||
}
|
||||
123
src/components/ui/typography/typography.stories.tsx
Normal file
123
src/components/ui/typography/typography.stories.tsx
Normal file
@@ -0,0 +1,123 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import { Typography } from './'
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Typography',
|
||||
component: Typography,
|
||||
tags: ['autodocs'],
|
||||
argTypes: {
|
||||
variant: {
|
||||
options: [
|
||||
'large',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'body1',
|
||||
'body2',
|
||||
'subtitle1',
|
||||
'subtitle2',
|
||||
'caption',
|
||||
'overline',
|
||||
'link1',
|
||||
'link2',
|
||||
'error',
|
||||
],
|
||||
control: { type: 'radio' },
|
||||
},
|
||||
},
|
||||
} satisfies Meta<typeof Typography>
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Large: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'large',
|
||||
},
|
||||
}
|
||||
|
||||
export const H1: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'h1',
|
||||
},
|
||||
}
|
||||
|
||||
export const H2: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'h2',
|
||||
},
|
||||
}
|
||||
|
||||
export const H3: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'h3',
|
||||
},
|
||||
}
|
||||
|
||||
export const Body1: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'body1',
|
||||
},
|
||||
}
|
||||
|
||||
export const Body2: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'body2',
|
||||
},
|
||||
}
|
||||
|
||||
export const Subtitle1: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'subtitle1',
|
||||
},
|
||||
}
|
||||
|
||||
export const Subtitle2: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'subtitle2',
|
||||
},
|
||||
}
|
||||
|
||||
export const Caption: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'caption',
|
||||
},
|
||||
}
|
||||
|
||||
export const Overline: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'overline',
|
||||
},
|
||||
}
|
||||
|
||||
export const Link1: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'link1',
|
||||
},
|
||||
}
|
||||
|
||||
export const Link2: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'link2',
|
||||
},
|
||||
}
|
||||
|
||||
export const Error: Story = {
|
||||
args: {
|
||||
children: 'Card content',
|
||||
variant: 'error',
|
||||
},
|
||||
}
|
||||
37
src/components/ui/typography/typography.tsx
Normal file
37
src/components/ui/typography/typography.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react'
|
||||
|
||||
import { clsx } from 'clsx'
|
||||
|
||||
import s from './typography.module.scss'
|
||||
|
||||
export interface TextProps<T extends ElementType> {
|
||||
as?: T
|
||||
variant?:
|
||||
| 'large'
|
||||
| 'h1'
|
||||
| 'h2'
|
||||
| 'h3'
|
||||
| 'body1'
|
||||
| 'body2'
|
||||
| 'subtitle1'
|
||||
| 'subtitle2'
|
||||
| 'caption'
|
||||
| 'overline'
|
||||
| 'link1'
|
||||
| 'link2'
|
||||
| 'error'
|
||||
children?: ReactNode
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function Typography<T extends ElementType = 'p'>({
|
||||
as,
|
||||
className,
|
||||
variant = 'body1',
|
||||
...restProps
|
||||
}: TextProps<T> & Omit<ComponentPropsWithoutRef<T>, keyof TextProps<T>>) {
|
||||
const classNames = clsx(s.text, s[variant], className)
|
||||
const Component = as || 'p'
|
||||
|
||||
return <Component className={classNames} {...restProps} />
|
||||
}
|
||||
13
src/styles/_tokens.scss
Normal file
13
src/styles/_tokens.scss
Normal file
@@ -0,0 +1,13 @@
|
||||
:root {
|
||||
/* outlines */
|
||||
--outline-focus: 2px solid var(--color-outline-focus);
|
||||
|
||||
/* transitions */
|
||||
--transition-duration-basic: 200ms;
|
||||
|
||||
/* border-radius */
|
||||
--border-radius-s: 0.25rem;
|
||||
|
||||
/* header */
|
||||
--header-height: 60px;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
@forward 'colors';
|
||||
@forward 'typography';
|
||||
@forward 'boilerplate';
|
||||
@forward 'tokens';
|
||||
|
||||
Reference in New Issue
Block a user