reza added PopularSearch and Input

master
Reza_ashrafi 3 years ago
parent 33f84f7c53
commit fec4a93dfd
  1. 16
      src/App.tsx
  2. BIN
      src/components/Input/danger.png
  3. 116
      src/components/Input/index.scss
  4. 179
      src/components/Input/index.tsx
  5. BIN
      src/components/Input/tick.png
  6. BIN
      src/components/PopularSearch/icon.png
  7. 115
      src/components/PopularSearch/index.scss
  8. 102
      src/components/PopularSearch/index.tsx
  9. BIN
      src/components/PopularSearch/x.png
  10. 3
      src/components/Search/index.scss
  11. 7
      src/components/Search/index.tsx
  12. 3
      src/global.scss

@ -1,10 +1,22 @@
import './global.scss'; import "./global.scss";
import Search from './components/Search'; import Search from "./components/Search";
import PopularSearch from "./components/PopularSearch";
import Input from "./components/Input";
function App() { function App() {
return ( return (
<div className="app"> <div className="app">
<Search /> <Search />
<hr />
<PopularSearch />
<hr />
<Input
label="نام و نام خانوادگی"
lang="fa"
status={false}
maxLength={30}
message={"اشتباه است."}
/>
</div> </div>
); );
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 B

@ -0,0 +1,116 @@
$primary: #06BACE;
$gray: #dbdbdb;
$danger: #E00A0A;
$success: #23C933;
.input {
display: flex;
flex-direction: column;
position: relative;
input{
flex: 1;
border-radius: 5px;
border: 1.7px solid $gray;
padding: 15px 11px 15px 30px;
font-size: 14px;
outline: 0px;
}
label{
position: absolute;
top: 50%;
font-size: 13px;
transform: translateY(-50%);
color: $gray;
background-color: white;
padding: 0px 5px;
}
&__labelFa{
right: 15px;
}
&__labelEn{
left: 15px;
}
&__labelFocus{
top: 0px !important;
font-size: 9px !important;
color: $primary !important;
}
&__labelDanger{
top: 0px !important;
font-size: 9px !important;
color: $danger !important;
}
&__labelSuccess{
top: 0px !important;
font-size: 9px !important;
color: $success !important;
}
&__inputActive{
border-color: $primary !important;
}
&__inputSuccess{
border-color: $success !important;
}
&__inputDanger{
border-color: $danger !important;
}
& img{
width : 18px;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
&__iconFa{
left: 15px;
}
&__iconEn{
right: 15px;
}
&__message{
position: absolute;
bottom: -25px;
font-size: 12px;
&En{
left: 5px;
}
&Fa{
right: 5px;
}
&Success{
color: $success;
}
&Danger{
color: $danger;
}
}
&__length{
position: absolute;
bottom: -25px;
font-size: 12px;
&En{
right: 5px;
}
&Fa{
left: 5px;
}
&Success{
color: $success;
}
&Danger{
color: $danger;
}
}
}
.en {
direction: ltr;
text-align: left;
}
.fa {
direction: rtl;
text-align: right;
}

@ -0,0 +1,179 @@
import React, { useState } from "react";
import _ from "lodash";
import tick from "./tick.png";
import danger from "./danger.png";
interface Types {
lang?: string;
theme?: string;
inputMode?: any;
label?: string;
status?: boolean;
maxLength?: number;
message?: string;
}
const langDetector = (lang: string, option1: any, option2: any) => {
return lang === "fa" ? option1 : option2;
};
const inputStatusHandler = (
value: string,
focus: boolean,
status: boolean,
primary: string,
success: string,
danger: string
) => {
if (!focus) {
return "";
} else {
if (!value) {
return primary;
} else {
if (status) {
return success;
} else {
return danger;
}
}
}
};
export default function Input(props: Types) {
const [value, setValue] = useState("");
const [focusToggle, setFocusToggle] = useState(false);
const { lang, theme, inputMode, label, status, maxLength, message } = props;
const onChange = (val: string) => {
setValue(val);
};
return (
<div
className={_.join(
["input", langDetector(lang as string, "fa", "en")],
" "
)}
>
<label
className={_.join(
[
langDetector(lang as string, "input__labelFa", "input__labelEn"),
"transition",
inputStatusHandler(
value,
focusToggle,
status as boolean,
"input__labelFocus",
"input__labelSuccess",
"input__labelDanger"
),
],
" "
)}
onClick={() => setFocusToggle(true)}
>
{label}
</label>
<input
type="text"
inputMode={inputMode}
className={_.join(
[
inputStatusHandler(
value,
focusToggle,
status as boolean,
"input__inputActive",
"input__inputSuccess",
"input__inputDanger"
),
"transition",
],
" "
)}
onChange={(e: any) => onChange(e.target.value)}
value={value}
onFocus={() => setFocusToggle(true)}
onBlur={() => !value && setFocusToggle(false)}
maxLength={maxLength}
/>
{!status && value && (
<img
src={danger}
alt={langDetector(lang as string, "اشتباه", "wrong")}
className={_.join(
[langDetector(lang as string, "input__iconFa", "input__iconEn")],
" "
)}
/>
)}
{status && value && (
<img
src={tick}
alt={langDetector(lang as string, "درست", "right")}
className={_.join(
[langDetector(lang as string, "input__iconFa", "input__iconEn")],
" "
)}
/>
)}
{value && !status && (
<span
className={_.join(
[
"input__message",
langDetector(
lang as string,
"input__messageFa",
"input__messageEn"
),
inputStatusHandler(
value,
focusToggle,
status as boolean,
"",
"input__messageSuccess",
"input__messageDanger"
),
"transition",
],
" "
)}
>
{message}
</span>
)}
{value && (
<span
className={_.join(
[
"input__length",
langDetector(
lang as string,
"input__lengthFa",
"input__lengthEn"
),
inputStatusHandler(
value,
focusToggle,
status as boolean,
"",
"input__lengthSuccess",
"input__lengthDanger"
),
"transition",
],
" "
)}
>
{value.length + '/' + maxLength}
</span>
)}
</div>
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 857 B

@ -0,0 +1,115 @@
$primary: #246e8a;
$gray: #dbdbdb;
$primary1: #EEFAFF;
.search {
display: flex;
flex-direction: column;
position: relative;
img{
cursor: pointer;
}
&__icon {
width: 27px;
position: absolute;
top: 50%;
transform: translateY(-50%);
&Fa {
left: 20px;
}
&En {
right: 20px;
}
}
&__x {
width: 15px;
position: absolute;
top: 50%;
transform: translateY(-50%);
opacity: 0;
&Fa {
right: 15px;
}
&En {
left: 10px;
}
&Active{
opacity: 1;
}
}
input {
padding: 15px 40px 15px 30px;
font-size: 14px;
border: 1.7px solid $gray;
border-radius: 5px;
background-color: inherit;
&::placeholder {
color: $gray;
}
&:focus {
border-color: $primary;
outline: 0px;
color: $primary;
&::placeholder {
color: $primary;
}
}
}
&__populars{
margin-top: 10px;
width: 100%;
border: 1.7px solid $gray;
border-radius: 5px;
background-color: white;
display: flex;
flex-direction: column;
list-style: none;
position: absolute;
top: 50px;
left: 0px;
opacity: 0;
display: none;
z-index: 100;
&Active{
opacity: 1;
display: flex;
}
strong{
width: 100%;
padding: 15px 40px;
font-size: 15px;
}
ul{
width : calc(100% - 80px);
list-style: none;
margin: 0px auto;
padding: 0px;
li{
padding: 15px 5px;
&:hover{
background-color: $primary1;
}
cursor: pointer;
font-size: 13px;
}
hr{
margin: 0px auto;
margin: 0px;
border: 0.5px solid #eee;
}
}
}
}
.en {
direction: ltr;
text-align: left;
}
.fa {
direction: rtl;
text-align: right;
}

@ -0,0 +1,102 @@
import React, { useState } from "react";
import _ from "lodash";
import searchIcon from "./icon.png";
import xIcon from "./x.png";
interface Types {
lang?: string;
theme?: string;
populars?: Array<string>;
}
const langDetector = (lang: string, option1: any, option2: any) => {
return lang === "fa" ? option1 : option2;
};
export default function PopularSearch(props: Types) {
const [value, setValue] = useState("");
const [popularsToggle, setPopularsToggle] = useState(false);
const { lang, theme, populars } = props;
const onChange = (val: string) => {
setValue(val);
};
return (
<div
className={_.join(
["search", langDetector(lang as string, "fa", "en")],
" "
)}
>
<input
type="search"
className="transition"
onChange={(e: any) => onChange(e.target.value)}
value={value}
placeholder={langDetector(
lang as string,
"نام کالا را جستجو کنید",
"search product name"
)}
onFocus={() => setPopularsToggle(true)}
onBlur={() => setPopularsToggle(false)}
/>
<img
src={searchIcon}
alt={langDetector(lang as string, "جستجو", "search")}
className={_.join(
[
"search__icon",
langDetector(lang as string, "search__iconFa", "search__iconEn"),
],
" "
)}
/>
<img
src={xIcon}
alt={langDetector(lang as string, "پاک کردن", "clear")}
className={_.join(
[
"search__x",
"transition",
langDetector(lang as string, "search__xFa", "search__xEn"),
value ? "search__xActive" : "",
],
" "
)}
onClick={() => setValue("")}
/>
<div
className={_.join(
[
"search__populars",
popularsToggle ? "search__popularsActive" : "",
"transition",
],
" "
)}
>
<strong>
{langDetector(lang as string, "جستجوهای پرطرفدار", "Popular search")}
</strong>
<ul>
{populars?.map((item: string, i: any) => (
<>
<li key={i} className="transition" onClick={() => setValue(() => item)}>
{item}
</li>
{i !== populars?.length - 1 && <hr />}
</>
))}
</ul>
</div>
</div>
);
}
PopularSearch.defaultProps = {
lang: "fa",
theme: "light",
populars: ["علی", "علیرضا", "محمد", "محمدرضا"],
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

@ -5,6 +5,9 @@ $gray: #dbdbdb;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative; position: relative;
img{
cursor: pointer;
}
&__icon { &__icon {
width: 27px; width: 27px;
position: absolute; position: absolute;

@ -13,17 +13,11 @@ const langDetector = (lang: string, option1: any, option2: any) => {
}; };
export default function Search(props: Types) { export default function Search(props: Types) {
const [clear, setClear] = useState(false);
const [value, setValue] = useState(""); const [value, setValue] = useState("");
const { lang, theme } = props; const { lang, theme } = props;
const onChange = (val: string) => { const onChange = (val: string) => {
setValue(val); setValue(val);
if (val.length) {
setClear(true);
} else {
setClear(false);
}
}; };
return ( return (
@ -61,6 +55,7 @@ export default function Search(props: Types) {
langDetector(lang as string, "search__xFa", "search__xEn"), langDetector(lang as string, "search__xFa", "search__xEn"),
value ? "search__xActive" : "", value ? "search__xActive" : "",
], " ")} ], " ")}
onClick={() => setValue("")}
/> />
</div> </div>
); );

@ -1,11 +1,12 @@
@import './components/Search/index.scss'; @import './components/Search/index.scss';
@import './components/PopularSearch/index.scss';
@import './components/Input/index.scss';
.app{ .app{
padding: 50px 20px; padding: 50px 20px;
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background-color: black;
} }
.transition{ .transition{

Loading…
Cancel
Save