@ -0,0 +1,10 @@ |
||||
module.exports = { |
||||
style: { |
||||
postcss: { |
||||
plugins: [ |
||||
require('tailwindcss'), |
||||
require('autoprefixer'), |
||||
], |
||||
}, |
||||
}, |
||||
} |
@ -0,0 +1,30 @@ |
||||
import React from "react"; |
||||
import './index.scss'; |
||||
|
||||
export default function Checkbox(props) { |
||||
return ( |
||||
<div> |
||||
<svg className="checkbox-symbol"> |
||||
<symbol id="check" viewBox="0 0 12 10"> |
||||
<polyline |
||||
points="1.5 6 4.5 9 10.5 1" |
||||
stroke-linecap="round" |
||||
stroke-linejoin="round" |
||||
stroke-width="2" |
||||
></polyline> |
||||
</symbol> |
||||
</svg> |
||||
|
||||
<div className="checkbox-container"> |
||||
<input className="checkbox-input" id="apples" type="checkbox" checked={props.checked} /> |
||||
<label className="checkbox" htmlFor="apples"> |
||||
<span> |
||||
<svg width="12px" height="10px"> |
||||
<use xlinkHref="#check"></use> |
||||
</svg> |
||||
</span> |
||||
</label> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,97 @@ |
||||
.checkbox-symbol { |
||||
position: absolute; |
||||
width: 0; |
||||
height: 0; |
||||
pointer-events: none; |
||||
user-select: none; |
||||
} |
||||
|
||||
.checkbox-container { |
||||
box-sizing: border-box; |
||||
color: #222; |
||||
height: 30px; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
flex-flow: row wrap; |
||||
} |
||||
|
||||
.checkbox-container * { |
||||
box-sizing: border-box; |
||||
} |
||||
|
||||
.checkbox-input { |
||||
position: absolute; |
||||
visibility: hidden; |
||||
} |
||||
|
||||
.checkbox { |
||||
user-select: none; |
||||
cursor: pointer; |
||||
padding: 6px 8px; |
||||
border-radius: 6px; |
||||
overflow: hidden; |
||||
transition: all 0.3s ease; |
||||
display: flex; |
||||
} |
||||
|
||||
.checkbox:not(:last-child) { |
||||
margin-right: 6px; |
||||
} |
||||
|
||||
.checkbox:hover { |
||||
background: inherit; |
||||
} |
||||
|
||||
.checkbox span { |
||||
vertical-align: middle; |
||||
transform: translate3d(0, 0, 0); |
||||
} |
||||
|
||||
.checkbox span:first-child { |
||||
position: relative; |
||||
flex: 0 0 18px; |
||||
width: 18px; |
||||
height: 18px; |
||||
border-radius: 4px; |
||||
transform: scale(1); |
||||
border: 1px solid #cccfdb; |
||||
transition: all 0.3s ease; |
||||
} |
||||
|
||||
.checkbox span:first-child svg { |
||||
position: absolute; |
||||
top: 3px; |
||||
left: 2px; |
||||
fill: none; |
||||
stroke: #fff; |
||||
stroke-dasharray: 16px; |
||||
stroke-dashoffset: 16px; |
||||
transition: all 0.3s ease; |
||||
transform: translate3d(0, 0, 0); |
||||
} |
||||
|
||||
.checkbox span:last-child { |
||||
padding-left: 8px; |
||||
line-height: 18px; |
||||
} |
||||
|
||||
.checkbox:hover span:first-child { |
||||
border-color: #0077ff; |
||||
} |
||||
|
||||
.checkbox-input:checked + .checkbox span:first-child { |
||||
background: #0077ff; |
||||
border-color: #0077ff; |
||||
animation: zoom-in-out 0.3s ease; |
||||
} |
||||
|
||||
.checkbox-input:checked + .checkbox span:first-child svg { |
||||
stroke-dashoffset: 0; |
||||
} |
||||
|
||||
@keyframes zoom-in-out { |
||||
50% { |
||||
transform: scale(0.9); |
||||
} |
||||
} |
After Width: | Height: | Size: 860 B |
@ -0,0 +1,162 @@ |
||||
import React, { useState } from "react"; |
||||
import _ from "lodash"; |
||||
import "./index.scss"; |
||||
|
||||
import tick from "./tick.png"; |
||||
import danger from "./danger.png"; |
||||
|
||||
const langDetector = (lang, option1, option2) => { |
||||
return lang === "fa" ? option1 : option2; |
||||
}; |
||||
|
||||
const inputStatusHandler = (value, focus, status, primary, success, danger) => { |
||||
if (!focus) { |
||||
return ""; |
||||
} else { |
||||
if (!value) { |
||||
return primary; |
||||
} else { |
||||
if (status) { |
||||
return success; |
||||
} else { |
||||
return danger; |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
|
||||
export default function Input(props) { |
||||
const [value, setValue] = useState(""); |
||||
const [focusToggle, setFocusToggle] = useState(false); |
||||
|
||||
const { lang, theme, inputMode, label, status, maxLength, message } = props; |
||||
|
||||
const onChange = (val) => { |
||||
setValue(val); |
||||
}; |
||||
|
||||
return ( |
||||
<div |
||||
className={_.join( |
||||
["input flex flex-col relative mb-6", langDetector(lang, "fa", "en")], |
||||
" " |
||||
)} |
||||
> |
||||
<label |
||||
className={_.join( |
||||
[ |
||||
"absolute top-1/2 transform -translate-y-1/2 text-gray-500 bg-white px-2 text-xs transition-all duration-300", |
||||
langDetector(lang, "right-2", "left-2"), |
||||
inputStatusHandler( |
||||
value, |
||||
focusToggle, |
||||
status, |
||||
"input__labelFocus", |
||||
"input__labelSuccess", |
||||
"input__labelDanger" |
||||
), |
||||
], |
||||
" " |
||||
)} |
||||
onClick={() => setFocusToggle(true)} |
||||
> |
||||
{label} |
||||
</label> |
||||
<input |
||||
type="text" |
||||
inputMode={inputMode} |
||||
className={_.join( |
||||
[ |
||||
"flex-1 border rounded-sm outline-none p-2", |
||||
inputStatusHandler( |
||||
value, |
||||
focusToggle, |
||||
status, |
||||
"input__inputActive", |
||||
"input__inputSuccess", |
||||
"input__inputDanger" |
||||
), |
||||
"transition", |
||||
], |
||||
" " |
||||
)} |
||||
onChange={(e) => onChange(e.target.value)} |
||||
value={value} |
||||
onFocus={() => setFocusToggle(true)} |
||||
onBlur={() => !value ? setFocusToggle(false) : setFocusToggle(true)} |
||||
maxLength={maxLength} |
||||
/> |
||||
{!status && value && ( |
||||
<img |
||||
src={danger} |
||||
alt={langDetector(lang, "اشتباه", "wrong")} |
||||
className={_.join( |
||||
[ |
||||
"w-4 h-4 absolute top-1/2 transform -translate-y-1/2", |
||||
langDetector(lang, "left-2", "right-2"), |
||||
], |
||||
" " |
||||
)} |
||||
/> |
||||
)} |
||||
{status && value && ( |
||||
<img |
||||
src={tick} |
||||
alt={langDetector(lang, "درست", "right")} |
||||
className={_.join( |
||||
[ |
||||
"w-4 h-4 absolute top-1/2 transform -translate-y-1/2", |
||||
langDetector(lang, "left-2", "right-2"), |
||||
], |
||||
" " |
||||
)} |
||||
/> |
||||
)} |
||||
|
||||
{value && !status && ( |
||||
<span |
||||
className={_.join( |
||||
[ |
||||
"input__message text-xs absolute -bottom-5", |
||||
langDetector(lang, "right-2", "left-2"), |
||||
inputStatusHandler( |
||||
value, |
||||
focusToggle, |
||||
status, |
||||
"", |
||||
"input__messageSuccess", |
||||
"input__messageDanger" |
||||
), |
||||
"transition", |
||||
], |
||||
" " |
||||
)} |
||||
> |
||||
{message} |
||||
</span> |
||||
)} |
||||
{value && ( |
||||
<span |
||||
className={_.join( |
||||
[ |
||||
"input__length absolute -bottom-5 text-xs", |
||||
langDetector(lang, "left-2", "right-2"), |
||||
inputStatusHandler( |
||||
value, |
||||
focusToggle, |
||||
status, |
||||
"", |
||||
"input__lengthSuccess", |
||||
"input__lengthDanger" |
||||
), |
||||
"transition", |
||||
], |
||||
" " |
||||
)} |
||||
> |
||||
{value.length + "/" + maxLength} |
||||
</span> |
||||
)} |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,60 @@ |
||||
$primary: #06BACE; |
||||
$gray: #dbdbdb; |
||||
$danger: #E00A0A; |
||||
$success: #23C933; |
||||
|
||||
.input { |
||||
&__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; |
||||
} |
||||
|
||||
&__message{ |
||||
&Success{ |
||||
color: $success; |
||||
} |
||||
&Danger{ |
||||
color: $danger; |
||||
} |
||||
} |
||||
&__length{ |
||||
&Success{ |
||||
color: $success; |
||||
} |
||||
&Danger{ |
||||
color: $danger; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.en { |
||||
direction: ltr; |
||||
text-align: left; |
||||
} |
||||
|
||||
.fa { |
||||
direction: rtl; |
||||
text-align: right; |
||||
} |
After Width: | Height: | Size: 411 B |
@ -0,0 +1,13 @@ |
||||
import React from "react"; |
||||
import './index.scss'; |
||||
|
||||
export default function Radio(props) { |
||||
return ( |
||||
<div className="container"> |
||||
<div className="radio flex items-center"> |
||||
<input id="radio-1" name={props.name} type="radio" /> |
||||
<label htmlFor="radio-1" className="radio-label text-xs">{props.label}</label> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,58 @@ |
||||
$color1: #f4f4f4; |
||||
$color2: #3197EE; |
||||
|
||||
.radio { |
||||
input[type="radio"] { |
||||
position: absolute; |
||||
opacity: 0; |
||||
+ .radio-label { |
||||
&:before { |
||||
content: ''; |
||||
background: $color1; |
||||
border-radius: 100%; |
||||
border: 1px solid darken($color1, 25%); |
||||
display: inline-block; |
||||
width: 1.4em; |
||||
height: 1.4em; |
||||
position: relative; |
||||
vertical-align: top; |
||||
margin-left: 0.5em; |
||||
cursor: pointer; |
||||
text-align: center; |
||||
transition: all 250ms ease; |
||||
} |
||||
} |
||||
&:checked { |
||||
+ .radio-label { |
||||
&:before { |
||||
background-color: $color2; |
||||
box-shadow: inset 0 0 0 4px $color1; |
||||
} |
||||
} |
||||
} |
||||
&:focus { |
||||
+ .radio-label { |
||||
&:before { |
||||
outline: none; |
||||
border-color: $color2; |
||||
} |
||||
} |
||||
} |
||||
&:disabled { |
||||
+ .radio-label { |
||||
&:before { |
||||
box-shadow: inset 0 0 0 4px $color1; |
||||
border-color: darken($color1, 25%); |
||||
background: darken($color1, 25%); |
||||
} |
||||
} |
||||
} |
||||
+ .radio-label { |
||||
&:empty { |
||||
&:before { |
||||
margin-right: 0; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,31 @@ |
||||
import React from "react"; |
||||
import _ from "lodash"; |
||||
import searchIcon from "./search.png"; |
||||
|
||||
const langDetector = (lang = 'fa', option1, option2) => { |
||||
return lang === "fa" ? option1 : option2; |
||||
}; |
||||
|
||||
export default function Search(props) { |
||||
return ( |
||||
<div className="flex items-center justify-center w-full"> |
||||
<div className="relative text-gray-600 focus-within:text-gray-400 w-full"> |
||||
<span className={_.join(["absolute inset-y-0 flex items-center pl-2", langDetector(props.lang, "left-0", "right-0")], " ")}> |
||||
<button |
||||
type="submit" |
||||
className="p-1 focus:outline-none focus:shadow-outline" |
||||
> |
||||
<img src={searchIcon} className="w-6 h-6" alt="" /> |
||||
</button> |
||||
</span> |
||||
<input |
||||
type="search" |
||||
name="q" |
||||
className="w-full py-2 text-sm text-white border rounded-sm pr-5 outline-none focus:ring-1 focus:text-gray-900" |
||||
placeholder={_.join([langDetector(props.lang , "جستجو...", "Search...")], " ")} |
||||
autocomplete="off" |
||||
/> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
After Width: | Height: | Size: 857 B |
After Width: | Height: | Size: 229 B |
@ -0,0 +1,108 @@ |
||||
import React, { useState } from "react"; |
||||
import _ from "lodash"; |
||||
import Checkbox from "../Checkbox"; |
||||
|
||||
import arrowIcon from "./arrow-top.png"; |
||||
|
||||
const langDetector = (lang, option1, option2) => { |
||||
return lang === "fa" ? option1 : option2; |
||||
}; |
||||
export default function SelectCheckbox(props) { |
||||
const [selectedItem, setSelectedItem] = useState(""); |
||||
const [value, setValue] = useState(""); |
||||
|
||||
const [toggle, setToggle] = useState(false); |
||||
const { lang, theme, list, label } = props; |
||||
|
||||
const onChangeItem = (val) => { |
||||
setSelectedItem(val); |
||||
}; |
||||
|
||||
const onChangeText = (val) => { |
||||
setValue(val); |
||||
}; |
||||
|
||||
return ( |
||||
<div |
||||
className={_.join( |
||||
["select-search flex flex-col relative", langDetector(lang, "fa", "en")], |
||||
" " |
||||
)} |
||||
> |
||||
<div |
||||
className={_.join( |
||||
["search flex flex-column relative", langDetector(lang, "fa", "en")], |
||||
" " |
||||
)} |
||||
onClick={() => setToggle(() => !toggle)} |
||||
> |
||||
<input |
||||
type="search" |
||||
className="w-full py-3 px-3 text-xs border rounded-sm bg-transparent placeholder-gray-500" |
||||
onChange={(e) => onChangeText(e.target.value)} |
||||
placeholder={langDetector(lang, "تنظیمات", "setting")} |
||||
disabled |
||||
/> |
||||
<img |
||||
src={arrowIcon} |
||||
alt="" |
||||
className={_.join( |
||||
[ |
||||
"cursor-pointer w-5 absolute top-1/2 transform -translate-y-1/2 transition-all duration-300", |
||||
langDetector(lang, "left-3", "right-3"), |
||||
toggle ? '-rotate-180' : '', |
||||
], |
||||
" " |
||||
)} |
||||
/> |
||||
</div> |
||||
{toggle && ( |
||||
<div |
||||
className={_.join( |
||||
[ |
||||
"select-search__list absolute top-12 left-0 flex flex-col px-5 border rounded-sm w-full bg-white z-20", |
||||
toggle ? "select-search__listActive" : "", |
||||
"transition", |
||||
], |
||||
" " |
||||
)} |
||||
> |
||||
<ul className="list-none p-0 divide-y divide-gray-200 w-full"> |
||||
{list?.map((item, i) => ( |
||||
<> |
||||
<li key={i} className="w-full py-1 text-gray-700 flex items-start flex-col"> |
||||
<div className="flex items-center"> |
||||
<Checkbox checked={false} /> |
||||
<span className="text-xs">{item?.name}</span> |
||||
</div> |
||||
<ul className="w-full p-0 mx-auto my-0"> |
||||
{item.sublist?.map((item1, j) => ( |
||||
<> |
||||
<li className="flex flex-row flex-1 pt-1 px-5 pb-0 items-center" key={j}> |
||||
<Checkbox checked={false} /> |
||||
<span className="text-xs">{item1?.name}</span> |
||||
</li> |
||||
</> |
||||
))} |
||||
</ul> |
||||
</li> |
||||
</> |
||||
))} |
||||
</ul> |
||||
</div> |
||||
)} |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
SelectCheckbox.defaultProps = { |
||||
lang: "fa", |
||||
theme: "light", |
||||
label: "کشور خود را انتخاب کنید", |
||||
list: [ |
||||
{ name: "وسایل آشپزخانه", sublist: [{ name: "اتو" }] }, |
||||
{ name: "غریق نجات از تمام جهات" }, |
||||
{ name: "قاشق و چنگال" }, |
||||
{ name: "وسایل آشپزخانه" }, |
||||
], |
||||
}; |
After Width: | Height: | Size: 229 B |
@ -0,0 +1,100 @@ |
||||
import React, { useState } from "react"; |
||||
import _ from "lodash"; |
||||
import Radio from "../Radio"; |
||||
|
||||
import xIcon from "./x.png"; |
||||
import arrowIcon from "./arrow-top.png"; |
||||
|
||||
|
||||
const langDetector = (lang, option1, option2) => { |
||||
return lang === "fa" ? option1 : option2; |
||||
}; |
||||
|
||||
export default function SelectRadio(props) { |
||||
const [selectedItem, setSelectedItem] = useState(""); |
||||
const [value, setValue] = useState(""); |
||||
|
||||
const [toggle, setToggle] = useState(false); |
||||
const { lang, theme, list, label } = props; |
||||
|
||||
const onChangeItem = (val) => { |
||||
setSelectedItem(val); |
||||
}; |
||||
|
||||
const onChangeText = (val) => { |
||||
setValue(val); |
||||
}; |
||||
|
||||
return ( |
||||
<div |
||||
className={_.join( |
||||
[ |
||||
"flex flex-col relative", |
||||
langDetector(lang, "fa", "en"), |
||||
], |
||||
" " |
||||
)} |
||||
> |
||||
<div |
||||
className={_.join( |
||||
["flex flex-col relative", langDetector(lang, "fa", "en")], |
||||
" " |
||||
)} |
||||
onClick={() => setToggle(() => !toggle)} |
||||
> |
||||
<input |
||||
type="search" |
||||
className="py-3 px-3 text-xs border rounded-sm bg-transparent focus:ring-1 outline-none focus:placeholder-blue-500 placeholder-gray-500" |
||||
onChange={(e) => onChangeText(e.target.value)} |
||||
placeholder={langDetector(lang, "تنظیمات", "setting")} |
||||
disabled |
||||
/> |
||||
<img |
||||
src={arrowIcon} |
||||
alt="" |
||||
className={_.join( |
||||
[ |
||||
"w-5 absolute top-1/2 transform -translate-y-1/2 cursor-pointer transition-all duration-300", |
||||
langDetector(lang, "left-3", "right-3"), |
||||
toggle ? '-rotate-180' : '' |
||||
], |
||||
" " |
||||
)} |
||||
/> |
||||
</div> |
||||
{toggle && ( |
||||
<div |
||||
className={_.join( |
||||
[ |
||||
"w-full absolute top-12 left-0 flex flex-col border rounded-sm bg-white z-20", |
||||
toggle ? "select-search__listActive" : "", |
||||
], |
||||
" " |
||||
)} |
||||
> |
||||
<ul className="list-none divide-y divide-gray-200 py-1 text-gray-700 w-full px-3"> |
||||
{list?.map((item, i) => ( |
||||
<> |
||||
<li key={i} className="transition w-full text-gray-700 items-center py-3 flex-col justify-center"> |
||||
<Radio label={item?.name} name="reza" /> |
||||
</li> |
||||
</> |
||||
))} |
||||
</ul> |
||||
</div> |
||||
)} |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
SelectRadio.defaultProps = { |
||||
lang: "fa", |
||||
theme: "light", |
||||
label: "کشور خود را انتخاب کنید", |
||||
list: [ |
||||
{ name: "وسایل آشپزخانه", sublist: [{ name: "اتو" }] }, |
||||
{ name: "غریق نجات از تمام جهات" }, |
||||
{ name: "قاشق و چنگال" }, |
||||
{ name: "وسایل آشپزخانه" }, |
||||
], |
||||
}; |
After Width: | Height: | Size: 346 B |
@ -0,0 +1,9 @@ |
||||
import React from 'react' |
||||
|
||||
export default function Col() { |
||||
return ( |
||||
<div> |
||||
|
||||
</div> |
||||
) |
||||
} |
@ -0,0 +1,66 @@ |
||||
import React, { useState } from "react"; |
||||
import category from "./data"; |
||||
import _ from "lodash"; |
||||
|
||||
export default function SidebarCategoryHover() { |
||||
const [activeItem, setActiveItem] = useState(null); |
||||
|
||||
const arrayLength = category.length; |
||||
|
||||
return ( |
||||
<div className="flex flex-col w-60 relative" onMouseOut={() => setActiveItem(null)}> |
||||
<ul className="list-none w-full divide-y border divide-gray-200"> |
||||
{category.map((item, i) => ( |
||||
<> |
||||
<li |
||||
className="p-4 w-full text-gray-500 font-normal text-sm hover:bg-blue-100 text-right" |
||||
key={i} |
||||
onMouseOver={() => setActiveItem(item.id)} |
||||
> |
||||
{item.name} |
||||
</li> |
||||
<ul |
||||
className={_.join( |
||||
[ |
||||
"absolute right-60 top-0 h-full border flex-row divide-x divide-gray-200", |
||||
activeItem === item.id ? "flex" : "hidden", |
||||
], |
||||
" " |
||||
)} |
||||
onMouseOver={() => setActiveItem(item.id)} |
||||
// style={{width : 1000}}
|
||||
> |
||||
<li className="h-full w-52 bg-red-50 flex flex-col text-right"> |
||||
<li className="flex items-center" style={{ minHeight: "calc(100% / 9)" }}> |
||||
{item.categories[0].name} |
||||
</li> |
||||
{item.categories[0].list.map((item1, i) => ( |
||||
<li |
||||
key={i} |
||||
className="text-normal flex text-sm items-center" |
||||
style={{ minHeight: "calc(100% / 9)" }} |
||||
> |
||||
{item1.name} |
||||
</li> |
||||
))} |
||||
<li className="flex items-center" style={{ minHeight: "calc(100% / 9)" }}> |
||||
{item.categories[1].name} |
||||
</li> |
||||
{item.categories[1].list.map((item1, i) => ( |
||||
<li key={i} className="flex items-center" style={{ minHeight: "calc(100% / 9)" }}> |
||||
{item1.name} |
||||
</li> |
||||
))} |
||||
</li> |
||||
<li className="h-full w-52 bg-green-50"></li> |
||||
<li className="h-full w-52 bg-blue-50"></li> |
||||
<li className="h-full w-52 bg-red-50"></li> |
||||
<li className="h-full w-52 bg-green-50"></li> |
||||
<li className="h-full w-52 bg-blue-50"></li> |
||||
</ul> |
||||
</> |
||||
))} |
||||
</ul> |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,11 @@ |
||||
import React from "react"; |
||||
import "./index.scss"; |
||||
|
||||
export default function index() { |
||||
return ( |
||||
<div className="switch"> |
||||
<input type="checkbox" id="toggle" /> |
||||
<label for="toggle"></label> |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,52 @@ |
||||
// *, *:after, *:before { |
||||
// // box-sizing: border-box; |
||||
// } |
||||
|
||||
// body { |
||||
// min-height: 100vh; |
||||
// display: flex; |
||||
// align-items: center; |
||||
// justify-content: center; |
||||
// } |
||||
|
||||
.switch { |
||||
position: relative; |
||||
input[type="checkbox"] { |
||||
visibility: hidden; |
||||
position : absolute; |
||||
&:checked + label { |
||||
transform: rotate(0deg); |
||||
background-color: #000; |
||||
&:before { |
||||
transform: translateX(35.5px); |
||||
background-color: #fff; |
||||
} |
||||
} |
||||
} |
||||
|
||||
label { |
||||
display: flex; |
||||
width: 70px; |
||||
height: 34px; |
||||
border: 3px solid; |
||||
border-radius: 99em; |
||||
position: relative; |
||||
transition: transform 0.3s ease-in-out; |
||||
transform-origin: 50% 50%; |
||||
cursor: pointer; |
||||
|
||||
&:before { |
||||
transition: transform 0.3s ease; |
||||
transition-delay: 0s; |
||||
content: ""; |
||||
display: block; |
||||
position: absolute; |
||||
width: 24px; |
||||
height: 24px; |
||||
background-color: #000; |
||||
border-radius: 50%; |
||||
top: 2px; |
||||
left: 3px; |
||||
} |
||||
} |
||||
} |
After Width: | Height: | Size: 229 B |
@ -0,0 +1,170 @@ |
||||
import React, { useState, useEffect } from "react"; |
||||
import searchIcon from "./search.png"; |
||||
import _ from "lodash"; |
||||
import Checkbox from "../Checkbox"; |
||||
import arrowIcon from "./arrow-top.png"; |
||||
|
||||
const langDetector = (lang = "fa", option1, option2) => { |
||||
return lang === "fa" ? option1 : option2; |
||||
}; |
||||
|
||||
export default function VerticalExpandableProductFilter(props) { |
||||
const [text, setText] = useState(""); |
||||
const [searchResult, setSearchResult] = useState([]); |
||||
useEffect(() => { |
||||
let fakeSearchResult; |
||||
fakeSearchResult = props.list.filter( |
||||
(item1) => item1.name.indexOf(text) !== -1 |
||||
); |
||||
setSearchResult(fakeSearchResult); |
||||
}, [text]); |
||||
|
||||
return ( |
||||
<div className="flex flex-col w-full border rounded-md pt-6 bg-transparent max-h-screen"> |
||||
<strong className="text-md text-gray-500 w-full mb-3 text-right px-3"> |
||||
دسته بندی |
||||
</strong> |
||||
<form className="relative w-full px-3 mb-3"> |
||||
<input |
||||
type="text" |
||||
placeholder={_.join( |
||||
[langDetector(props.lang, "جستجو...", "Search...")], |
||||
" " |
||||
)} |
||||
className="border rounded-sm py-1 px-2 w-full placeholder-gray-300 outline-none text-gray-500" |
||||
onChange={(e) => setText(e.target.value)} |
||||
/> |
||||
<span |
||||
className={_.join( |
||||
[ |
||||
"absolute inset-y-0 flex items-center", |
||||
langDetector(props.lang, "left-4", "right-4"), |
||||
], |
||||
" " |
||||
)} |
||||
> |
||||
<button |
||||
type="submit" |
||||
className="p-1 focus:outline-none focus:shadow-outline" |
||||
> |
||||
<img src={searchIcon} className="w-5 h-5" alt="" /> |
||||
</button> |
||||
</span> |
||||
</form> |
||||
<ul className="w-full list-none flex flex-col divide-y divide-gray-100"> |
||||
{(searchResult.length > 0 ? searchResult : props.list)?.map( |
||||
(item1, i) => ( |
||||
<li |
||||
key={i} |
||||
className="hover:bg-gray-100 px-3 flex flex-row items-center justify-between py-2" |
||||
> |
||||
<div className="flex flex-row items-center"> |
||||
<Checkbox /> |
||||
<strong className="text-xs font-light text-gray-500"> |
||||
{item1.name} |
||||
</strong> |
||||
</div> |
||||
|
||||
{item1.subList?.length > 0 && ( |
||||
<img |
||||
src={arrowIcon} |
||||
alt="" |
||||
className={_.join( |
||||
[ |
||||
"cursor-pointer w-5 transform transition-all duration-300", |
||||
item1.expaneded ? "" : "rotate-180", |
||||
], |
||||
" " |
||||
)} |
||||
/> |
||||
)} |
||||
</li> |
||||
) |
||||
)} |
||||
</ul> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
VerticalExpandableProductFilter.defaultProps = { |
||||
list: [ |
||||
{ |
||||
id: 0, |
||||
name: "وسایل آشپزخانه", |
||||
expaneded: false, |
||||
subList: [], |
||||
}, |
||||
{ |
||||
id: 3, |
||||
name: "ماشین و موتور سیکلت", |
||||
expaneded: false, |
||||
subList: [ |
||||
{ |
||||
id: 4, |
||||
name: "ماشین", |
||||
}, |
||||
{ |
||||
id: 5, |
||||
name: "موتور", |
||||
}, |
||||
], |
||||
}, |
||||
{ |
||||
id: 6, |
||||
name: "اتاق خواب", |
||||
expaneded: false, |
||||
subList: [ |
||||
{ |
||||
id: 7, |
||||
name: "کمد", |
||||
}, |
||||
{ |
||||
id: 8, |
||||
name: "تخت خواب", |
||||
}, |
||||
], |
||||
}, |
||||
{ |
||||
id: 9, |
||||
name: "دکوراسیون و چیدمان", |
||||
expaneded: false, |
||||
subList: [], |
||||
}, |
||||
{ |
||||
id: 10, |
||||
name: "وسایل بهداشت شخصی", |
||||
expaneded: false, |
||||
subList: [ |
||||
{ |
||||
id: 11, |
||||
name: "مسواک", |
||||
}, |
||||
{ |
||||
id: 12, |
||||
name: "حوله", |
||||
}, |
||||
], |
||||
}, |
||||
{ |
||||
id: 13, |
||||
name: "وسایل بهداشت شخصی", |
||||
expaneded: false, |
||||
subList: [ |
||||
{ |
||||
id: 14, |
||||
name: "مسواک", |
||||
}, |
||||
{ |
||||
id: 15, |
||||
name: "حوله", |
||||
}, |
||||
], |
||||
}, |
||||
{ |
||||
id: 16, |
||||
name: "وسایل بهداشت شخصی", |
||||
expaneded: false, |
||||
subList: [], |
||||
}, |
||||
], |
||||
}; |
After Width: | Height: | Size: 857 B |
@ -0,0 +1,88 @@ |
||||
import React, { useState } from "react"; |
||||
import _ from "lodash"; |
||||
import searchIcon from "./search.png"; |
||||
|
||||
const langDetector = (lang, option1, option2) => { |
||||
return lang === "fa" ? option1 : option2; |
||||
}; |
||||
|
||||
export default function PopularSearch(props) { |
||||
const [value, setValue] = useState(""); |
||||
const [popularsToggle, setPopularsToggle] = useState(false); |
||||
const { lang, theme, populars } = props; |
||||
|
||||
const onChange = (val) => { |
||||
setValue(val); |
||||
}; |
||||
|
||||
return ( |
||||
<div |
||||
className={_.join( |
||||
["flex flex-col relative search", langDetector(lang, "fa", "en")], |
||||
" " |
||||
)} |
||||
> |
||||
<input |
||||
type="search" |
||||
className="transition py-2 pr-4 pl-2 mx-0 border rounded-sm outline-none focus:ring-1 placeholder-gray-500 placeholder-opacity-40 focus:placeholder-blue-300" |
||||
onChange={(e) => onChange(e.target.value)} |
||||
value={value} |
||||
placeholder={langDetector( |
||||
lang, |
||||
"نام کالا را جستجو کنید", |
||||
"search product name" |
||||
)} |
||||
onFocus={() => setPopularsToggle(true)} |
||||
onBlur={() => |
||||
setTimeout(() => { |
||||
setPopularsToggle(false); |
||||
}, 250) |
||||
} |
||||
/> |
||||
<img |
||||
src={searchIcon} |
||||
alt={langDetector(lang, "جستجو", "search")} |
||||
className={_.join( |
||||
[ |
||||
"search__icon absolute w-6 h-6 top-1/2 transform -translate-y-1/2", |
||||
langDetector(lang, "left-3", "right-3"), |
||||
], |
||||
" " |
||||
)} |
||||
/> |
||||
<div |
||||
className={_.join( |
||||
[ |
||||
"search__populars w-full mt-0 border rounded-sm top-12 left-0 absolute z-10 px-4 bg-white", |
||||
popularsToggle ? "flex flex-col" : "hidden", |
||||
"transition", |
||||
], |
||||
" " |
||||
)} |
||||
> |
||||
<strong className="py-3"> |
||||
{langDetector(lang, "جستجوهای پرطرفدار", "Popular search")} |
||||
</strong> |
||||
<ul className="divide-y divide-gray-200"> |
||||
{populars?.map((item, i) => ( |
||||
<> |
||||
<li |
||||
key={i} |
||||
className="transition py-3 px-1 hover:bg-blue-100" |
||||
onClick={() => setValue(() => item)} |
||||
> |
||||
{item} |
||||
</li> |
||||
</> |
||||
))} |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
PopularSearch.defaultProps = { |
||||
lang: "fa", |
||||
theme: "light", |
||||
populars: ["علی", "علیرضا", "محمد", "محمدرضا"], |
||||
}; |
After Width: | Height: | Size: 857 B |
@ -0,0 +1 @@ |
||||
/// <reference types="react-scripts" />
|
@ -0,0 +1,11 @@ |
||||
module.exports = { |
||||
purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'], |
||||
darkMode: 'class', // or 'media' or 'class'
|
||||
theme: { |
||||
extend: {}, |
||||
}, |
||||
variants: { |
||||
extend: {}, |
||||
}, |
||||
plugins: [], |
||||
} |