🔀 merge: Merge branch 'common' of https://github.com/KieIO/grocery-vercel-commerce into m1-sonnguyen

:%s
This commit is contained in:
lytrankieio123 2021-08-26 18:04:08 +07:00
commit f7359ed6f5
68 changed files with 1596 additions and 160 deletions

View File

@ -1,5 +1,6 @@
import React, { MutableRefObject, useRef } from 'react';
import { HeadingCommon, CollectionHeading, ScrollToTop, ScrollTarget } from 'src/components/common'
import { Banner, ButtonCommon, ButtonIconBuy, CollectionHeading, HeadingCommon, Inputcommon, InputSearch, Layout, ScrollTarget } from 'src/components/common';
import { IconBuy } from 'src/components/icons';
export default function Home() {
const refScrollUp = useRef() as MutableRefObject<HTMLDivElement>;
@ -7,30 +8,29 @@ export default function Home() {
return (
<>
<ScrollTarget refScrollUp={refScrollUp} />
<HeadingCommon align="center" children="categories" />
<CollectionHeading type="highlight" children="fresh product todays" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading children="coffee bean" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading type="highlight" children="fresh product todays" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading children="coffee bean" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading type="highlight" children="fresh product todays" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading children="coffee bean" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading type="highlight" children="fresh product todays" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading children="coffee bean" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading type="highlight" children="fresh product todays" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading children="coffee bean" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading type="highlight" children="fresh product todays" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading children="coffee bean" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading type="highlight" children="fresh product todays" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading children="coffee bean" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading type="highlight" children="fresh product todays" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading children="coffee bean" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading type="highlight" children="fresh product todays" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading children="coffee bean" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading type="highlight" children="fresh product todays" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<CollectionHeading children="coffee bean" subtitle="Last call! Shop deep deals on 100+ bulk picks while you can." />
<ScrollToTop target={refScrollUp} />
<HeadingCommon align="center">categories</HeadingCommon>
<HeadingCommon type='light'>categories</HeadingCommon>
<CollectionHeading subtitle='Lorem' title='Heading here'/>
<HeadingCommon align="center" type='light'>categories</HeadingCommon>
<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>
{/* demo */}
<div style={{ display: 'flex' }}>
<Inputcommon placeholder="Enter here" />
<InputSearch />
</div>
<ButtonCommon type='ghost' icon={<IconBuy />}>Button</ButtonCommon>
<ButtonIconBuy />
<Banner
title="Save 15% on your first order"
subtitle="Last call! Shop deep deals on 100+ bulk picks while you can."
imgLink="https://user-images.githubusercontent.com/76729908/130574371-3b75fa72-9552-4605-aba9-a4b31cd9dce7.png"
/>
</>
)
}
// Home.Layout = Layout
Home.Layout = Layout

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

BIN
src/assets/imgs/gpay.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 B

BIN
src/assets/imgs/visa.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

View File

@ -0,0 +1,51 @@
@import "../../../styles/utilities";
.banner {
@apply bg-primary-light custom-border-radius-lg overflow-hidden;
@screen md {
border: 1px solid var(--primary);
}
&.large {
.inner {
@screen xl {
@apply bg-right-bottom;
background-size: unset;
}
}
}
.inner {
@apply bg-no-repeat;
background-size: 90%;
background-position: right -500% bottom 0%;
.content {
background-image: linear-gradient(
to right,
rgb(227, 242, 233, 0.9),
rgb(227, 242, 233, 0.5) 80%,
rgb(227, 242, 233, 0)
);
padding: 1.6rem;
max-width: 37rem;
@screen md {
max-width: 49.6rem;
padding: 4.8rem;
}
.top {
.heading {
@apply heading-1 font-heading;
margin-bottom: 1.6rem;
}
.subHeading {
@apply sub-headline;
@screen md {
@apply caption;
}
}
}
.bottom {
margin-top: 4rem;
}
}
}
}

View File

@ -0,0 +1,48 @@
import classNames from 'classnames'
import Link from 'next/link'
import React, { memo } from 'react'
import { IconArrowRight } from 'src/components/icons'
import { ROUTE } from 'src/utils/constanst.utils'
import { LANGUAGE } from 'src/utils/language.utils'
import ButtonCommon from '../ButtonCommon/ButtonCommon'
import s from './Banner.module.scss'
interface Props {
imgLink: string,
title: string,
subtitle: string,
buttonLabel?: string,
linkButton?: string,
size?: 'small' | 'large',
}
const Banner = memo(({ imgLink, title, subtitle, buttonLabel = LANGUAGE.BUTTON_LABEL.SHOP_NOW, linkButton = ROUTE.HOME, size = 'large' }: Props) => {
return (
<div className={classNames({
[s.banner]: true,
[s[size]]: true,
})}>
<div className={s.inner} style={{ backgroundImage: `url(${imgLink})` }}>
<div className={s.content}>
<div className={s.top}>
<h1 className={s.heading}>
{title}
</h1>
<div className={s.subHeading}>
{subtitle}
</div>
</div>
<div className={s.bottom}>
<Link href={linkButton}>
<a>
<ButtonCommon icon={<IconArrowRight />} isIconSuffix={true}>{buttonLabel}</ButtonCommon>
</a>
</Link>
</div>
</div>
</div>
</div>
)
})
export default Banner

View File

@ -11,6 +11,20 @@
cursor: not-allowed;
color: var(--disabled);
}
&: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);
}
&.loading {
&::before {
content: "";
@ -24,20 +38,6 @@
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;
@ -60,8 +60,18 @@
}
}
&.onlyIcon {
padding: 0.8rem;
.icon {
margin: 0;
}
}
&.large {
padding: 3.2rem 4.8rem;
&.onlyIcon {
padding: 1.6rem;
}
&.loading {
&::before {
width: 2.4rem;
@ -70,6 +80,8 @@
}
}
&.preserve {
flex-direction: row-reverse;
.icon {
@ -79,6 +91,10 @@
.icon {
margin: 0 1.6rem 0 0;
}
.label,
.icon {
svg path {
fill: currentColor;
}

View File

@ -6,15 +6,15 @@ interface Props {
children?: React.ReactNode,
type?: 'primary' | 'light' | 'ghost',
size?: 'default' | 'large',
icon?: any,
icon?: React.ReactNode,
isIconSuffix?: boolean,
loading?: boolean,
disabled?: boolean,
onClick?: () => void,
}
const ButtonCommon = memo(({ type = 'primary', size = 'default',
icon, loading, disabled, isIconSuffix, children, onClick }: Props) => {
const ButtonCommon = memo(({ type = 'primary', size = 'default', loading = false, isIconSuffix = false,
icon, disabled, children, onClick }: Props) => {
return (
<button className={classNames({
[s.buttonCommon]: true,
@ -22,6 +22,7 @@ const ButtonCommon = memo(({ type = 'primary', size = 'default',
[s[size]]: !!size,
[s.loading]: loading,
[s.preserve]: isIconSuffix,
[s.onlyIcon]: icon && !children,
})}
disabled={disabled}
onClick={onClick}

View File

@ -0,0 +1,26 @@
import React, { memo } from 'react'
import { IconBuy } from 'src/components/icons'
import ButtonCommon from '../ButtonCommon/ButtonCommon'
interface Props {
type?: 'primary' | 'light' | 'ghost',
size?: 'default' | 'large',
loading?: boolean,
disabled?: boolean,
onClick?: () => void,
}
const ButtonIconBuy = memo(({ type = 'light', size = 'default', loading = false, disabled, onClick }: Props) => {
return (
<ButtonCommon
type={type}
size={size}
loading={loading}
disabled={disabled}
onClick={onClick}
icon={<IconBuy />}
/>
)
})
export default ButtonIconBuy

View File

@ -4,15 +4,15 @@ import HeadingCommon from '../HeadingCommon/HeadingCommon'
interface CollectionHeadingProps {
type?: 'default' | 'highlight' | 'light';
children: string;
title: string;
subtitle: string;
}
const CollectionHeading = ({ type='default', children, subtitle }: CollectionHeadingProps) => {
const CollectionHeading = ({ type = 'default', title, subtitle }: CollectionHeadingProps) => {
return (
<section>
<HeadingCommon type={type} children={children}/>
<HeadingCommon type={type}>{title}</HeadingCommon>
<div className={s.subtitle}>{subtitle}</div>
</section>
)

View File

@ -0,0 +1,31 @@
@import "../../../styles/utilities";
.footer {
@apply spacing-horizontal;
padding-top: 4rem;
padding-bottom: 2rem;
margin-bottom: 10rem;
.footerMenu {
padding-bottom: 4rem;
}
.menu {
@apply flex flex-wrap;
}
@screen md {
margin-bottom: 0;
padding-bottom: 4rem;
padding-left: 3.2rem;
padding-right: 3.2rem;
.footerMenu {
@apply flex;
padding-bottom: 8rem;
.menu {
@apply flex-nowrap justify-between;
}
}
}
@screen lg {
@apply spacing-horizontal;
}
}

View File

@ -0,0 +1,85 @@
import React from 'react'
import { ROUTE } from 'src/utils/constanst.utils'
import FooterColumn from './components/FooterColumn/FooterColumn'
import FooterSocial from './components/FooterSocial/FooterSocial'
import s from './Footer.module.scss'
const FOOTER_COLUMNS = [
{
title: 'Company',
items: [
{
name: 'All Product',
link: ROUTE.PRODUCTS,
},
{
name: 'About Us',
link: ROUTE.ABOUT,
},
{
name: 'Bussiness',
link: ROUTE.BUSSINESS,
}
]
},
{
title: 'Resources',
items: [
{
name: 'Contact Us',
link: ROUTE.CONTACT,
},
{
name: 'FAQ',
link: ROUTE.FAQ,
},
{
name: 'Customer Service',
link: ROUTE.CUSTOMER_SERVICE,
},
]
},
{
title: 'Quick Links',
items: [
{
name: 'Terms & Conditions',
link: ROUTE.TERM_CONDITION,
},
{
name: 'Privacy Policy',
link: ROUTE.TERM_CONDITION,
},
{
name: 'Blog',
link: ROUTE.TERM_CONDITION,
},
]
}
]
interface Props {
className?: string
children?: any
}
const Footer = ({ }: Props) => {
return (
<footer className={s.footer}>
<div className={s.footerMenu}>
<section className={s.menu}>
{FOOTER_COLUMNS.map(item => <FooterColumn
key={item.title}
title={item.title}
items={item.items} />)}
</section>
<FooterSocial />
</div>
<div>
© 2021 Online Grocery
</div>
</footer>
)
}
export default Footer

View File

@ -0,0 +1,33 @@
@import "../../../../../styles/utilities";
.footerColumn {
width: 50%;
margin-bottom: 4rem;
@screen md {
padding-right: 6.4rem;
width: unset;
margin-bottom: 0;
}
@screen lg {
padding-right: 12.8rem;
}
.title {
@apply sm-headline text-active;
margin-bottom: 2.4rem;
}
ul {
list-style: none;
li {
&:not(:last-child) {
margin-bottom: 1.6rem;
}
a {
@apply transition-all duration-200 no-underline;
&:hover {
color: var(--primary);
}
}
}
}
}

View File

@ -0,0 +1,38 @@
import Link from 'next/link';
import React from 'react';
import s from './FooterColumn.module.scss'
interface Props {
title: string,
items: { link: string, name: string, isOpenNewTab?: boolean }[],
}
const FooterColumn = ({ title, items }: Props) => {
return (
<section className={s.footerColumn}>
<h4 className={s.title}>
{title}
</h4>
<ul>
{
items.map(item => <li key={item.name}>
{
item.isOpenNewTab ?
<a href={item.link} target="_blank" rel="noopener noreferrer">
{item.name}
</a>
:
<Link href={item.link}>
<a >
{item.name}
</a>
</Link>
}
</li>)
}
</ul>
</section>
);
};
export default FooterColumn;

View File

@ -0,0 +1,43 @@
@import "../../../../../styles/utilities";
.footerSocial {
.title {
@apply sm-headline text-active;
margin-bottom: 2.4rem;
}
.socialMedia,
.payment {
@apply list-none flex items-center;
}
.socialMedia {
li {
@apply transition-all duration-200;
margin-right: 1.6rem;
&:last-child {
margin-right: 0;
}
a {
@apply no-underline;
}
&:hover {
svg path {
fill: var(--primary);
}
}
}
}
.payment {
margin-top: 3.2rem;
li {
margin-right: 1.6rem;
width: 4rem;
img {
width: 100%;
object-fit: contain;
}
&:last-child {
margin-right: 0;
}
}
}
}

View File

@ -0,0 +1,75 @@
import React from 'react';
import IconFacebook from 'src/components/icons/IconFacebook';
import IconInstagram from 'src/components/icons/IconInstagram';
import IconTwitter from 'src/components/icons/IconTwitter';
import IconYoutube from 'src/components/icons/IconYoutube';
import { SOCIAL_LINKS } from 'src/utils/constanst.utils';
import IconVisa from '../../../../../assets/imgs/visa.png';
import IconMasterCard from '../../../../../assets/imgs/mastercard.png';
import IconGooglePlay from '../../../../../assets/imgs/gpay.png';
import IconApplePay from '../../../../../assets/imgs/apple_pay.png';
import s from './FooterSocial.module.scss';
const SOCIAL_MENU = [
{
icon: <IconFacebook />,
link: SOCIAL_LINKS.FB,
},
{
icon: <IconTwitter />,
link: SOCIAL_LINKS.TWITTER,
},
{
icon: <IconYoutube />,
link: SOCIAL_LINKS.YOUTUBE,
},
{
icon: <IconInstagram />,
link: SOCIAL_LINKS.IG,
},
]
const PAYMENT_METHODS = [
{
icon: IconVisa.src,
name: 'Visa'
},
{
icon: IconMasterCard.src,
name: 'Master Card'
},
{
icon: IconGooglePlay.src,
name: 'GooglePay'
},
{
icon: IconApplePay.src,
name: 'Apple Pay'
},
]
const FooterSocial = () => {
return (
<section className={s.footerSocial}>
<div className={s.title}>Social</div>
<ul className={s.socialMedia}>
{
SOCIAL_MENU.map(item => <li key={item.link}>
<a href={item.link} target="_blank" rel="noopener noreferrer">
{item.icon}
</a>
</li>)
}
</ul>
<ul className={s.payment}>
{
PAYMENT_METHODS.map(item => <li key={item.name}>
<img src={item.icon} alt={item.name} />
</li>)
}
</ul>
</section>
);
};
export default FooterSocial;

View File

@ -1,22 +1,16 @@
@import "../../../styles/utilities";
.header {
.btn {
// @apply font-bold py-2 px-4 rounded;
@apply sticky bg-white shadow-md;
top: 0;
z-index: 9999;
margin-bottom: 3.2rem;
&.full {
@apply shadow-none;
border: 1px solid var(--border-line);
}
.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 font-heading;
}
.paragraph {
@apply topline;
}
.logo {
@apply font-logo;
.menu {
padding-left: 3.2rem;
padding-right: 3.2rem;
}
}

View File

@ -1,4 +1,10 @@
import { FC } from 'react'
import classNames from 'classnames'
import React, { memo, useEffect, useState } from 'react'
import { isMobile } from 'src/utils/funtion.utils'
import HeaderHighLight from './components/HeaderHighLight/HeaderHighLight'
import HeaderMenu from './components/HeaderMenu/HeaderMenu'
import HeaderSubMenu from './components/HeaderSubMenu/HeaderSubMenu'
import HeaderSubMenuMobile from './components/HeaderSubMenuMobile/HeaderSubMenuMobile'
import s from './Header.module.scss'
interface Props {
@ -6,14 +12,37 @@ interface Props {
children?: any
}
const Header: FC<Props> = ({ }: Props) => {
const Header = memo(({ }: Props) => {
const [isFullHeader, setIsFullHeader] = useState<boolean>(true)
useEffect(() => {
window.addEventListener('scroll', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
const handleScroll = () => {
if (!isMobile()) {
if (window.scrollY === 0) {
setIsFullHeader(true)
} else {
setIsFullHeader(false)
}
}
}
return (
<div className={s.header}>
This is Header
<h1 className={s.heading}>This is heading</h1>
<div className={s.logo}>This is logo text</div>
</div>
<>
<header className={classNames({ [s.header]: true, [s.full]: isFullHeader })}>
<HeaderHighLight isShow={isFullHeader} />
<div className={s.menu}>
<HeaderMenu isFull={isFullHeader} />
<HeaderSubMenu isShow={isFullHeader} />
</div>
</header>
<HeaderSubMenuMobile />
</>
)
}
})
export default Header

View File

@ -0,0 +1,39 @@
@import "../../../../../styles/utilities";
.headerHighLight {
@apply hidden;
@screen md {
transform: translateY(-10rem);
height: 0;
&.show {
@apply flex justify-between items-center spacing-horizontal bg-primary caption;
animation: showHeaderHightlight 0.2s;
height: unset;
transform: none;
padding-top: 0.8rem;
padding-bottom: 0.8rem;
color: var(--white);
.menu {
@apply flex items-center list-none;
padding: 0.8rem 0;
li {
&:not(:last-child) {
margin-right: 3.2rem;
}
a {
@appy no-underline;
}
}
}
}
}
}
@keyframes showHeaderHightlight {
0% {
transform: translateY(-4rem);
}
100% {
transform: none;
}
}

View File

@ -0,0 +1,49 @@
import classNames from 'classnames'
import Link from 'next/link'
import { memo, useEffect, useRef } from 'react'
import { ROUTE } from 'src/utils/constanst.utils'
import s from './HeaderHighLight.module.scss'
const MENU = [
{
name: 'Delivery & Policy',
link: ROUTE.PRIVACY_POLICY,
},
{
name: 'Blog',
link: ROUTE.BLOGS,
},
{
name: 'About Us',
link: ROUTE.ABOUT,
},
]
interface Props {
children?: any,
isShow: boolean,
}
const HeaderHighLight = memo(({ isShow }: Props) => {
return (
<section className={classNames({ [s.headerHighLight]: true, [s.show]: isShow })}>
<div>
Free Shipping on order $49+ / Express $99+
</div>
<ul className={s.menu}>
{
MENU.map(item => <li key={item.name}>
<Link href={item.link}>
<a >
{item.name}
</a>
</Link>
</li>)
}
</ul>
</section>
)
})
export default HeaderHighLight

View File

@ -0,0 +1,65 @@
@import "../../../../../styles/utilities";
.headerMenu {
padding-top: 1.6rem;
padding-bottom: 0.8rem;
@screen md {
@apply flex justify-between items-center;
padding-top: 0.8rem;
padding-bottom: 0.8rem;
&.full {
padding-top: 2.4rem;
padding-bottom: 2.4rem;
}
}
.left {
.top {
@apply flex justify-between items-center;
.iconCart {
}
}
.inputSearch {
margin-top: 2.4rem;
@screen lg {
min-width: 51.2rem;
max-width: 50%;
}
}
@screen md {
@apply flex items-center;
.top {
.iconCart {
@apply hidden;
}
}
.inputSearch {
margin-left: 4.8rem;
margin-top: 0;
}
}
}
.menu {
@apply hidden;
@screen md {
@apply flex items-center list-none;
li {
@apply flex justify-center items-center w-full;
&:not(:last-child) {
margin-right: 4.8rem;
@screen lg {
margin-right: 6.4rem;
}
}
a {
@appy no-underline;
&.iconFovourite {
svg path {
fill: var(--negative);
}
}
}
}
}
}
}

View File

@ -0,0 +1,69 @@
import classNames from 'classnames'
import Link from 'next/link'
import { memo } from 'react'
import InputSearch from 'src/components/common/InputSearch/InputSearch'
import MenuDropdown from 'src/components/common/MenuDropdown/MenuDropdown'
import { IconBuy, IconHeart, IconHistory, IconUser } from 'src/components/icons'
import { ACCOUNT_TAB, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'
import s from './HeaderMenu.module.scss'
const OPTION_MENU = [
{
link: ROUTE.ACCOUNT,
name: 'Account',
},
{
link: '/',
name: 'Logout',
},
]
interface Props {
children?: any,
isFull: boolean,
}
const HeaderMenu = memo(({ isFull }: Props) => {
return (
<section className={classNames({ [s.headerMenu]: true, [s.full]: isFull })}>
<div className={s.left}>
<div className={s.top}>
<div>Online Grocery</div>
<button className={s.iconCart}>
<IconBuy />
</button>
</div>
<div className={s.inputSearch}>
<InputSearch />
</div>
</div>
<ul className={s.menu}>
<li>
<Link href={`${ROUTE.ACCOUNT}?${QUERY_KEY.TAB}=${ACCOUNT_TAB.ORDER}`}>
<a >
<IconHistory />
</a>
</Link>
</li>
<li>
<Link href={`${ROUTE.ACCOUNT}?${QUERY_KEY.TAB}=${ACCOUNT_TAB.FAVOURITE}`}>
<a className={s.iconFovourite}>
<IconHeart />
</a>
</Link>
</li>
<li>
<MenuDropdown options={OPTION_MENU} isHasArrow={false}><IconUser /></MenuDropdown>
</li>
<li>
<button>
<IconBuy />
</button>
</li>
</ul>
</section>
)
})
export default HeaderMenu

View File

@ -0,0 +1,3 @@
.headerNoti {
@apply flex items-center;
}

View File

@ -0,0 +1,16 @@
import React from 'react';
import NotiMessage from 'src/components/common/NotiMessage/NotiMessage';
import { IconInfo } from 'src/components/icons';
import s from './HeaderNoti.module.scss';
const HeaderNoti = () => {
return (
<NotiMessage>
<div className={s.headerNoti}>
<IconInfo />&nbsp;<span>You can buy fresh products after <b>11pm</b> or <b>8am</b></span>
</div>
</NotiMessage>
);
};
export default HeaderNoti;

View File

@ -0,0 +1,42 @@
@import "../../../../../styles/utilities";
.headerSubMenu {
@apply hidden;
@screen md {
transform: translateY(-10rem);
height: 0;
&.show {
@apply block;
padding-bottom: 2.4rem;
transform: none;
height: unset;
@screen lg {
@apply flex justify-between items-center;
}
.menu {
@apply flex items-center list-none;
margin-bottom: 2.4rem;
@screen lg {
margin-bottom: 0;
}
li {
&:not(:last-child) {
margin-right: 2.4rem;
@screen lg {
margin-right: 4rem;
}
}
a {
@appy no-underline;
}
&:hover {
@apply text-primary;
}
&.active {
@apply text-primary;
}
}
}
}
}
}

View File

@ -0,0 +1,88 @@
import classNames from 'classnames'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { memo } from 'react'
import MenuDropdown from 'src/components/common/MenuDropdown/MenuDropdown'
import { ProductFeature, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'
import HeaderNoti from './HeaderNoti/HeaderNoti'
import s from './HeaderSubMenu.module.scss'
const MENU = [
{
name: 'New Items',
link: `${ROUTE.PRODUCTS}?${QUERY_KEY.FEATURED}=${ProductFeature.NewItem}`,
},
{
name: 'Sales',
link: `${ROUTE.PRODUCTS}?${QUERY_KEY.FEATURED}=${ProductFeature.Sales}`,
},
{
name: 'Best Sellers',
link: `${ROUTE.PRODUCTS}?${QUERY_KEY.FEATURED}=${ProductFeature.BestSellers}`,
},
{
name: 'About Us',
link: ROUTE.ABOUT,
},
{
name: 'Blog',
link: ROUTE.BLOGS,
},
]
// note: hard code, remove later
const CATEGORY = [
{
name: 'Veggie',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=veggie`,
},
{
name: 'Seafood',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=seafood`,
},
{
name: 'Frozen',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=frozen`,
},
{
name: 'Coffee Bean',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=coffee-bean`,
},
{
name: 'Sauce',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=sauce`,
},
]
interface Props {
children?: any,
isShow: boolean,
}
const HeaderSubMenu = memo(({ isShow }: Props) => {
const router = useRouter()
return (
<section className={classNames({ [s.headerSubMenu]: true, [s.show]: isShow })}>
<ul className={s.menu}>
{/* todo: handle active item */}
<li>
<MenuDropdown options={CATEGORY} align="left">Categories</MenuDropdown>
</li>
{
MENU.map(item => <li key={item.name}
className={classNames({ [s.active]: router.asPath === item.link })}>
<Link href={item.link}>
<a >
{item.name}
</a>
</Link>
</li>)
}
</ul>
<HeaderNoti />
</section>
)
})
export default HeaderSubMenu

View File

@ -0,0 +1,50 @@
@import "../../../../../styles/utilities";
.headerSubMenuMobile {
@apply fixed w-full bg-white;
bottom: 0;
left: 0;
padding: 2rem 1rem;
border-top: 1px solid var(--border-line);
box-shadow: -5px 6px 10px rgba(0, 0, 0, 0.2);
.menu {
@apply grid grid-cols-4;
li {
a {
@apply transition-all duration-200 no-underline;
&:hover {
color: var(--primary);
}
}
.menuItem {
@apply flex flex-col justify-center items-center sm-label;
.icon {
position: relative;
margin-bottom: 0.5rem;
svg path {
fill: currentColor;
}
}
&.active {
@apply text-primary;
}
&.dot {
.icon {
&::after {
@apply absolute bg-negative rounded-full;
content: "";
top: 0;
right: 0;
$size: 1rem;
width: $size;
height: $size;
}
}
}
}
}
}
@screen md {
@apply hidden;
}
}

View File

@ -0,0 +1,66 @@
import classNames from 'classnames'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { memo } from 'react'
import { IconHeart, IconHome, IconShopping, IconUser } from 'src/components/icons'
import { ACCOUNT_TAB, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'
import s from './HeaderSubMenuMobile.module.scss'
const OPTION_MENU = [
{
link: ROUTE.HOME,
name: 'Home',
icon: <IconHome />,
isMarked: true,
},
{
link: ROUTE.PRODUCTS,
name: 'Shopping',
icon: <IconShopping />,
isMarked: false,
},
{
link: `${ROUTE.ACCOUNT}?${QUERY_KEY.TAB}=${ACCOUNT_TAB.FAVOURITE}`,
name: 'Favourites',
icon: <IconHeart />,
isMarked: false,
},
{
link: ROUTE.ACCOUNT,
name: 'Account',
icon: <IconUser />,
isMarked: false,
},
]
interface Props {
children?: any
}
const HeaderSubMenuMobile = memo(({ }: Props) => {
const router = useRouter()
return (
<header className={s.headerSubMenuMobile}>
<ul className={s.menu}>
{
OPTION_MENU.map(item => <li key={item.name}>
<Link href={item.link}>
<a >
<div className={classNames({
[s.menuItem]: true,
[s.dot]: item.isMarked,
[s.active]: router.pathname === item.link, // todo: handle active item
})}>
<span className={s.icon}>{item.icon}</span>
<span className={s.label}>{item.name}</span>
</div>
</a>
</Link>
</li>)
}
</ul>
</header>
)
})
export default HeaderSubMenuMobile

View File

@ -7,7 +7,7 @@
color: var(--negative);
}
&.light {
color: var(--disabled);
color: var(--white);
}
&.center {
@apply text-center;

View File

@ -11,11 +11,11 @@ interface HeadingCommonProps {
const HeadingCommon = ({ type='default', align='left', children }: HeadingCommonProps) => {
return (
<div className={classNames(s.headingCommon, {
<h1 className={classNames(s.headingCommon, {
[s[type]]: type,
[s[align]]: align
})}
>{children}</div>
>{children}</h1>
)
}

View File

@ -1,5 +1,44 @@
@import "../../../styles/utilities";
.inputCommon {
@apply custom-border-radius transition-all duration-200;
.inputWrap {
@apply flex items-center relative;
.icon {
@apply absolute;
content: "";
left: 1.6rem;
margin-right: 1.6rem;
svg path {
fill: currentColor;
}
}
.icon + .inputCommon {
padding-left: 4.8rem;
}
.inputCommon {
@apply block w-full transition-all duration-200 rounded;
padding: 1.2rem 1.6rem;
border: 1px solid var(--border-line);
&:hover,
&:focus,
&:active {
outline: none;
border: 1px solid var(--primary);
@apply shadow-md;
}
&::placeholder {
@apply text-label;
}
&.custom {
@apply custom-border-radius;
border: 1px solid transparent;
background: var(--gray);
&:hover,
&:focus,
&:active {
border: 1px solid var(--primary);
}
}
}
}

View File

@ -5,17 +5,19 @@ import s from './InputCommon.module.scss';
type Ref = {
focus: () => void
} | null;
interface Props {
children?: React.ReactNode,
value?: string | number,
placeholder?: string,
type?: 'text' | 'number',
styleType?: 'default' | 'custom',
icon?: React.ReactNode,
onChange?: (value: string | number) => void,
onEnter?: (value: string | number) => void,
}
const InputCommon = forwardRef<Ref, Props>(({ value, placeholder, type, onChange, onEnter }: Props, ref) => {
const InputCommon = forwardRef<Ref, Props>(({ value, placeholder, type, styleType = 'default', icon,
onChange, onEnter }: Props, ref) => {
const inputElementRef = useRef<HTMLInputElement>(null);
useImperativeHandle(ref, () => ({
@ -36,15 +38,20 @@ const InputCommon = forwardRef<Ref, Props>(({ value, placeholder, type, onChange
}
return (
<input
ref={inputElementRef}
value={value}
type={type}
placeholder={placeholder}
onChange={handleChange}
onKeyDown={handleKeyDown}
className={s.inputCommon}
/>
<div className={s.inputWrap}>
{
icon && <span className={s.icon}>{icon}</span>
}
<input
ref={inputElementRef}
value={value}
type={type}
placeholder={placeholder}
onChange={handleChange}
onKeyDown={handleKeyDown}
className={`${s.inputCommon} ${s[styleType]}`}
/>
</div>
)
})

View File

@ -0,0 +1,22 @@
import React from 'react';
import { IconSearch } from 'src/components/icons';
import { LANGUAGE } from 'src/utils/language.utils';
import { Inputcommon } from '..';
interface Props {
onChange?: (value: string | number) => void,
onEnter?: (value: string | number) => void,
}
const InputSearch = ({ onChange, onEnter }: Props) => {
return (
<Inputcommon placeholder={LANGUAGE.PLACE_HOLDER.SEARCH}
styleType='custom'
icon={<IconSearch />}
onChange={onChange}
onEnter={onEnter}
/>
)
}
export default InputSearch

View File

@ -0,0 +1,8 @@
.mainLayout {
display: flex;
flex-direction: column;
min-height: 100vh;
> main {
flex: 1;
}
}

View File

@ -1,7 +1,9 @@
import { FC, useRef, useEffect } from 'react'
import Header from '../Header/Header'
import { CommerceProvider } from '@framework'
import { useRouter } from 'next/router'
import { FC } from 'react'
import Footer from '../Footer/Footer'
import Header from '../Header/Header'
import s from './Layout.module.scss'
interface Props {
className?: string
@ -14,8 +16,11 @@ const Layout: FC<Props> = ({ children }) => {
return (
<CommerceProvider locale={locale}>
<Header />
<main>{children}</main>
<div className={s.mainLayout}>
<Header />
<main >{children}</main>
<Footer />
</div>
</CommerceProvider>
)

View File

@ -0,0 +1,90 @@
@import "../../../styles/utilities";
.menuDropdown {
@apply relative cursor-pointer;
width: fit-content;
&:hover {
.label {
color: var(--primary);
svg path {
fill: currentColor;
}
}
.menu {
@apply block;
animation: menuDropdownAnimation 0.2s ease-out;
}
}
.label {
@apply flex justify-end items-center transition-all duration-200;
svg path {
width: fit-content;
}
}
&.arrow {
.label {
margin-right: 1.6rem;
}
&::after {
@apply inline-block absolute transition-all duration-100;
content: "";
top: 35%;
right: 0;
border: solid currentColor;
border-width: 0 2px 2px 0;
padding: 2px;
transform: rotate(45deg);
}
&:hover {
&::after {
@apply border-primary;
transform: rotate(-135deg);
}
}
}
.menu {
@apply hidden absolute;
content: "";
right: 0;
top: 2rem;
height: max-content;
min-width: 19.2rem;
z-index: 100;
&.left {
left: 0;
}
&:hover {
@apply block shadow-md;
}
.menuIner {
@apply rounded list-none bg-white;
border: 1px solid var(--text-active);
margin-top: .4rem;
li {
@apply block w-full transition-all duration-200 cursor-pointer text-active;
padding: 0.8rem 1.6rem;
&:hover {
@apply bg-primary-lightest;
color: var(--primary);
}
a {
@apply block;
}
}
}
}
}
@keyframes menuDropdownAnimation {
0% {
opacity: 0;
transform: translateY(1.6rem);
}
100% {
opacity: 1;
transform: none;
}
}

View File

@ -0,0 +1,42 @@
import classNames from 'classnames';
import Link from 'next/link';
import React from 'react';
import s from './MenuDropdown.module.scss';
interface Props {
children?: React.ReactNode,
options: { link: string, name: string }[],
isHasArrow?: boolean,
align?: 'left'
}
const MenuDropdown = ({ options, children, isHasArrow = true, align }: Props) => {
return (
<div className={classNames({
[s.menuDropdown]: true,
[s.arrow]: isHasArrow,
})}>
<span className={s.label}>
{children}
</span>
<section className={classNames({
[s.menu]: true,
[s.left]: align === 'left',
})} >
<ul className={s.menuIner}>
{
options.map(item => <li key={item.name}>
<Link href={item.link}>
<a >
{item.name}
</a>
</Link>
</li>)
}
</ul>
</section>
</div>
);
};
export default MenuDropdown;

View File

@ -0,0 +1,9 @@
@import "../../../styles/utilities";
.notiMessage {
@apply caption bg-info-light;
width: fit-content;
color: var(--info-dark);
padding: 0.4rem 1.6rem;
border-radius: 3rem;
}

View File

@ -0,0 +1,16 @@
import React from 'react'
import s from './NotiMessage.module.scss'
interface Props {
children?: React.ReactNode
}
const NotiMessage = ({ children }: Props) => {
return (
<div className={s.notiMessage}>
{children}
</div>
)
}
export default NotiMessage

View File

@ -11,4 +11,10 @@ export { default as Inputcommon} from './InputCommon/InputCommon'
export { default as HeadingCommon } from './HeadingCommon/HeadingCommon'
export { default as CollectionHeading } from './CollectionHeading/CollectionHeading'
export { default as ScrollToTop } from './ScrollToTop/ScrollToTop'
export { default as ScrollTarget } from './ScrollToTop/ScrollTarget'
export { default as ScrollTarget } from './ScrollToTop/ScrollTarget'
export { default as InputSearch} from './InputSearch/InputSearch'
export { default as ButtonIconBuy} from './ButtonIconBuy/ButtonIconBuy'
export { default as Banner} from './Banner/Banner'
export { default as Footer} from './Footer/Footer'
export { default as MenuDropdown} from './MenuDropdown/MenuDropdown'
export { default as NotiMessage} from './NotiMessage/NotiMessage'

View File

@ -1,20 +0,0 @@
const Vector = ({ ...props }) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M20.16 4.99992C19.1 3.93713 17.6948 3.28846 16.1984 3.17109C14.7019 3.05372 13.2128 3.47539 12 4.35992C10.7277 3.41356 9.14402 2.98443 7.56795 3.15896C5.99188 3.33348 4.54047 4.0987 3.506 5.30051C2.47154 6.50231 1.93085 8.05144 1.99283 9.63594C2.05481 11.2204 2.71485 12.7226 3.84003 13.8399L10.05 20.0599C10.57 20.5717 11.2704 20.8585 12 20.8585C12.7296 20.8585 13.43 20.5717 13.95 20.0599L20.16 13.8399C21.3276 12.6652 21.983 11.0762 21.983 9.41992C21.983 7.76365 21.3276 6.17465 20.16 4.99992ZM18.75 12.4599L12.54 18.6699C12.4694 18.7413 12.3853 18.7979 12.2926 18.8366C12.1999 18.8752 12.1005 18.8951 12 18.8951C11.8996 18.8951 11.8002 18.8752 11.7075 18.8366C11.6148 18.7979 11.5307 18.7413 11.46 18.6699L5.25003 12.4299C4.46579 11.6283 4.02664 10.5514 4.02664 9.42992C4.02664 8.30846 4.46579 7.23158 5.25003 6.42992C6.04919 5.64091 7.127 5.19849 8.25003 5.19849C9.37306 5.19849 10.4509 5.64091 11.25 6.42992C11.343 6.52365 11.4536 6.59804 11.5755 6.64881C11.6973 6.69958 11.828 6.72572 11.96 6.72572C12.092 6.72572 12.2227 6.69958 12.3446 6.64881C12.4665 6.59804 12.5771 6.52365 12.67 6.42992C13.4692 5.64091 14.547 5.19849 15.67 5.19849C16.7931 5.19849 17.8709 5.64091 18.67 6.42992C19.4651 7.22107 19.9186 8.29211 19.9336 9.41361C19.9485 10.5351 19.5237 11.6179 18.75 12.4299V12.4599Z"
fill={props.color}
/>
</svg>
)
}
export default Vector

View File

@ -0,0 +1,11 @@
import React from 'react'
const IconArrowRight = () => {
return (
<svg width="12" height="14" viewBox="0 0 12 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.92 6.62019C11.8724 6.49743 11.801 6.38529 11.71 6.29019L6.71 1.29019C6.61676 1.19695 6.50607 1.12299 6.38425 1.07253C6.26243 1.02207 6.13186 0.996094 6 0.996094C5.7337 0.996094 5.4783 1.10188 5.29 1.29019C5.19676 1.38342 5.1228 1.49411 5.07234 1.61594C5.02188 1.73776 4.99591 1.86833 4.99591 2.00019C4.99591 2.26649 5.1017 2.52188 5.29 2.71019L8.59 6.00019H1C0.734784 6.00019 0.48043 6.10554 0.292893 6.29308C0.105357 6.48062 0 6.73497 0 7.00019C0 7.2654 0.105357 7.51976 0.292893 7.70729C0.48043 7.89483 0.734784 8.00019 1 8.00019H8.59L5.29 11.2902C5.19627 11.3831 5.12188 11.4937 5.07111 11.6156C5.02034 11.7375 4.9942 11.8682 4.9942 12.0002C4.9942 12.1322 5.02034 12.2629 5.07111 12.3848C5.12188 12.5066 5.19627 12.6172 5.29 12.7102C5.38296 12.8039 5.49356 12.8783 5.61542 12.9291C5.73728 12.9798 5.86799 13.006 6 13.006C6.13201 13.006 6.26272 12.9798 6.38458 12.9291C6.50644 12.8783 6.61704 12.8039 6.71 12.7102L11.71 7.71019C11.801 7.61508 11.8724 7.50294 11.92 7.38019C12.02 7.13672 12.02 6.86365 11.92 6.62019Z" fill="white" />
</svg>
)
}
export default IconArrowRight

View File

@ -0,0 +1,11 @@
import React from 'react'
const IconFacebook = () => {
return (
<svg width="11" height="20" viewBox="0 0 11 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.12035 3.32003H11.0004V0.14003C10.0901 0.045377 9.17551 -0.00135428 8.26035 2.98641e-05C5.54035 2.98641e-05 3.68035 1.66003 3.68035 4.70003V7.32003H0.610352V10.88H3.68035V20H7.36035V10.88H10.4204L10.8804 7.32003H7.36035V5.05003C7.36035 4.00003 7.64035 3.32003 9.12035 3.32003Z" fill="#141414" />
</svg>
)
}
export default IconFacebook

View File

@ -0,0 +1,11 @@
import React from 'react'
const IconHeart = () => {
return (
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19.1598 2.61006C18.0981 1.54806 16.6905 0.902384 15.193 0.790439C13.6955 0.678494 12.2076 1.10772 10.9998 2.00006C9.72744 1.0537 8.14378 0.624569 6.56771 0.799095C4.99164 0.973621 3.54023 1.73884 2.50576 2.94064C1.47129 4.14245 0.93061 5.69158 0.992588 7.27607C1.05457 8.86057 1.71461 10.3627 2.83979 11.4801L10.2898 18.9301C10.3828 19.0238 10.4934 19.0982 10.6152 19.1489C10.7371 19.1997 10.8678 19.2259 10.9998 19.2259C11.1318 19.2259 11.2625 19.1997 11.3844 19.1489C11.5062 19.0982 11.6168 19.0238 11.7098 18.9301L19.1598 11.4801C19.7424 10.8978 20.2047 10.2064 20.52 9.44542C20.8354 8.68445 20.9977 7.86879 20.9977 7.04506C20.9977 6.22133 20.8354 5.40567 20.52 4.64469C20.2047 3.88371 19.7424 3.19233 19.1598 2.61006ZM17.7498 10.0701L10.9998 16.8101L4.24979 10.0701C3.65496 9.47276 3.24976 8.71311 3.08502 7.8864C2.92027 7.05969 3.00332 6.20274 3.32374 5.42305C3.64416 4.64336 4.18768 3.97565 4.88613 3.50368C5.58458 3.03171 6.40685 2.7765 7.24979 2.77006C8.3759 2.77282 9.45488 3.22239 10.2498 4.02006C10.3428 4.11379 10.4534 4.18818 10.5752 4.23895C10.6971 4.28972 10.8278 4.31586 10.9598 4.31586C11.0918 4.31586 11.2225 4.28972 11.3444 4.23895C11.4662 4.18818 11.5768 4.11379 11.6698 4.02006C12.4881 3.31094 13.5453 2.9392 14.6273 2.98008C15.7094 3.02096 16.7355 3.47141 17.498 4.24025C18.2605 5.00909 18.7024 6.0389 18.7343 7.12125C18.7662 8.2036 18.3857 9.25765 17.6698 10.0701H17.7498Z" fill="#141414" />
</svg>
)
}
export default IconHeart

View File

@ -0,0 +1,11 @@
import React from 'react'
const IconHistory = () => {
return (
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 0C7.43639 0.00731219 4.97349 0.998914 3.12 2.77V1C3.12 0.734784 3.01464 0.48043 2.82711 0.292893C2.63957 0.105357 2.38522 0 2.12 0C1.85478 0 1.60043 0.105357 1.41289 0.292893C1.22536 0.48043 1.12 0.734784 1.12 1V5.5C1.12 5.76522 1.22536 6.01957 1.41289 6.20711C1.60043 6.39464 1.85478 6.5 2.12 6.5H6.62C6.88522 6.5 7.13957 6.39464 7.32711 6.20711C7.51464 6.01957 7.62 5.76522 7.62 5.5C7.62 5.23478 7.51464 4.98043 7.32711 4.79289C7.13957 4.60536 6.88522 4.5 6.62 4.5H4.22C5.50578 3.15636 7.21951 2.30265 9.06653 2.08567C10.9136 1.86868 12.7785 2.30198 14.3407 3.31104C15.9028 4.32011 17.0646 5.84191 17.6263 7.61479C18.188 9.38767 18.1145 11.3009 17.4184 13.0254C16.7223 14.7499 15.4472 16.1781 13.8122 17.0643C12.1772 17.9505 10.2845 18.2394 8.45956 17.8813C6.63463 17.5232 4.99147 16.5405 3.81259 15.1022C2.63372 13.6638 1.99279 11.8597 2 10C2 9.73478 1.89464 9.48043 1.70711 9.29289C1.51957 9.10536 1.26522 9 1 9C0.734784 9 0.48043 9.10536 0.292893 9.29289C0.105357 9.48043 0 9.73478 0 10C0 11.9778 0.58649 13.9112 1.6853 15.5557C2.78412 17.2002 4.3459 18.4819 6.17317 19.2388C8.00043 19.9957 10.0111 20.1937 11.9509 19.8079C13.8907 19.422 15.6725 18.4696 17.0711 17.0711C18.4696 15.6725 19.422 13.8907 19.8079 11.9509C20.1937 10.0111 19.9957 8.00043 19.2388 6.17317C18.4819 4.3459 17.2002 2.78412 15.5557 1.6853C13.9112 0.58649 11.9778 0 10 0ZM10 6C9.73478 6 9.48043 6.10536 9.29289 6.29289C9.10536 6.48043 9 6.73478 9 7V10C9 10.2652 9.10536 10.5196 9.29289 10.7071C9.48043 10.8946 9.73478 11 10 11H12C12.2652 11 12.5196 10.8946 12.7071 10.7071C12.8946 10.5196 13 10.2652 13 10C13 9.73478 12.8946 9.48043 12.7071 9.29289C12.5196 9.10536 12.2652 9 12 9H11V7C11 6.73478 10.8946 6.48043 10.7071 6.29289C10.5196 6.10536 10.2652 6 10 6Z" fill="#5B9A74" />
</svg>
)
}
export default IconHistory

View File

@ -0,0 +1,11 @@
import React from 'react'
const IconHome = () => {
return (
<svg width="18" height="21" viewBox="0 0 18 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.0001 7.00001L11.0001 1.74001C10.4501 1.24805 9.73803 0.976074 9.00009 0.976074C8.26216 0.976074 7.55012 1.24805 7.00009 1.74001L1.00009 7.00001C0.682463 7.28408 0.428995 7.63256 0.256567 8.02225C0.0841385 8.41194 -0.00329256 8.83389 9.47941e-05 9.26001V18C9.47941e-05 18.7957 0.316165 19.5587 0.878775 20.1213C1.44138 20.6839 2.20445 21 3.00009 21H15.0001C15.7957 21 16.5588 20.6839 17.1214 20.1213C17.684 19.5587 18.0001 18.7957 18.0001 18V9.25001C18.0021 8.82557 17.9139 8.40555 17.7416 8.01769C17.5692 7.62983 17.3165 7.28296 17.0001 7.00001ZM11.0001 19H7.00009V14C7.00009 13.7348 7.10545 13.4804 7.29299 13.2929C7.48052 13.1054 7.73488 13 8.00009 13H10.0001C10.2653 13 10.5197 13.1054 10.7072 13.2929C10.8947 13.4804 11.0001 13.7348 11.0001 14V19ZM16.0001 18C16.0001 18.2652 15.8947 18.5196 15.7072 18.7071C15.5197 18.8946 15.2653 19 15.0001 19H13.0001V14C13.0001 13.2044 12.684 12.4413 12.1214 11.8787C11.5588 11.3161 10.7957 11 10.0001 11H8.00009C7.20444 11 6.44138 11.3161 5.87877 11.8787C5.31616 12.4413 5.00009 13.2044 5.00009 14V19H3.00009C2.73488 19 2.48052 18.8946 2.29299 18.7071C2.10545 18.5196 2.00009 18.2652 2.00009 18V9.25001C2.00027 9.10802 2.03069 8.9677 2.08931 8.83839C2.14794 8.70907 2.23343 8.59372 2.3401 8.50001L8.34009 3.25001C8.52258 3.08969 8.75719 3.00127 9.00009 3.00127C9.243 3.00127 9.47761 3.08969 9.66009 3.25001L15.6601 8.50001C15.7668 8.59372 15.8523 8.70907 15.9109 8.83839C15.9695 8.9677 15.9999 9.10802 16.0001 9.25001V18Z" fill="#141414" />
</svg>
)
}
export default IconHome

View File

@ -0,0 +1,11 @@
import React from 'react'
const IconInfo = () => {
return (
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.99968 6.3335C6.82287 6.3335 6.6533 6.40373 6.52827 6.52876C6.40325 6.65378 6.33301 6.82335 6.33301 7.00016V9.66683C6.33301 9.84364 6.40325 10.0132 6.52827 10.1382C6.6533 10.2633 6.82287 10.3335 6.99968 10.3335C7.17649 10.3335 7.34606 10.2633 7.47108 10.1382C7.59611 10.0132 7.66634 9.84364 7.66634 9.66683V7.00016C7.66634 6.82335 7.59611 6.65378 7.47108 6.52876C7.34606 6.40373 7.17649 6.3335 6.99968 6.3335ZM7.25301 3.72016C7.0907 3.65348 6.90865 3.65348 6.74634 3.72016C6.66451 3.75189 6.58975 3.79947 6.52634 3.86016C6.46746 3.92496 6.4201 3.99937 6.38634 4.08016C6.34902 4.15928 6.33076 4.24605 6.33301 4.3335C6.3325 4.42123 6.34932 4.50821 6.3825 4.58943C6.41567 4.67066 6.46456 4.74454 6.52634 4.80683C6.59114 4.86572 6.66555 4.91307 6.74634 4.94683C6.84734 4.98832 6.95699 5.00437 7.06564 4.99357C7.1743 4.98277 7.27863 4.94544 7.36949 4.88488C7.46034 4.82431 7.53492 4.74235 7.58668 4.64621C7.63845 4.55007 7.6658 4.44269 7.66634 4.3335C7.66389 4.15698 7.59483 3.98792 7.47301 3.86016C7.40961 3.79947 7.33485 3.75189 7.25301 3.72016ZM6.99968 0.333496C5.68114 0.333496 4.3922 0.724489 3.29588 1.45703C2.19955 2.18957 1.34506 3.23077 0.840481 4.44894C0.335896 5.66711 0.203874 7.00756 0.461109 8.30077C0.718344 9.59397 1.35328 10.7819 2.28563 11.7142C3.21798 12.6466 4.40587 13.2815 5.69908 13.5387C6.99228 13.796 8.33273 13.6639 9.5509 13.1594C10.7691 12.6548 11.8103 11.8003 12.5428 10.704C13.2753 9.60764 13.6663 8.31871 13.6663 7.00016C13.6663 6.12468 13.4939 5.25778 13.1589 4.44894C12.8238 3.6401 12.3328 2.90517 11.7137 2.28612C11.0947 1.66706 10.3597 1.176 9.5509 0.840966C8.74206 0.505935 7.87516 0.333496 6.99968 0.333496ZM6.99968 12.3335C5.94484 12.3335 4.9137 12.0207 4.03664 11.4347C3.15957 10.8486 2.47599 10.0157 2.07232 9.04114C1.66865 8.0666 1.56303 6.99425 1.76882 5.95968C1.97461 4.92512 2.48256 3.97481 3.22844 3.22893C3.97432 2.48305 4.92463 1.9751 5.9592 1.76931C6.99376 1.56352 8.06612 1.66914 9.04066 2.07281C10.0152 2.47647 10.8481 3.16006 11.4342 4.03712C12.0202 4.91418 12.333 5.94533 12.333 7.00016C12.333 8.41465 11.7711 9.77121 10.7709 10.7714C9.77072 11.7716 8.41417 12.3335 6.99968 12.3335Z" fill="#3468B7" />
</svg>
)
}
export default IconInfo

View File

@ -0,0 +1,11 @@
import React from 'react'
const IconInstagram = () => {
return (
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 7.52C9.5095 7.52 9.03002 7.66545 8.62219 7.93795C8.21435 8.21046 7.89648 8.59778 7.70878 9.05095C7.52107 9.50411 7.47196 10.0028 7.56765 10.4838C7.66334 10.9649 7.89954 11.4068 8.24638 11.7536C8.59321 12.1005 9.0351 12.3367 9.51618 12.4323C9.99725 12.528 10.4959 12.4789 10.9491 12.2912C11.4022 12.1035 11.7895 11.7856 12.062 11.3778C12.3346 10.97 12.48 10.4905 12.48 10C12.48 9.67432 12.4159 9.35183 12.2912 9.05095C12.1666 8.75006 11.9839 8.47666 11.7536 8.24638C11.5233 8.01609 11.2499 7.83341 10.9491 7.70878C10.6482 7.58415 10.3257 7.52 10 7.52ZM19.93 5.07C19.9247 4.29776 19.7825 3.53257 19.51 2.81C19.3093 2.28126 18.9987 1.80109 18.5988 1.40119C18.1989 1.00128 17.7187 0.690718 17.19 0.49C16.4674 0.217464 15.7022 0.0752609 14.93 0.0699999C13.64 -6.70552e-08 13.26 0 10 0C6.74 0 6.36 -6.70552e-08 5.07 0.0699999C4.29776 0.0752609 3.53257 0.217464 2.81 0.49C2.28126 0.690718 1.80109 1.00128 1.40119 1.40119C1.00128 1.80109 0.690718 2.28126 0.49 2.81C0.217464 3.53257 0.0752609 4.29776 0.0699999 5.07C-6.70552e-08 6.36 0 6.74 0 10C0 13.26 -6.70552e-08 13.64 0.0699999 14.93C0.0807639 15.705 0.222774 16.4725 0.49 17.2C0.689828 17.7263 1.00013 18.2037 1.4 18.6C1.79819 19.0023 2.27939 19.3129 2.81 19.51C3.53257 19.7825 4.29776 19.9247 5.07 19.93C6.36 20 6.74 20 10 20C13.26 20 13.64 20 14.93 19.93C15.7022 19.9247 16.4674 19.7825 17.19 19.51C17.7206 19.3129 18.2018 19.0023 18.6 18.6C18.9999 18.2037 19.3102 17.7263 19.51 17.2C19.7823 16.4739 19.9244 15.7055 19.93 14.93C20 13.64 20 13.26 20 10C20 6.74 20 6.36 19.93 5.07ZM17.39 13.07C17.3579 13.6871 17.2262 14.295 17 14.87C16.8059 15.3497 16.5173 15.7854 16.1514 16.1514C15.7854 16.5173 15.3497 16.8059 14.87 17C14.2895 17.2136 13.6783 17.3318 13.06 17.35C12.27 17.35 12.06 17.35 10 17.35C7.94 17.35 7.73 17.35 6.94 17.35C6.32173 17.3318 5.71049 17.2136 5.13 17C4.6341 16.8157 4.18628 16.5217 3.82 16.14C3.45767 15.7813 3.17784 15.3479 3 14.87C2.78556 14.2901 2.67061 13.6782 2.66 13.06C2.66 12.27 2.66 12.06 2.66 10C2.66 7.94 2.66 7.73 2.66 6.94C2.67061 6.32183 2.78556 5.70988 3 5.13C3.18428 4.6341 3.47827 4.18628 3.86 3.82C4.22033 3.45962 4.65326 3.18009 5.13 3C5.71049 2.78641 6.32173 2.66821 6.94 2.65C7.73 2.65 7.94 2.65 10 2.65C12.06 2.65 12.27 2.65 13.06 2.65C13.6783 2.66821 14.2895 2.78641 14.87 3C15.3659 3.18428 15.8137 3.47827 16.18 3.86C16.5423 4.21875 16.8222 4.65213 17 5.13C17.2136 5.71049 17.3318 6.32173 17.35 6.94C17.35 7.73 17.35 7.94 17.35 10C17.35 12.06 17.42 12.27 17.39 13.06V13.07ZM15.79 5.63C15.6709 5.30698 15.4832 5.01364 15.2398 4.77021C14.9964 4.52678 14.703 4.33906 14.38 4.22C13.9365 4.06626 13.4693 3.99179 13 4C12.22 4 12 4 10 4C8 4 7.78 4 7 4C6.52827 4.00461 6.06107 4.09263 5.62 4.26C5.30193 4.37366 5.01169 4.55371 4.76858 4.7882C4.52547 5.02269 4.33506 5.30624 4.21 5.62C4.06478 6.06537 3.99383 6.5316 4 7C4 7.78 4 8 4 10C4 12 4 12.22 4 13C4.00991 13.4712 4.09777 13.9375 4.26 14.38C4.37906 14.703 4.56678 14.9964 4.81021 15.2398C5.05364 15.4832 5.34698 15.6709 5.67 15.79C6.09667 15.9469 6.54565 16.0347 7 16.05C7.78 16.05 8 16.05 10 16.05C12 16.05 12.22 16.05 13 16.05C13.4717 16.0454 13.9389 15.9574 14.38 15.79C14.703 15.6709 14.9964 15.4832 15.2398 15.2398C15.4832 14.9964 15.6709 14.703 15.79 14.38C15.9574 13.9389 16.0454 13.4717 16.05 13C16.05 12.22 16.05 12 16.05 10C16.05 8 16.05 7.78 16.05 7C16.0503 6.5278 15.9621 6.05972 15.79 5.62V5.63ZM10 13.82C9.49882 13.82 9.00257 13.7211 8.53966 13.529C8.07676 13.3369 7.6563 13.0554 7.30238 12.7005C6.94846 12.3457 6.66803 11.9245 6.47714 11.4611C6.28626 10.9977 6.18868 10.5012 6.19 10C6.19 9.24405 6.4143 8.5051 6.83449 7.87669C7.25468 7.24828 7.85187 6.75866 8.55047 6.46983C9.24907 6.181 10.0177 6.10594 10.7589 6.25415C11.5002 6.40236 12.1808 6.76717 12.7147 7.30241C13.2485 7.83764 13.6116 8.51924 13.7578 9.2609C13.9041 10.0026 13.827 10.771 13.5363 11.4688C13.2457 12.1666 12.7545 12.7625 12.125 13.1811C11.4955 13.5996 10.7559 13.822 10 13.82ZM14 6.93C13.7789 6.9066 13.5744 6.80222 13.4257 6.63697C13.277 6.47172 13.1947 6.25729 13.1947 6.035C13.1947 5.81271 13.277 5.59828 13.4257 5.43303C13.5744 5.26778 13.7789 5.1634 14 5.14C14.2211 5.1634 14.4256 5.26778 14.5743 5.43303C14.723 5.59828 14.8053 5.81271 14.8053 6.035C14.8053 6.25729 14.723 6.47172 14.5743 6.63697C14.4256 6.80222 14.2211 6.9066 14 6.93Z" fill="#141414" />
</svg>
)
}
export default IconInstagram

View File

@ -0,0 +1,11 @@
import React from 'react'
const IconSearch = () => {
return (
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20.7104 19.2899L17.0004 15.6099C18.4405 13.8143 19.1379 11.5352 18.9492 9.2412C18.7605 6.94721 17.7001 4.81269 15.9859 3.27655C14.2718 1.74041 12.0342 0.919414 9.73332 0.982375C7.43243 1.04534 5.24311 1.98747 3.61553 3.61505C1.98795 5.24263 1.04582 7.43194 0.982863 9.73283C0.919903 12.0337 1.7409 14.2713 3.27704 15.9854C4.81318 17.6996 6.94769 18.76 9.24169 18.9487C11.5357 19.1374 13.8148 18.44 15.6104 16.9999L19.2904 20.6799C19.3834 20.7736 19.494 20.848 19.6158 20.8988C19.7377 20.9496 19.8684 20.9757 20.0004 20.9757C20.1324 20.9757 20.2631 20.9496 20.385 20.8988C20.5068 20.848 20.6174 20.7736 20.7104 20.6799C20.8906 20.4934 20.9914 20.2442 20.9914 19.9849C20.9914 19.7256 20.8906 19.4764 20.7104 19.2899ZM10.0004 16.9999C8.61592 16.9999 7.26255 16.5894 6.1114 15.8202C4.96026 15.051 4.06305 13.9578 3.53324 12.6787C3.00342 11.3996 2.8648 9.99214 3.1349 8.63427C3.40499 7.27641 4.07168 6.02912 5.05065 5.05016C6.02961 4.07119 7.27689 3.4045 8.63476 3.13441C9.99263 2.86431 11.4001 3.00293 12.6792 3.53275C13.9583 4.06256 15.0515 4.95977 15.8207 6.11091C16.5899 7.26206 17.0004 8.61544 17.0004 9.9999C17.0004 11.8564 16.2629 13.6369 14.9501 14.9497C13.6374 16.2624 11.8569 16.9999 10.0004 16.9999Z" fill="#3D3D3D" />
</svg>
)
}
export default IconSearch

View File

@ -0,0 +1,11 @@
import React from 'react'
const IconShopping = () => {
return (
<svg width="20" height="24" viewBox="0 0 20 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18.167 6.16659H14.667V4.99992C14.667 3.76224 14.1753 2.57526 13.3002 1.70009C12.425 0.824917 11.238 0.333252 10.0003 0.333252C8.76265 0.333252 7.57566 0.824917 6.70049 1.70009C5.82532 2.57526 5.33366 3.76224 5.33366 4.99992V6.16659H1.83366C1.52424 6.16659 1.22749 6.2895 1.0087 6.50829C0.789909 6.72709 0.666992 7.02383 0.666992 7.33325V20.1666C0.666992 21.0948 1.03574 21.9851 1.69212 22.6415C2.3485 23.2978 3.23873 23.6666 4.16699 23.6666H15.8337C16.7619 23.6666 17.6522 23.2978 18.3085 22.6415C18.9649 21.9851 19.3337 21.0948 19.3337 20.1666V7.33325C19.3337 7.02383 19.2107 6.72709 18.9919 6.50829C18.7732 6.2895 18.4764 6.16659 18.167 6.16659ZM7.66699 4.99992C7.66699 4.38108 7.91282 3.78759 8.35041 3.35C8.78799 2.91242 9.38149 2.66659 10.0003 2.66659C10.6192 2.66659 11.2127 2.91242 11.6502 3.35C12.0878 3.78759 12.3337 4.38108 12.3337 4.99992V6.16659H7.66699V4.99992ZM17.0003 20.1666C17.0003 20.476 16.8774 20.7728 16.6586 20.9915C16.4398 21.2103 16.1431 21.3333 15.8337 21.3333H4.16699C3.85757 21.3333 3.56083 21.2103 3.34203 20.9915C3.12324 20.7728 3.00033 20.476 3.00033 20.1666V8.49992H5.33366V9.66659C5.33366 9.97601 5.45657 10.2728 5.67537 10.4915C5.89416 10.7103 6.19091 10.8333 6.50032 10.8333C6.80974 10.8333 7.10649 10.7103 7.32528 10.4915C7.54407 10.2728 7.66699 9.97601 7.66699 9.66659V8.49992H12.3337V9.66659C12.3337 9.97601 12.4566 10.2728 12.6754 10.4915C12.8942 10.7103 13.1909 10.8333 13.5003 10.8333C13.8097 10.8333 14.1065 10.7103 14.3253 10.4915C14.5441 10.2728 14.667 9.97601 14.667 9.66659V8.49992H17.0003V20.1666Z" fill="#141414" />
</svg>
)
}
export default IconShopping

View File

@ -0,0 +1,11 @@
import React from 'react'
const IconTwitter = () => {
return (
<svg width="20" height="18" viewBox="0 0 20 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 2.80021C19.2483 3.1263 18.4534 3.34187 17.64 3.44021C18.4982 2.92753 19.1413 2.12099 19.45 1.17021C18.6436 1.65027 17.7608 1.98851 16.84 2.17021C16.2245 1.50278 15.405 1.05851 14.5098 0.907061C13.6147 0.755616 12.6945 0.905568 11.8938 1.3334C11.093 1.76123 10.4569 2.44274 10.0852 3.27105C9.71355 4.09935 9.62729 5.0276 9.84 5.91021C8.20943 5.82774 6.61444 5.40316 5.15865 4.66407C3.70287 3.92498 2.41885 2.8879 1.39 1.62021C1.02914 2.25038 0.839519 2.96403 0.84 3.69021C0.83872 4.36459 1.00422 5.02883 1.32176 5.62377C1.63929 6.21872 2.09902 6.72592 2.66 7.10021C2.00798 7.08247 1.36989 6.90751 0.8 6.59021V6.64021C0.804887 7.5851 1.13599 8.4993 1.73731 9.22818C2.33864 9.95705 3.17326 10.4559 4.1 10.6402C3.74326 10.7488 3.37287 10.806 3 10.8102C2.74189 10.8072 2.48442 10.7838 2.23 10.7402C2.49391 11.553 3.00462 12.2634 3.69107 12.7724C4.37753 13.2814 5.20558 13.5638 6.06 13.5802C4.6172 14.7155 2.83588 15.3351 1 15.3402C0.665735 15.3413 0.331736 15.3213 0 15.2802C1.87443 16.4905 4.05881 17.1329 6.29 17.1302C7.82969 17.1462 9.35714 16.8552 10.7831 16.2743C12.2091 15.6934 13.505 14.8341 14.5952 13.7467C15.6854 12.6593 16.548 11.3656 17.1326 9.94112C17.7172 8.51663 18.012 6.98994 18 5.45021C18 5.28021 18 5.10021 18 4.92021C18.7847 4.33502 19.4615 3.61763 20 2.80021Z" fill="#141414" />
</svg>
)
}
export default IconTwitter

View File

@ -0,0 +1,11 @@
import React from 'react'
const IconUser = () => {
return (
<svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.7105 11.7101C14.6909 10.9388 15.4065 9.88105 15.7577 8.68407C16.109 7.48709 16.0784 6.21039 15.6703 5.03159C15.2621 3.85279 14.4967 2.83052 13.4806 2.10698C12.4644 1.38344 11.2479 0.994629 10.0005 0.994629C8.75303 0.994629 7.5366 1.38344 6.52041 2.10698C5.50423 2.83052 4.73883 3.85279 4.3307 5.03159C3.92257 6.21039 3.892 7.48709 4.24325 8.68407C4.59449 9.88105 5.31009 10.9388 6.29048 11.7101C4.61056 12.3832 3.14477 13.4995 2.04938 14.94C0.953983 16.3806 0.270048 18.0914 0.070485 19.8901C0.0560396 20.0214 0.0676015 20.1543 0.10451 20.2812C0.141419 20.408 0.202952 20.5264 0.285596 20.6294C0.452504 20.8376 0.695269 20.971 0.960485 21.0001C1.2257 21.0293 1.49164 20.9519 1.69981 20.785C1.90798 20.6181 2.04131 20.3753 2.07049 20.1101C2.29007 18.1553 3.22217 16.3499 4.6887 15.0389C6.15524 13.7279 8.05338 13.0032 10.0205 13.0032C11.9876 13.0032 13.8857 13.7279 15.3523 15.0389C16.8188 16.3499 17.7509 18.1553 17.9705 20.1101C17.9977 20.3558 18.1149 20.5828 18.2996 20.7471C18.4843 20.9115 18.7233 21.0016 18.9705 21.0001H19.0805C19.3426 20.97 19.5822 20.8374 19.747 20.6314C19.9119 20.4253 19.9886 20.1625 19.9605 19.9001C19.76 18.0963 19.0724 16.3811 17.9713 14.9383C16.8703 13.4955 15.3974 12.3796 13.7105 11.7101ZM10.0005 11.0001C9.20936 11.0001 8.436 10.7655 7.7782 10.326C7.12041 9.88648 6.60772 9.26176 6.30497 8.53086C6.00222 7.79995 5.923 6.99569 6.07734 6.21976C6.23168 5.44384 6.61265 4.73111 7.17206 4.1717C7.73147 3.61229 8.4442 3.23132 9.22012 3.07698C9.99605 2.92264 10.8003 3.00186 11.5312 3.30461C12.2621 3.60736 12.8868 4.12005 13.3264 4.77784C13.7659 5.43564 14.0005 6.209 14.0005 7.00012C14.0005 8.06099 13.5791 9.07841 12.8289 9.82855C12.0788 10.5787 11.0614 11.0001 10.0005 11.0001Z" fill="#141414" />
</svg>
)
}
export default IconUser

View File

@ -0,0 +1,11 @@
import React from 'react'
const IconYoutube = () => {
return (
<svg width="24" height="16" viewBox="0 0 24 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23 5.70998C23.0495 4.27864 22.7365 2.858 22.09 1.57998C21.6514 1.05558 21.0427 0.701694 20.37 0.579984C17.5875 0.327509 14.7936 0.224028 12 0.269984C9.21667 0.221942 6.43274 0.322084 3.66003 0.569984C3.11185 0.669701 2.60454 0.926826 2.20003 1.30998C1.30003 2.13998 1.20003 3.55998 1.10003 4.75998C0.954939 6.91755 0.954939 9.08242 1.10003 11.24C1.12896 11.9154 1.22952 12.5858 1.40003 13.24C1.5206 13.745 1.76455 14.2123 2.11003 14.6C2.51729 15.0034 3.03641 15.2752 3.60003 15.38C5.75594 15.6461 7.92824 15.7564 10.1 15.71C13.6 15.76 16.67 15.71 20.3 15.43C20.8775 15.3316 21.4112 15.0595 21.83 14.65C22.11 14.3699 22.3191 14.0271 22.44 13.65C22.7977 12.5526 22.9733 11.4041 22.96 10.25C23 9.68998 23 6.30998 23 5.70998ZM9.74003 10.85V4.65998L15.66 7.76998C14 8.68998 11.81 9.72998 9.74003 10.85Z" fill="#141414" />
</svg>
)
}
export default IconYoutube

View File

@ -1,2 +1,10 @@
export { default as IconBuy } from './IconBuy'
export { default as ArrowUp } from './IconArrowUp'
export { default as IconSearch } from './IconSearch'
export { default as IconArrowRight } from './IconArrowRight'
export { default as IconUser } from './IconUser'
export { default as IconHistory } from './IconHistory'
export { default as IconInfo } from './IconInfo'
export { default as IconHome } from './IconHome'
export { default as IconShopping } from './IconShopping'
export { default as IconHeart } from './IconHeart'

View File

@ -1,5 +0,0 @@
/* style demo here */
.homeBanner {
color: green;
}

View File

@ -0,0 +1,42 @@
@import "../../../../styles/utilities";
.homeBanner {
@apply spacing-horizontal;
.left {
@apply hidden;
}
@screen xl {
@apply grid;
grid-template-columns: 1fr 1.8fr;
.left {
@apply flex items-end justify-center custom-border-radius-lg;
margin-right: 1.6rem;
background-image: url('./assets/home_banner.png');
background-repeat: no-repeat;
background-size: cover;
.text {
@apply relative font-heading text-center;
padding: 2.4rem 2.4rem 4.8rem;
width: min-content;
color: var(--white);
font-size: 8.8rem;
line-height: 8rem;
letter-spacing: -0.03em;
font-weight: bold;
text-transform: uppercase;
&::after {
@apply absolute;
content: "";
top: -2.4rem;
right: 0.8rem;
width: 5.7rem;
height: 4.7rem;
background-image: url("./assets/text-decorative.svg");
background-repeat: no-repeat;
}
}
}
}
}

View File

@ -1,14 +1,28 @@
import { FC } from 'react'
import s from './HomeBanner.module.css'
import React from 'react'
import { Banner } from 'src/components/common'
import s from './HomeBanner.module.scss'
import BannerImgRight from './assets/banner_full.png'
interface Props {
className?: string
children?: any
}
const HomeBanner: FC<Props> = ({ }) => {
const HomeBanner = ({ }: Props) => {
return (
<div className={s.homeBanner}>This is HomeBanner</div>
<div className={s.homeBanner}>
<section className={s.left}>
<div className={s.text}>
Freshness<br/>guaranteed
</div>
</section >
<Banner
title="Save 15% on your first order"
subtitle="Last call! Shop deep deals on 100+ bulk picks while you can."
imgLink={BannerImgRight.src}
size="small"
/>
</div >
)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@ -0,0 +1,3 @@
<svg width="58" height="47" viewBox="0 0 58 47" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.991538 29.9054C0.0557444 29.3451 0.620583 20.0215 0.90645 15.3028L0.93056 14.9044C1.10464 12.0221 1.28864 8.97576 1.58821 5.60623C1.85672 2.58606 4.06709 -0.174201 7.09366 0.00859758C9.21393 0.136658 10.9477 0.241374 12.378 1.21201C13.2727 1.81922 12.8541 6.60392 12.4398 11.3389L12.4398 11.339C12.2963 12.9785 12.1534 14.6121 12.0657 16.0642C11.9035 18.7492 11.712 22.151 11.5556 24.9805C11.3803 28.1532 8.87611 30.8509 5.70437 30.6593C5.5283 30.6487 5.35605 30.6386 5.18762 30.6288C3.28784 30.5176 1.87604 30.435 0.991538 29.9054ZM16.2741 30.4881C15.761 29.4441 21.6699 21.4235 24.6604 17.3643L24.9129 17.0215L24.913 17.0213C26.7392 14.5416 28.6693 11.9208 30.8902 9.07754C32.8808 6.52904 36.4595 5.33858 39.0634 7.2562C40.8876 8.59959 42.3792 9.69809 43.0973 11.396C43.5466 12.4582 40.3989 16.4996 37.2839 20.499C36.2054 21.8838 35.1307 23.2636 34.2106 24.513C32.5094 26.823 30.3665 29.7578 28.5868 32.2006C26.5912 34.9397 22.7857 35.9039 20.0569 33.8943C19.9054 33.7827 19.757 33.6739 19.6119 33.5674C17.9753 32.367 16.7592 31.4748 16.2741 30.4881ZM40.166 32.5648C36.3483 34.8144 28.8052 39.2593 28.8599 40.2802C28.9115 41.2451 29.5869 42.3858 30.4956 43.9207C30.5762 44.0568 30.6586 44.196 30.7425 44.3384C32.2551 46.9041 35.6638 47.4375 38.2217 45.9119C40.503 44.5512 43.2476 42.9182 45.4196 41.6378C46.5943 40.9453 47.939 40.2007 49.2885 39.4533C53.1861 37.2951 57.1245 35.1141 57.1278 34.1006C57.1331 32.4804 56.3063 31.0778 55.2952 29.3627C53.8519 26.9144 50.5485 26.6421 48.0602 28.0155C45.2842 29.5476 42.8199 31.0004 40.4883 32.3748L40.4883 32.3749C40.3841 32.4362 40.2766 32.4996 40.166 32.5648Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -32,7 +32,8 @@
--disabled: #cccccc;
--border-line: #ebebeb;
--background: #f8f8f8;
--background: #fff;
--gray: #f8f8f8;
--white: #fbfbfb;
--background-arrow:rgba(20, 20, 20, 0.05);
--font-size: 1.6rem;
@ -41,8 +42,7 @@
// --font-size: 16px;
// --line-height: 24px;
--font-sans: "Nunito", cursive, -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "Helvetica",
sans-serif;
--font-sans: "Nunito", -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "Helvetica", sans-serif;
--font-heading: "Righteous", -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "Helvetica", sans-serif;
--font-logo: "Poppins", -apple-system, system-ui, BlinkMacSystemFont, "Helvetica Neue", "Helvetica", sans-serif;
}

View File

@ -1,78 +1,86 @@
@layer utilities {
.heading-1 {
font-size: 4.8rem;
line-height: 5.6rem;
letter-spacing: -0.03em;
font-size: 24px;
line-height: 28px;
letter-spacing: -0.01em;
font-weight: bold;
text-transform: uppercase;
@screen md {
font-size: 6.4rem;
line-height: 8rem;
font-size: 64px;
line-height: 80px;
letter-spacing: -0.03em;
}
}
.heading-2 {
font-size: 4rem;
line-height: 4.8rem;
font-size: 32px;
line-height: 40px;
letter-spacing: -0.02em;
font-weight: bold;
text-transform: uppercase;
@screen md {
font-size: 4.8rem;
line-height: 5.6rem;
font-size: 48px;
line-height: 56px;
letter-spacing: -0.02em;
}
}
.heading-3 {
font-size: 2.4rem;
line-height: 3.2rem;
font-size: 24px;
line-height: 32px;
letter-spacing: -0.01em;
font-weight: bold;
text-transform: uppercase;
@screen md {
font-size: 3.2rem;
line-height: 4rem;
font-size: 32px;
line-height: 40px;
letter-spacing: -0.01em;
}
}
.sm-headline {
font-size: 1.8rem;
line-height: 2.8rem;
font-size: 18px;
line-height: 28px;
letter-spacing: -0.01em;
font-weight: bold;
@screen md {
font-size: 2rem;
line-height: 2.8rem;
font-size: 20px;
line-height: 28px;
letter-spacing: -0.01em;
}
}
.sub-headline {
font-size: 2rem;
line-height: 2.8rem;
font-size: 20px;
line-height: 28px;
letter-spacing: -0.01em;
@screen md {
font-size: 2.4rem;
line-height: 3.2rem;
font-size: 24px;
line-height: 32px;
letter-spacing: -0.01em;
}
}
.topline {
font-size: 1.8rem;
line-height: 2.8rem;
font-size: 18px;
line-height: 28px;
letter-spacing: 0.01em;
@screen md {
font-size: 2rem;
line-height: 2.8rem;
font-size: 20px;
line-height: 28px;
letter-spacing: 0.01em;
}
}
.caption {
font-size: 1.2rem;
line-height: 2rem;
font-size: 12px;
line-height: 20px;
letter-spacing: 0.01em;
}
.sm-label {
font-size: 1rem;
line-height: 1.6rem;
font-size: 10px;
line-height: 16px;
}
.spacing-horizontal {
padding-left: 2rem;
padding-right: 2rem;
@ -89,7 +97,11 @@
}
}
.custom-border-radius {
border-radius: 60% 10% 60% 2%/ 10% 40% 10% 50%;
border-radius: 60% 10% 60% 2%/ 10% 20% 10% 50%;
}
.custom-border-radius-lg {
border-radius: 60% 2% 2% 2%/ 6% 50% 50% 50%;
}
.font-heading {

View File

@ -1,3 +1,47 @@
export const SOCIAL_LINKS = {
FB: 'FB',
TWITTER: 'TWITTER',
YOUTUBE: 'YOUTUBE',
IG: 'IG',
}
export const ROUTE = {
HOME: '/',
PRODUCTS: '/products',
ABOUT: '/about',
ACCOUNT: '/account',
BUSSINESS: '/bussiness',
CONTACT: '/contact',
FAQ: '/faq',
CUSTOMER_SERVICE: '/customer-service',
TERM_CONDITION: '/term-condition',
PRIVACY_POLICY: '/privacy-policy',
BLOGS: '/blogs',
}
export const ACCOUNT_TAB = {
CUSTOMER_INFO: '',
ORDER: 'orders',
FAVOURITE: 'wishlist',
}
export const QUERY_KEY = {
TAB: 'tab',
CATEGORY: 'category',
BRAND: 'brand',
FEATURED: 'feature'
}
export enum ProductFeature {
BestSellers = 'Best Sellers',
Sales = 'Sales',
NewItem = 'New Item',
Viewed = 'Viewed',
}
export const KEY = {
ENTER: 'Enter',
}

View File

@ -1 +1,3 @@
// funtion utils here
export function isMobile() {
return window.innerWidth <= 768
}

View File

@ -3,4 +3,7 @@ export const LANGUAGE = {
BUY_NOW: 'Buy now',
SHOP_NOW: 'Shop now',
},
PLACE_HOLDER: {
SEARCH: 'Search',
}
}

View File

@ -44,14 +44,14 @@ module.exports = {
'negative': 'var(--negative)',
'negative-border-line': 'var(--negative-border-line)',
'negative-light': 'var(--negative-light)',
'line': 'var(--border-line)',
'background': 'var(--background)',
'white': 'var(--white)',
'background-arrow':'var(--background-arrow)',
'disabled': 'var(--text-disabled)',
line: 'var(--border-line)',
background: 'var(--background)',
white: 'var(--white)',
'background-arrow':'var(--background-arrow)',
gray: 'var(--gray)',
disabled: 'var(--text-disabled)',
// @deprecated (NOT use these variables)
'primary-2': 'var(--primary-2)',
@ -85,9 +85,9 @@ module.exports = {
active: 'var(--text-active)',
label: 'var(--text-label)',
placeholder: 'var(--text-placeholder)',
primary: 'var(--primary)',
// @deprecated (NOT use these variables)
primary: 'var(--text-primary)',
secondary: 'var(--text-secondary)',
},
boxShadow: {