feat: add input
This commit is contained in:
@@ -21,4 +21,5 @@ $color-lightgray: #E4E1E1;
|
|||||||
$color-darkgray: #999999;
|
$color-darkgray: #999999;
|
||||||
$color-text: #333333;
|
$color-text: #333333;
|
||||||
$color-text-light: #222222;
|
$color-text-light: #222222;
|
||||||
$color-mark: #E96526;
|
$color-mark: #E96526;
|
||||||
|
$color-error: #FF0000;
|
||||||
@@ -1,14 +1,113 @@
|
|||||||
.Container {
|
.input {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: flex-start;
|
||||||
padding: 15px 40px;
|
width: 100%;
|
||||||
width: max-content;
|
height: 42px;
|
||||||
border: 1px solid $color-darkgray;
|
border: 1px solid $color-darkgray;
|
||||||
border-radius: 28px;
|
border-radius: 28px;
|
||||||
background: $color-white;
|
|
||||||
|
//@include iftablet {
|
||||||
|
// height: rem(53px);
|
||||||
|
//}
|
||||||
|
|
||||||
|
&__self {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 22px 16px 6px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 100%;
|
||||||
|
color: $color-text;
|
||||||
|
opacity: 0.9;
|
||||||
|
|
||||||
|
//@include iftablet {
|
||||||
|
// padding: rem(26px) rem(16px) rem(6px) rem(16px);
|
||||||
|
// font-size: rem(16px);
|
||||||
|
// line-height: 130%;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__placeholder {
|
||||||
|
position: absolute;
|
||||||
|
top: 12px;
|
||||||
|
left: 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 130%;
|
||||||
|
color: $color-darkgray;
|
||||||
|
opacity: 0.4;
|
||||||
|
transition: all 0.15s ease-in;
|
||||||
|
|
||||||
|
//@include iftablet {
|
||||||
|
// top: rem(16px);
|
||||||
|
// font-size: rem(16px);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__placeholder_active {
|
||||||
|
top: 6px;
|
||||||
|
left: 16px;
|
||||||
|
font-size: 11px;
|
||||||
|
color: $color-darkgray;
|
||||||
|
|
||||||
|
//@include iftablet {
|
||||||
|
// top: rem(6px);
|
||||||
|
// left: rem(16px);
|
||||||
|
// font-size: rem(14px);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error {
|
||||||
|
border-color: $color-error !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__errorMessage {
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 130%;
|
||||||
|
color: $color-error;
|
||||||
|
|
||||||
|
//@include iftablet {
|
||||||
|
// margin-top: 6px;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
color: $color-lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__password-rules {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 6px;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
//@include iftablet {
|
||||||
|
// gap: rem(10px);
|
||||||
|
//}
|
||||||
|
//@include ifdesktop {
|
||||||
|
// margin-top: rem(9px);
|
||||||
|
//}
|
||||||
|
|
||||||
|
&__rule-block {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__rule-text {
|
||||||
|
font-family: $font-open-sans;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 100%;
|
||||||
|
color: rgba(35, 48, 56, 0.7);
|
||||||
|
|
||||||
|
//@include iftablet {
|
||||||
|
// font-size: rem(14px);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.Input {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,69 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
import s from './input.module.scss';
|
import s from './input.module.scss';
|
||||||
import { clsx } from 'clsx';
|
|
||||||
import { DetailedHTMLProps, InputHTMLAttributes } from 'react';
|
|
||||||
|
|
||||||
type InputProps = {
|
import React, { InputHTMLAttributes, useState } from 'react';
|
||||||
outerClassName?: string;
|
import clsx from 'clsx';
|
||||||
variant?: 'default' | 'outlined';
|
|
||||||
} & DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
|
|
||||||
|
|
||||||
export default function input({
|
type InputPropsType = {
|
||||||
outerClassName,
|
className?: string;
|
||||||
variant = 'default',
|
placeholder: string;
|
||||||
|
errorMessage?: string | boolean;
|
||||||
|
} & InputHTMLAttributes<HTMLInputElement>;
|
||||||
|
|
||||||
|
const Input = ({
|
||||||
|
placeholder,
|
||||||
|
errorMessage,
|
||||||
|
disabled,
|
||||||
|
className,
|
||||||
|
onChange,
|
||||||
...props
|
...props
|
||||||
}: InputProps) {
|
}: InputPropsType) => {
|
||||||
|
const [onFocus, setOnFocus] = useState(false);
|
||||||
|
|
||||||
|
const hasValue =
|
||||||
|
typeof props.value === 'string'
|
||||||
|
? props.value.length > 0
|
||||||
|
: props.value !== undefined && props.value !== null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div>
|
||||||
className={clsx(s.Container, s['Container_' + variant], outerClassName)}
|
<div
|
||||||
>
|
className={clsx(s.input, className, {
|
||||||
<input {...props} className={clsx(s.Input, s['Input_' + variant])} />
|
[s['input--error']]: !!errorMessage,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
className={clsx(s.input__placeholder, {
|
||||||
|
[s.input__placeholder_active]: hasValue || onFocus,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{placeholder}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
{...props}
|
||||||
|
onChange={onChange}
|
||||||
|
onFocus={(event) => {
|
||||||
|
if (typeof props.onFocus !== 'undefined') {
|
||||||
|
props.onFocus(event);
|
||||||
|
}
|
||||||
|
setOnFocus(true);
|
||||||
|
}}
|
||||||
|
onBlur={(event) => {
|
||||||
|
if (typeof props.onBlur !== 'undefined') {
|
||||||
|
props.onBlur(event);
|
||||||
|
}
|
||||||
|
setOnFocus(false);
|
||||||
|
}}
|
||||||
|
disabled={disabled}
|
||||||
|
className={clsx(s.input__self, { [s['input--disabled']]: disabled })}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{errorMessage && (
|
||||||
|
<span className={s.input__errorMessage}>{errorMessage}</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default Input;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
'use client';
|
||||||
import s from './offer.module.scss';
|
import s from './offer.module.scss';
|
||||||
|
|
||||||
import { Button, Mark, Input } from '@shared/ui';
|
import { Button, Mark, Input } from '@shared/ui';
|
||||||
@@ -11,8 +12,11 @@ import gridFour from '@public/images/grid-4.png';
|
|||||||
import gridFive from '@public/images/grid-5.png';
|
import gridFive from '@public/images/grid-5.png';
|
||||||
import gridSix from '@public/images/grid-6.png';
|
import gridSix from '@public/images/grid-6.png';
|
||||||
import bgForm from '@public/images/bg-form.jpg';
|
import bgForm from '@public/images/bg-form.jpg';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
export default function Offer() {
|
export default function Offer() {
|
||||||
|
const [name, setName] = useState('');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={s.Offer}>
|
<section className={s.Offer}>
|
||||||
<h2 className={s.Title}>
|
<h2 className={s.Title}>
|
||||||
@@ -38,7 +42,12 @@ export default function Offer() {
|
|||||||
</ul>
|
</ul>
|
||||||
<div className={s.RowForm}>
|
<div className={s.RowForm}>
|
||||||
<Input type='text' placeholder='+79991234567' />
|
<Input type='text' placeholder='+79991234567' />
|
||||||
<Input type='text' placeholder='Ваше имя' />
|
<Input
|
||||||
|
type='text'
|
||||||
|
placeholder=''
|
||||||
|
value={name}
|
||||||
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
/>
|
||||||
<Button>Узнать подробности</Button>
|
<Button>Узнать подробности</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className={s.Inner}>
|
<div className={s.Inner}>
|
||||||
|
|||||||
Reference in New Issue
Block a user