mirror of
https://github.com/vercel/commerce.git
synced 2025-07-29 05:01:22 +00:00
feat: checkboxCommon
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
/* style demo here */
|
||||
|
||||
.buttonCommon {
|
||||
color: red;
|
||||
}
|
96
src/components/common/ButtonCommon/ButtonCommon.module.scss
Normal file
96
src/components/common/ButtonCommon/ButtonCommon.module.scss
Normal file
@@ -0,0 +1,96 @@
|
||||
@import "../../../styles/utilities";
|
||||
|
||||
.buttonCommon {
|
||||
@apply custom-border-radius bg-primary transition-all duration-200 text-white font-bold;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 1.6rem 3.2rem;
|
||||
&:disabled {
|
||||
filter: brightness(0.9);
|
||||
cursor: not-allowed;
|
||||
color: var(--disabled);
|
||||
}
|
||||
&.loading {
|
||||
&::before {
|
||||
content: "";
|
||||
border-radius: 50%;
|
||||
width: 1.6rem;
|
||||
height: 1.6rem;
|
||||
border: 3px solid rgba(170, 170, 170, 0.5);
|
||||
border-top: 3px solid var(--white);
|
||||
-webkit-animation: spin 2s linear infinite;
|
||||
animation: spin 2s linear infinite;
|
||||
margin-right: 0.8rem;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
@apply shadow-md;
|
||||
&:not(:disabled) {
|
||||
filter: brightness(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
filter: brightness(1.05);
|
||||
}
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--text-active);
|
||||
}
|
||||
|
||||
&.light {
|
||||
@apply text-base bg-white;
|
||||
border: 1px solid var(--text-active);
|
||||
&.loading {
|
||||
&::before {
|
||||
border-top-color: var(--primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.ghost {
|
||||
@apply bg-white;
|
||||
color: var(--primary);
|
||||
border: 1px solid var(--primary);
|
||||
&.loading {
|
||||
&::before {
|
||||
border-top-color: var(--primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.large {
|
||||
padding: 3.2rem 4.8rem;
|
||||
&.loading {
|
||||
&::before {
|
||||
width: 2.4rem;
|
||||
height: 2.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.preserve {
|
||||
flex-direction: row-reverse;
|
||||
.icon {
|
||||
margin: 0 0 0 1.6rem;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin: 0 1.6rem 0 0;
|
||||
svg path {
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
@@ -1,15 +1,37 @@
|
||||
import { FC, useRef, useEffect } from 'react'
|
||||
import s from './ButtonCommon.module.css'
|
||||
import classNames from 'classnames'
|
||||
import React, { memo } from 'react'
|
||||
import s from './ButtonCommon.module.scss'
|
||||
|
||||
interface Props {
|
||||
className?: string
|
||||
children?: any
|
||||
children?: React.ReactNode,
|
||||
type?: 'primary' | 'light' | 'ghost',
|
||||
size?: 'default' | 'large',
|
||||
icon?: any,
|
||||
isIconSuffix?: boolean,
|
||||
loading?: boolean,
|
||||
disabled?: boolean,
|
||||
onClick?: () => void,
|
||||
}
|
||||
|
||||
const ButtonCommon: FC<Props> = ({ }) => {
|
||||
const ButtonCommon = memo(({ type = 'primary', size = 'default',
|
||||
icon, loading, disabled, isIconSuffix, children, onClick }: Props) => {
|
||||
return (
|
||||
<div className={s.buttonCommon}>This is button common</div>
|
||||
<button className={classNames({
|
||||
[s.buttonCommon]: true,
|
||||
[s[type]]: !!type,
|
||||
[s[size]]: !!size,
|
||||
[s.loading]: loading,
|
||||
[s.preserve]: isIconSuffix,
|
||||
})}
|
||||
disabled={disabled}
|
||||
onClick={onClick}
|
||||
>
|
||||
{
|
||||
icon && <span className={s.icon}>{icon}</span>
|
||||
}
|
||||
<span className={s.label}>{children}</span>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default ButtonCommon
|
||||
|
@@ -0,0 +1,5 @@
|
||||
.navigation_wrapper{
|
||||
@apply relative;
|
||||
min-height: theme("caroucel.arrow-height") ;
|
||||
|
||||
}
|
57
src/components/common/CarouselCommon/CarouselCommon.tsx
Normal file
57
src/components/common/CarouselCommon/CarouselCommon.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import { useKeenSlider } from 'keen-slider/react'
|
||||
import React from 'react'
|
||||
import 'keen-slider/keen-slider.min.css'
|
||||
import { CustomCarouselArrow } from './CustomArrow/CustomCarouselArrow';
|
||||
import s from "./CaroucelCommon.module.scss"
|
||||
interface CarouselCommonProps {
|
||||
children?: React.ReactNode
|
||||
data?: any[]
|
||||
Component: React.ComponentType<any>
|
||||
isArrow?:Boolean
|
||||
itemKey:String
|
||||
}
|
||||
|
||||
const CarouselCommon = ({ data, Component,itemKey }: CarouselCommonProps) => {
|
||||
const [currentSlide, setCurrentSlide] = React.useState(0)
|
||||
const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({
|
||||
slidesPerView: 1,
|
||||
initial: 0,
|
||||
slideChanged(s) {
|
||||
setCurrentSlide(s.details().relativeSlide)
|
||||
},
|
||||
})
|
||||
const handleRightArrowClick = () => {
|
||||
slider.next()
|
||||
}
|
||||
|
||||
const handleLeftArrowClick = () => {
|
||||
slider.prev()
|
||||
}
|
||||
return (
|
||||
<div className={s.navigation_wrapper}>
|
||||
<div ref={sliderRef} className="keen-slider">
|
||||
{data?.map((props,index) => (
|
||||
<div className="keen-slider__slide" key={`${itemKey}-${index}`}>
|
||||
<Component {...props} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{slider && (
|
||||
<>
|
||||
<CustomCarouselArrow
|
||||
side="right"
|
||||
onClick={handleRightArrowClick}
|
||||
isDisabled={currentSlide === slider.details().size - 1}
|
||||
/>
|
||||
<CustomCarouselArrow
|
||||
side="left"
|
||||
onClick={handleLeftArrowClick}
|
||||
isDisabled={currentSlide === 0}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CarouselCommon
|
@@ -0,0 +1,17 @@
|
||||
.custom_arrow{
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
&:focus{
|
||||
outline: none;
|
||||
}
|
||||
@apply absolute top-1/2 bg-background-arrow transform -translate-y-1/2 flex justify-center items-center transition duration-100;
|
||||
&.left{
|
||||
@apply left-0;
|
||||
}
|
||||
&.right{
|
||||
@apply right-0;
|
||||
}
|
||||
&.isDisabled{
|
||||
@apply hidden ;
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
import classNames from 'classnames'
|
||||
import React from 'react'
|
||||
import ArrowLeft from 'src/components/icons/ArrowLeft'
|
||||
import ArrowRight from 'src/components/icons/ArrowRight'
|
||||
import s from "./CustomCarouselArrow.module.scss"
|
||||
interface CustomCarouselArrowProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
side: 'left' | 'right'
|
||||
isDisabled:Boolean
|
||||
}
|
||||
|
||||
export const CustomCarouselArrow = ({
|
||||
side,isDisabled,
|
||||
...props
|
||||
}: CustomCarouselArrowProps) => {
|
||||
return (
|
||||
<button
|
||||
{...props}
|
||||
className={classNames(`${s.custom_arrow}`, { [`${s[side]}`]: side,[`${s.isDisabled}`]:isDisabled })}
|
||||
>
|
||||
{side==='left'?(<ArrowLeft/>):(<ArrowRight/>)}
|
||||
</button>
|
||||
)
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
@import '../../../styles/utilities';
|
||||
.checkboxCommonWarper{
|
||||
@apply flex flex-col;
|
||||
margin-left:2rem;
|
||||
.checkboxItem{
|
||||
display: block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
margin-top:2rem;
|
||||
border-radius: 0.4rem;
|
||||
width:50%;
|
||||
&:hover .checkboxInput ~ .checkMark {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.checkboxInput{
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
height: 0;
|
||||
width: 0;
|
||||
&:checked ~ .checkMark:after {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.checkMark {
|
||||
border-radius: 0.4rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 2rem;
|
||||
width: 2rem;
|
||||
background-color:var(--positive);
|
||||
&:after {
|
||||
left: 25%;
|
||||
top: 27%;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
color:white;
|
||||
content: "";
|
||||
background-image:url('/assets/svg/checkmark.svg');
|
||||
background-repeat: no-repeat;
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&~ .checkMark{
|
||||
background-color: #ccc;
|
||||
|
||||
}
|
||||
&:checked ~ .checkMark {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
&:checked ~ .checkMark:after {
|
||||
display: block;
|
||||
}
|
||||
&:hover .checkboxInput ~ .checkMark {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
.checkboxText{
|
||||
margin-left:3rem;
|
||||
}
|
||||
}
|
40
src/components/common/CheckboxCommon/CheckboxCommon.tsx
Normal file
40
src/components/common/CheckboxCommon/CheckboxCommon.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import React,{useState,useEffect} from 'react';
|
||||
import s from './CheckboxCommon.module.scss';
|
||||
import classNames from 'classnames';
|
||||
|
||||
interface CheckboxProps extends Omit<
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
'onChange'
|
||||
>{
|
||||
onChange?: (value: boolean) => void,
|
||||
defaultChecked?: boolean
|
||||
}
|
||||
|
||||
const CheckboxCommon = ({onChange,defaultChecked = true,...props}: CheckboxProps) =>{
|
||||
|
||||
const [value, setValue] = useState<boolean>();
|
||||
|
||||
useEffect(()=>{
|
||||
onChange && onChange(value)
|
||||
},[value])
|
||||
|
||||
|
||||
const onValueChange = (e: ChangeEvent<HTMLInputElement>)=>{
|
||||
let value =e.target.checked;
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames(s.checkboxCommonWarper)}>
|
||||
<label className={classNames(s.checkboxItem)}>
|
||||
<input id="check" defaultChecked={defaultChecked} className={s.checkboxInput} type="checkbox" onChange={onValueChange}/>
|
||||
<span className={s.checkMark}></span>
|
||||
</label>
|
||||
<div className={classNames(s.checkboxText)}>
|
||||
<label for="check"> Billing address is same as shipping </label>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CheckboxCommon;
|
@@ -1,21 +1,22 @@
|
||||
@import '../../../styles/utilities';
|
||||
@import "../../../styles/utilities";
|
||||
|
||||
.header {
|
||||
.btn {
|
||||
@apply font-bold py-2 px-4 rounded;
|
||||
// @apply font-bold py-2 px-4 rounded;
|
||||
}
|
||||
.btnBlue {
|
||||
@apply bg-primary hover:bg-warning text-label font-bold py-2 px-4 custom-border-radius;
|
||||
|
||||
}
|
||||
.link {
|
||||
color: theme("colors.warning");
|
||||
}
|
||||
.heading {
|
||||
@apply text-base;
|
||||
@apply text-base font-heading;
|
||||
}
|
||||
|
||||
.paragraph {
|
||||
@apply topline;
|
||||
}
|
||||
.logo {
|
||||
@apply font-logo;
|
||||
}
|
||||
}
|
||||
|
@@ -10,27 +10,8 @@ const Header: FC<Props> = ({ }: Props) => {
|
||||
return (
|
||||
<div className={s.header}>
|
||||
This is Header
|
||||
<button className={s.btnBlue}>
|
||||
Button
|
||||
</button>
|
||||
<button className={s.btn}>
|
||||
Button
|
||||
</button>
|
||||
<div className={s.link}>
|
||||
Test link style
|
||||
</div>
|
||||
<h1 className="heading-1">
|
||||
HEADING 1
|
||||
</h1>
|
||||
<p className="spacing-horizontal">
|
||||
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Sunt delectus, atque aliquid repudiandae debitis dolor facere impedit alias nemo dolores voluptatum? Commodi, delectus. Dignissimos aspernatur nobis, distinctio delectus eligendi nisi illo tempore non nostrum, molestias excepturi dolor culpa fugiat rem perspiciatis. Repellendus numquam quisquam possimus natus vero recusandae, ipsam earum ratione quos ex consectetur cum nostrum modi amet odit fugiat fugit. Facere cum enim dignissimos molestias facilis error dicta exercitationem, delectus voluptates fuga laboriosam esse sunt odio, impedit modi veritatis, nisi nam? Voluptatum voluptas similique aspernatur. Soluta, accusamus! Mollitia praesentium adipisci perspiciatis iusto dolorum sint sit placeat, nesciunt id repellendus.
|
||||
</p>
|
||||
<p className="spacing-horizontal-left">
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Itaque doloremque quos excepturi laborum maiores laudantium hic iusto natus? Ipsa deleniti quas odit! Labore esse enim ipsam tempora tenetur beatae maxime officiis est, a illo! Soluta suscipit maxime odit eveniet laudantium, iure atque doloribus quaerat. Obcaecati tempore molestiae aliquid amet maiores suscipit, beatae repellat illum ipsam tenetur. Porro officiis omnis quam, iure quia necessitatibus consectetur culpa itaque, in tempora rem ex ad et iusto, hic commodi fuga quibusdam. Dolores exercitationem natus dolor pariatur voluptates non corporis, minus repellat! Quis distinctio esse, animi suscipit ducimus sequi obcaecati facere, perferendis ea omnis soluta.
|
||||
</p>
|
||||
<p className={s.paragraph}>
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Tempore, natus?
|
||||
</p>
|
||||
<h1 className={s.heading}>This is heading</h1>
|
||||
<div className={s.logo}>This is logo text</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@@ -0,0 +1,5 @@
|
||||
@import "../../../styles/utilities";
|
||||
|
||||
.inputCommon {
|
||||
@apply custom-border-radius transition-all duration-200;
|
||||
}
|
52
src/components/common/InputCommon/InputCommon.tsx
Normal file
52
src/components/common/InputCommon/InputCommon.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
|
||||
import { KEY } from 'src/utils/constanst.utils';
|
||||
import s from './InputCommon.module.scss';
|
||||
|
||||
type Ref = {
|
||||
focus: () => void
|
||||
} | null;
|
||||
|
||||
interface Props {
|
||||
children?: React.ReactNode,
|
||||
value?: string | number,
|
||||
placeholder?: string,
|
||||
type?: 'text' | 'number',
|
||||
onChange?: (value: string | number) => void,
|
||||
onEnter?: (value: string | number) => void,
|
||||
}
|
||||
|
||||
const InputCommon = forwardRef<Ref, Props>(({ value, placeholder, type, onChange, onEnter }: Props, ref) => {
|
||||
const inputElementRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
focus: () => {
|
||||
inputElementRef.current?.focus();
|
||||
},
|
||||
}));
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
onChange && onChange(e.target.value)
|
||||
}
|
||||
|
||||
const handleKeyDown = (e: any) => {
|
||||
if (e.key === KEY.ENTER && onEnter) {
|
||||
const value = inputElementRef.current?.value || ''
|
||||
onEnter(value)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<input
|
||||
ref={inputElementRef}
|
||||
value={value}
|
||||
type={type}
|
||||
placeholder={placeholder}
|
||||
onChange={handleChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
className={s.inputCommon}
|
||||
/>
|
||||
)
|
||||
|
||||
})
|
||||
|
||||
export default InputCommon
|
10
src/components/common/ItemWishList/ItemWishList.module.scss
Normal file
10
src/components/common/ItemWishList/ItemWishList.module.scss
Normal file
@@ -0,0 +1,10 @@
|
||||
@import '../../../styles/utilities';
|
||||
|
||||
.heartToggle{
|
||||
cursor: pointer;
|
||||
width: 4.8rem;
|
||||
height: 4.8rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
19
src/components/common/ItemWishList/ItemWishList.tsx
Normal file
19
src/components/common/ItemWishList/ItemWishList.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Heart } from '@components/icons'
|
||||
import React, { useState } from 'react'
|
||||
import s from './ItemWishList.module.scss'
|
||||
|
||||
interface Props {
|
||||
className?: string
|
||||
children?: any
|
||||
}
|
||||
|
||||
const ItemWishList = ({}:Props) => {
|
||||
const [isClick,setClick] = useState(false)
|
||||
return(
|
||||
<div className={s.heartToggle} onClick={() => setClick(!isClick)}>
|
||||
<Heart color={isClick ? "#D1644D" : "#5B9A74"}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ItemWishList
|
43
src/components/common/LabelCommon/LabelCommon.module.scss
Normal file
43
src/components/common/LabelCommon/LabelCommon.module.scss
Normal file
@@ -0,0 +1,43 @@
|
||||
.labelCommonWarper{
|
||||
display: inline-flex;
|
||||
align-items: flex-start;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0.01em;
|
||||
@apply text-white text-right;
|
||||
&.defaultSize{
|
||||
min-height: 2rem;
|
||||
line-height: 2rem;
|
||||
font-size: 1.2rem;
|
||||
padding: 0 0.8rem;
|
||||
}
|
||||
&.largeSize{
|
||||
max-height: 2.4rem;
|
||||
line-height: 2.4rem;
|
||||
font-size: 1.6rem;
|
||||
padding: 0 1.8rem;
|
||||
}
|
||||
&.defaultType{
|
||||
@apply bg-positive-dark;
|
||||
}
|
||||
&.discountType{
|
||||
@apply bg-negative;
|
||||
}
|
||||
&.waitingType{
|
||||
@apply bg-warning;
|
||||
}
|
||||
&.deliveringType{
|
||||
@apply bg-info;
|
||||
}
|
||||
&.deliveredType{
|
||||
@apply bg-positive;
|
||||
}
|
||||
&.defaultShape{
|
||||
border-radius: 0.4rem;
|
||||
}
|
||||
&.halfShape{
|
||||
border-radius: 0px 1.4rem 1.4rem 0px;
|
||||
}
|
||||
&.roundShape{
|
||||
border-radius: 1.4rem;
|
||||
}
|
||||
}
|
30
src/components/common/LabelCommon/LabelCommon.tsx
Normal file
30
src/components/common/LabelCommon/LabelCommon.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import classNames from 'classnames'
|
||||
import React from 'react'
|
||||
import s from './LabelCommon.module.scss'
|
||||
interface LabelCommonProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
size?: 'default' | 'large'
|
||||
shape?: 'half' | 'round' | 'default'
|
||||
type?: 'default' | 'discount' | 'waiting' | 'delivering' | 'delivered'
|
||||
color?: string
|
||||
}
|
||||
|
||||
const LabelCommon = ({
|
||||
size = 'default',
|
||||
type = 'default',
|
||||
shape = "default",
|
||||
children,
|
||||
}: LabelCommonProps) => {
|
||||
return (
|
||||
<div
|
||||
className={classNames(s.labelCommonWarper, {
|
||||
[s[`${size}Size`]]: size,
|
||||
[s[`${type}Type`]]: type,
|
||||
[s[`${shape}Shape`]]: shape,
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default LabelCommon
|
20
src/components/common/Logo/Logo.module.scss
Normal file
20
src/components/common/Logo/Logo.module.scss
Normal file
@@ -0,0 +1,20 @@
|
||||
@import '../../../styles/utilities';
|
||||
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@700&display=swap');
|
||||
|
||||
|
||||
.logo{
|
||||
display: flex;
|
||||
.eclipse{
|
||||
width: 3.2rem;
|
||||
height: 3.2rem;
|
||||
background-color: theme("colors.primary");
|
||||
border-radius: 50%;
|
||||
margin-right: 1.2rem;
|
||||
}
|
||||
.conTent{
|
||||
font-family: 'Poppins', sans-serif;
|
||||
text-transform: uppercase;
|
||||
line-height: 3.2rem;
|
||||
letter-spacing: -0.02rem;
|
||||
}
|
||||
}
|
21
src/components/common/Logo/Logo.tsx
Normal file
21
src/components/common/Logo/Logo.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import s from './Logo.module.scss'
|
||||
|
||||
interface Props {
|
||||
className?: string
|
||||
children?: any
|
||||
}
|
||||
|
||||
const Logo = ({}: Props) => {
|
||||
return(
|
||||
<div className={s.logo}>
|
||||
<div className={s.eclipse}>
|
||||
|
||||
</div>
|
||||
<div className={s.conTent}>
|
||||
ONLINE GROCERY
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Logo
|
@@ -0,0 +1,39 @@
|
||||
@import '../../../styles/utilities';
|
||||
.quanittyInputWarper{
|
||||
border-color: theme("textColor.active");
|
||||
@apply border border-solid inline-flex justify-between items-center custom-border-radius;
|
||||
.plusIcon, .minusIcon{
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
&.default{
|
||||
max-width: 18.4rem;
|
||||
min-height: 4rem;
|
||||
.plusIcon, .minusIcon{
|
||||
margin: 0.8rem;
|
||||
width: 2.4rem;
|
||||
height: 2.4rem;
|
||||
}
|
||||
}
|
||||
&.small{
|
||||
max-width: 10rem;
|
||||
min-height: 2.8rem;
|
||||
.plusIcon, .minusIcon{
|
||||
margin: 0 0.6rem;
|
||||
// width: 1rem;
|
||||
// height: 1rem;
|
||||
}
|
||||
}
|
||||
.quanittyInput{
|
||||
@apply bg-background outline-none w-1/2 text-center h-full font-bold;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
color: theme("textColor.active");
|
||||
&::-webkit-inner-spin-button, &::-webkit-inner-spin-button{
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
83
src/components/common/QuanittyInput/QuanittyInput.tsx
Normal file
83
src/components/common/QuanittyInput/QuanittyInput.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import React, { ChangeEvent, useEffect, useState } from 'react'
|
||||
import s from './QuanittyInput.module.scss'
|
||||
import classNames from 'classnames'
|
||||
import { Minus, Plus } from '@components/icons'
|
||||
interface QuanittyInputProps
|
||||
extends Omit<
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
'onChange' | 'min' | 'max' | 'step' | "type" | "size"
|
||||
> {
|
||||
size?: 'default' | 'small'
|
||||
onChange?: (value: number) => void
|
||||
initValue?: number
|
||||
min?: number
|
||||
max?: number
|
||||
step?: number
|
||||
}
|
||||
|
||||
const QuanittyInput = ({
|
||||
size = 'default',
|
||||
onChange,
|
||||
initValue = 0,
|
||||
min,
|
||||
max,
|
||||
step = 1,
|
||||
...props
|
||||
}: QuanittyInputProps) => {
|
||||
const [value, setValue] = useState<number>(0)
|
||||
|
||||
useEffect(() => {
|
||||
onChange && onChange(value)
|
||||
}, [value])
|
||||
|
||||
useEffect(() => {
|
||||
initValue && setValue(initValue)
|
||||
}, [initValue])
|
||||
|
||||
const onPlusClick = () => {
|
||||
if (max && value + step > max) {
|
||||
setValue(max)
|
||||
} else {
|
||||
setValue(value + step)
|
||||
}
|
||||
}
|
||||
|
||||
const onMinusClick = () => {
|
||||
if (min && value - step < min) {
|
||||
setValue(min)
|
||||
} else {
|
||||
setValue(value - step)
|
||||
}
|
||||
}
|
||||
|
||||
const onValueChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
let value = Number(e.target.value) || 0
|
||||
if (min && value < min) {
|
||||
setValue(min)
|
||||
} else if (max && value > max) {
|
||||
setValue(max)
|
||||
} else {
|
||||
setValue(value)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames(s.quanittyInputWarper, { [s[size]]: size })}>
|
||||
<div className={s.minusIcon} onClick={onMinusClick}>
|
||||
<Minus />
|
||||
</div>
|
||||
<input
|
||||
{...props}
|
||||
type="number"
|
||||
value={value}
|
||||
onChange={onValueChange}
|
||||
className={s.quanittyInput}
|
||||
/>
|
||||
<div className={s.plusIcon} onClick={onPlusClick}>
|
||||
<Plus />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default QuanittyInput
|
17
src/components/common/ViewAllItem/ViewAllItem.module.scss
Normal file
17
src/components/common/ViewAllItem/ViewAllItem.module.scss
Normal file
@@ -0,0 +1,17 @@
|
||||
@import '../../../styles/utilities';
|
||||
@import url('https://fonts.googleapis.com/css2?family=Nunito&display=swap');
|
||||
|
||||
.viewAll{
|
||||
display: flex;
|
||||
color: theme("colors.primary");
|
||||
.conTent{
|
||||
margin: 0.8rem 0.8rem 0.8rem 1.6rem;
|
||||
font-family: 'Nunito', sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
.vecTor{
|
||||
margin: 0.8rem 0rem 0.8rem 0rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
26
src/components/common/ViewAllItem/ViewAllItem.tsx
Normal file
26
src/components/common/ViewAllItem/ViewAllItem.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import Vector from 'src/components/icons/Vector'
|
||||
import s from './ViewAllItem.module.scss'
|
||||
import Link from 'next/link'
|
||||
|
||||
interface Props {
|
||||
className?: string
|
||||
children?: any
|
||||
link?: string
|
||||
}
|
||||
|
||||
const ViewAllItem = ({ link }: Props) => {
|
||||
return(
|
||||
<div className={s.viewAll}>
|
||||
<Link href={"/all"}>
|
||||
<a className={s.conTent}>
|
||||
View All
|
||||
</a>
|
||||
</Link>
|
||||
<div className={s.vecTor}>
|
||||
<Vector />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ViewAllItem
|
@@ -1,4 +1,11 @@
|
||||
export { default as ButtonCommon } from './ButtonCommon/ButtonCommon'
|
||||
export { default as Layout } from './Layout/Layout'
|
||||
export { default as CarouselCommon } from './CarouselCommon/CarouselCommon'
|
||||
export { default as QuanittyInput } from './QuanittyInput/QuanittyInput'
|
||||
export { default as LabelCommon } from './LabelCommon/LabelCommon'
|
||||
export { default as Head } from './Head/Head'
|
||||
|
||||
export { default as ViewAllItem} from './ViewAllItem/ViewAllItem'
|
||||
export { default as ItemWishList} from './ItemWishList/ItemWishList'
|
||||
export { default as Logo} from './Logo/Logo'
|
||||
export { default as Inputcommon} from './InputCommon/InputCommon'
|
||||
export { default as CheckboxCommon} from './CheckboxCommon/CheckboxCommon'
|
Reference in New Issue
Block a user