Merge pull request #3 from KieIO/m1-datnguyen

feat: label, quanitty input, caroucel
This commit is contained in:
datnguyenkieio 2021-08-24 12:07:50 +07:00 committed by GitHub
commit 20fb4b3446
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 408 additions and 7 deletions

View File

@ -2,10 +2,32 @@
import { ButtonCommon, Layout } from 'src/components/common'
import { IconBuy } from 'src/components/icons'
import { ButonType, ButtonSize } from 'src/utils/constanst.utils'
import {CarouselCommon, LabelCommon, QuanittyInput } from 'src/components/common'
const dataTest = [{
text:1
},{
text:2
},{
text:3
},{
text:4
},{
text:5
},{
text:6
}]
const test = (props:{text:string})=><div className="h-64 bg-yellow-300">{props.text}</div>
export default function Home() {
return (
<>
<div>This is home page</div>
<CarouselCommon data={dataTest} Component={test} itemKey="test"/>
<QuanittyInput size ="default" min={5} max={10} initValue={3}/>
<QuanittyInput size ="small" min={3} step={10}/>
<LabelCommon type="default" shape="half" >SEEFOOT</LabelCommon>
<LabelCommon type="discount" shape="round">-15%</LabelCommon>
<LabelCommon type="waiting">Waitting</LabelCommon>
<LabelCommon type="delivering" >Delivering</LabelCommon>
<LabelCommon type="delivered">Delivered</LabelCommon>
<ButtonCommon loading={true}>Button default</ButtonCommon>
<ButtonCommon type={ButonType.light} >{ButonType.light} - Button light</ButtonCommon>
<ButtonCommon type={ButonType.light} disabled>{ButonType.light} - Button light</ButtonCommon>
@ -13,9 +35,6 @@ export default function Home() {
<ButtonCommon size={ButtonSize.large} icon={<IconBuy/>}>{ButtonSize.large} - Button default large</ButtonCommon>
<ButtonCommon icon={<IconBuy/>} disabled isIconSuffix={true}>Button with icon disabled</ButtonCommon>
<ButtonCommon icon={<IconBuy/>} type={ButonType.light}>Button with icon</ButtonCommon>
<p>Go to <code>pages/index.tsx</code> to get your hand dirty!</p>
<p>Go to <code>src/components</code> to make your awesome component!</p>
<p>Go to <code>src/styles</code> to find global styles!</p>
</>
)
}

View File

@ -0,0 +1,5 @@
.navigation_wrapper{
@apply relative;
min-height: theme("caroucel.arrow-height") ;
}

View 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

View File

@ -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 ;
}
}

View File

@ -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>
)
}

View 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;
}
}

View 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

View File

@ -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;
}
}
}

View 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

View File

@ -1,5 +1,8 @@
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'

View File

@ -0,0 +1,18 @@
const ArrowLeft = ({ ...props }) => {
return (
<svg
width="12"
height="18"
viewBox="0 0 12 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4.81637 8.99983L10.7164 3.09983C11.0268 2.78756 11.201 2.36514 11.201 1.92483C11.201 1.48452 11.0268 1.0621 10.7164 0.749833C10.5614 0.593619 10.3771 0.469628 10.174 0.385014C9.9709 0.300399 9.75306 0.256836 9.53304 0.256836C9.31302 0.256836 9.09517 0.300399 8.89207 0.385014C8.68898 0.469628 8.50464 0.593619 8.3497 0.749833L1.28304 7.8165C1.12682 7.97144 1.00283 8.15577 0.918218 8.35887C0.833603 8.56197 0.790039 8.77981 0.790039 8.99983C0.790039 9.21985 0.833603 9.43769 0.918218 9.64079C1.00283 9.84389 1.12682 10.0282 1.28304 10.1832L8.3497 17.3332C8.50544 17.4876 8.69013 17.6098 8.89319 17.6928C9.09626 17.7757 9.31369 17.8178 9.53304 17.8165C9.75238 17.8178 9.96982 17.7757 10.1729 17.6928C10.3759 17.6098 10.5606 17.4876 10.7164 17.3332C11.0268 17.0209 11.201 16.5985 11.201 16.1582C11.201 15.7179 11.0268 15.2954 10.7164 14.9832L4.81637 8.99983Z"
fill="#141414"
/>
</svg>
)
}
export default ArrowLeft

View File

@ -0,0 +1,18 @@
const ArrowRight = ({ ...props }) => {
return (
<svg
width="12"
height="18"
viewBox="0 0 12 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10.7168 7.8165L3.65015 0.749833C3.49521 0.593619 3.31088 0.469628 3.10778 0.385014C2.90468 0.300399 2.68684 0.256836 2.46682 0.256836C2.2468 0.256836 2.02895 0.300399 1.82585 0.385014C1.62276 0.469628 1.43842 0.593619 1.28348 0.749833C0.973064 1.0621 0.798828 1.48452 0.798828 1.92483C0.798828 2.36514 0.973064 2.78756 1.28348 3.09983L7.18348 8.99983L1.28348 14.8998C0.973064 15.2121 0.798828 15.6345 0.798828 16.0748C0.798828 16.5151 0.973064 16.9376 1.28348 17.2498C1.43922 17.4043 1.62391 17.5265 1.82697 17.6095C2.03003 17.6924 2.24747 17.7344 2.46682 17.7332C2.68616 17.7344 2.9036 17.6924 3.10666 17.6095C3.30972 17.5265 3.49442 17.4043 3.65015 17.2498L10.7168 10.1832C10.873 10.0282 10.997 9.84389 11.0816 9.64079C11.1662 9.4377 11.2098 9.21985 11.2098 8.99983C11.2098 8.77981 11.1662 8.56197 11.0816 8.35887C10.997 8.15577 10.873 7.97144 10.7168 7.8165Z"
fill="#141414"
/>
</svg>
)
}
export default ArrowRight

View File

@ -0,0 +1,18 @@
const ArrowRight = ({ ...props }) => {
return (
<svg
width="12"
height="12"
viewBox="0 0 12 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10.6667 5.33317H6.66669V1.33317C6.66669 1.15636 6.59645 0.98679 6.47142 0.861766C6.3464 0.736742 6.17683 0.666504 6.00002 0.666504C5.82321 0.666504 5.65364 0.736742 5.52862 0.861766C5.40359 0.98679 5.33335 1.15636 5.33335 1.33317V5.33317H1.33335C1.15654 5.33317 0.986974 5.40341 0.861949 5.52843C0.736925 5.65346 0.666687 5.82303 0.666687 5.99984C0.666687 6.17665 0.736925 6.34622 0.861949 6.47124C0.986974 6.59627 1.15654 6.6665 1.33335 6.6665H5.33335V10.6665C5.33335 10.8433 5.40359 11.0129 5.52862 11.1379C5.65364 11.2629 5.82321 11.3332 6.00002 11.3332C6.17683 11.3332 6.3464 11.2629 6.47142 11.1379C6.59645 11.0129 6.66669 10.8433 6.66669 10.6665V6.6665H10.6667C10.8435 6.6665 11.0131 6.59627 11.1381 6.47124C11.2631 6.34622 11.3334 6.17665 11.3334 5.99984C11.3334 5.82303 11.2631 5.65346 11.1381 5.52843C11.0131 5.40341 10.8435 5.33317 10.6667 5.33317Z"
fill="#141414"
/>
</svg>
)
}
export default ArrowRight

View File

@ -0,0 +1,18 @@
const ArrowLeft = ({ ...props }) => {
return (
<svg
width="12"
height="2"
viewBox="0 0 12 2"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10.6667 0.333496H1.33335C1.15654 0.333496 0.986974 0.403734 0.861949 0.528758C0.736925 0.653783 0.666687 0.823352 0.666687 1.00016C0.666687 1.17697 0.736925 1.34654 0.861949 1.47157C0.986974 1.59659 1.15654 1.66683 1.33335 1.66683H10.6667C10.8435 1.66683 11.0131 1.59659 11.1381 1.47157C11.2631 1.34654 11.3334 1.17697 11.3334 1.00016C11.3334 0.823352 11.2631 0.653783 11.1381 0.528758C11.0131 0.403734 10.8435 0.333496 10.6667 0.333496Z"
fill="#141414"
/>
</svg>
)
}
export default ArrowLeft

View File

@ -34,9 +34,12 @@
--border-line: #ebebeb;
--background: #f8f8f8;
--white: #fbfbfb;
--background-arrow:rgba(20, 20, 20, 0.05);
--font-size: 1.6rem;
--line-height: 2.4rem;
--font-size: 16px;
--line-height: 24px;
// --font-size: 16px;
// --line-height: 24px;
--font-sans: "Nunito", cursive, -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "Helvetica",
sans-serif;

View File

@ -48,6 +48,9 @@ module.exports = {
'line': 'var(--border-line)',
'background': 'var(--background)',
'white': 'var(--white)',
'background-arrow':'var(--background-arrow)',
'disabled': 'var(--text-disabled)',
// @deprecated (NOT use these variables)
@ -113,7 +116,10 @@ module.exports = {
'2xl': '1536px',
// => @media (min-width: 1536px) { ... }
}
},
caroucel:{
"arrow-height":"64px"
},
},
},
plugins: [require('postcss-import'), require('tailwindcss'), require('autoprefixer')]