diff --git a/.gitignore b/.gitignore index 22f1bf4f3..61386b73c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ node_modules /.pnp .pnp.js +package-lock.json # testing /coverage diff --git a/pages/index.tsx b/pages/index.tsx index 6eb35bc03..a61c40d14 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -122,4 +122,4 @@ export default function Home() { ) } -// Home.Layout = Layout +Home.Layout = Layout diff --git a/src/assets/imgs/apple_pay.png b/src/assets/imgs/apple_pay.png new file mode 100644 index 000000000..c2c915d66 Binary files /dev/null and b/src/assets/imgs/apple_pay.png differ diff --git a/src/assets/imgs/gpay.png b/src/assets/imgs/gpay.png new file mode 100644 index 000000000..55e5dfbae Binary files /dev/null and b/src/assets/imgs/gpay.png differ diff --git a/src/assets/imgs/mastercard.png b/src/assets/imgs/mastercard.png new file mode 100644 index 000000000..fad380822 Binary files /dev/null and b/src/assets/imgs/mastercard.png differ diff --git a/src/assets/imgs/visa.png b/src/assets/imgs/visa.png new file mode 100644 index 000000000..1ba0cec4b Binary files /dev/null and b/src/assets/imgs/visa.png differ diff --git a/src/components/common/Banner/Banner.module.scss b/src/components/common/Banner/Banner.module.scss new file mode 100644 index 000000000..4cec48628 --- /dev/null +++ b/src/components/common/Banner/Banner.module.scss @@ -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; + } + } + } +} diff --git a/src/components/common/Banner/Banner.tsx b/src/components/common/Banner/Banner.tsx new file mode 100644 index 000000000..a953052b6 --- /dev/null +++ b/src/components/common/Banner/Banner.tsx @@ -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 ( +
+
+
+
+

+ {title} +

+
+ {subtitle} +
+
+
+ + + } isIconSuffix={true}>{buttonLabel} + + +
+
+
+
+ ) +}) + +export default Banner diff --git a/src/components/common/CollectionHeading/CollectionHeading.module.scss b/src/components/common/CollectionHeading/CollectionHeading.module.scss index 208a78728..870eda782 100644 --- a/src/components/common/CollectionHeading/CollectionHeading.module.scss +++ b/src/components/common/CollectionHeading/CollectionHeading.module.scss @@ -1,6 +1,5 @@ -@import '../../../styles/utilities'; - .subtitle { font-size: var(--font-size); line-height: var(--line-height); + margin-top: .4rem; } \ No newline at end of file diff --git a/src/components/common/CollectionHeading/CollectionHeading.tsx b/src/components/common/CollectionHeading/CollectionHeading.tsx index e52352618..3655d6561 100644 --- a/src/components/common/CollectionHeading/CollectionHeading.tsx +++ b/src/components/common/CollectionHeading/CollectionHeading.tsx @@ -1,19 +1,18 @@ import React from 'react' -// import classNames from 'classnames' import s from './CollectionHeading.module.scss' import HeadingCommon from '../HeadingCommon/HeadingCommon' interface CollectionHeadingProps { - headingType?: 'default' | 'highlight' | 'light' - headingText: string; - subtitle: string + type?: 'default' | 'highlight' | 'light'; + title: string; + subtitle: string; } -const CollectionHeading = ({ headingType='default', headingText, subtitle }: CollectionHeadingProps) => { +const CollectionHeading = ({ type = 'default', title, subtitle }: CollectionHeadingProps) => { return ( -
- +
+ {title}
{subtitle}
) diff --git a/src/components/common/Footer/Footer.module.scss b/src/components/common/Footer/Footer.module.scss new file mode 100644 index 000000000..bfe9ceead --- /dev/null +++ b/src/components/common/Footer/Footer.module.scss @@ -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; + } +} diff --git a/src/components/common/Footer/Footer.tsx b/src/components/common/Footer/Footer.tsx new file mode 100644 index 000000000..a830c60ea --- /dev/null +++ b/src/components/common/Footer/Footer.tsx @@ -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_COLUMNS.map(item => )} +
+ +
+
+ © 2021 Online Grocery +
+
+ ) +} + +export default Footer diff --git a/src/components/common/Footer/components/FooterColumn/FooterColumn.module.scss b/src/components/common/Footer/components/FooterColumn/FooterColumn.module.scss new file mode 100644 index 000000000..754ebce69 --- /dev/null +++ b/src/components/common/Footer/components/FooterColumn/FooterColumn.module.scss @@ -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); + } + } + } + } +} diff --git a/src/components/common/Footer/components/FooterColumn/FooterColumn.tsx b/src/components/common/Footer/components/FooterColumn/FooterColumn.tsx new file mode 100644 index 000000000..4adda1985 --- /dev/null +++ b/src/components/common/Footer/components/FooterColumn/FooterColumn.tsx @@ -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 ( +
+

+ {title} +

+ +
+ ); +}; + +export default FooterColumn; \ No newline at end of file diff --git a/src/components/common/Footer/components/FooterSocial/FooterSocial.module.scss b/src/components/common/Footer/components/FooterSocial/FooterSocial.module.scss new file mode 100644 index 000000000..cfc2060c5 --- /dev/null +++ b/src/components/common/Footer/components/FooterSocial/FooterSocial.module.scss @@ -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; + } + } + } +} diff --git a/src/components/common/Footer/components/FooterSocial/FooterSocial.tsx b/src/components/common/Footer/components/FooterSocial/FooterSocial.tsx new file mode 100644 index 000000000..94fb097a8 --- /dev/null +++ b/src/components/common/Footer/components/FooterSocial/FooterSocial.tsx @@ -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: , + link: SOCIAL_LINKS.FB, + }, + { + icon: , + link: SOCIAL_LINKS.TWITTER, + }, + { + icon: , + link: SOCIAL_LINKS.YOUTUBE, + }, + { + icon: , + 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 ( +
+
Social
+ +
    + { + PAYMENT_METHODS.map(item =>
  • + {item.name} +
  • ) + } +
+
+ ); +}; + +export default FooterSocial; \ No newline at end of file diff --git a/src/components/common/Header/Header.module.scss b/src/components/common/Header/Header.module.scss index 0207f107f..ce960228b 100644 --- a/src/components/common/Header/Header.module.scss +++ b/src/components/common/Header/Header.module.scss @@ -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; } } diff --git a/src/components/common/Header/Header.tsx b/src/components/common/Header/Header.tsx index 0c4bfa92e..dfce58b57 100644 --- a/src/components/common/Header/Header.tsx +++ b/src/components/common/Header/Header.tsx @@ -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) => { +const Header = memo(({ }: Props) => { + const [isFullHeader, setIsFullHeader] = useState(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 ( -
- This is Header -

This is heading

-
This is logo text
-
+ <> +
+ +
+ + +
+
+ + ) -} +}) export default Header diff --git a/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.module.scss b/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.module.scss new file mode 100644 index 000000000..9717fd29d --- /dev/null +++ b/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.module.scss @@ -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; + } +} diff --git a/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.tsx b/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.tsx new file mode 100644 index 000000000..a1759eede --- /dev/null +++ b/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.tsx @@ -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 ( +
+
+ Free Shipping on order $49+ / Express $99+ +
+ +
+ ) +}) + +export default HeaderHighLight diff --git a/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss b/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss new file mode 100644 index 000000000..a61c059e6 --- /dev/null +++ b/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss @@ -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); + } + } + } + + } + } + } +} diff --git a/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx b/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx new file mode 100644 index 000000000..8f19b11e8 --- /dev/null +++ b/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx @@ -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 ( +
+
+
+
Online Grocery
+ +
+
+ +
+
+ +
+ ) +}) + +export default HeaderMenu diff --git a/src/components/common/Header/components/HeaderSubMenu/HeaderNoti/HeaderNoti.module.scss b/src/components/common/Header/components/HeaderSubMenu/HeaderNoti/HeaderNoti.module.scss new file mode 100644 index 000000000..7e678a7ed --- /dev/null +++ b/src/components/common/Header/components/HeaderSubMenu/HeaderNoti/HeaderNoti.module.scss @@ -0,0 +1,3 @@ +.headerNoti { + @apply flex items-center; +} diff --git a/src/components/common/Header/components/HeaderSubMenu/HeaderNoti/HeaderNoti.tsx b/src/components/common/Header/components/HeaderSubMenu/HeaderNoti/HeaderNoti.tsx new file mode 100644 index 000000000..4e5b922c1 --- /dev/null +++ b/src/components/common/Header/components/HeaderSubMenu/HeaderNoti/HeaderNoti.tsx @@ -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 ( + +
+  You can buy fresh products after 11pm or 8am +
+
+ ); +}; + +export default HeaderNoti; \ No newline at end of file diff --git a/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.module.scss b/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.module.scss new file mode 100644 index 000000000..8a1d76c4d --- /dev/null +++ b/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.module.scss @@ -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; + } + } + } + } + } +} diff --git a/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.tsx b/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.tsx new file mode 100644 index 000000000..6a02259b5 --- /dev/null +++ b/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.tsx @@ -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 ( +
+
    + {/* todo: handle active item */} +
  • + Categories +
  • + { + MENU.map(item =>
  • + + + {item.name} + + + +
  • ) + } +
+ +
+ ) +}) + +export default HeaderSubMenu diff --git a/src/components/common/Header/components/HeaderSubMenuMobile/HeaderSubMenuMobile.module.scss b/src/components/common/Header/components/HeaderSubMenuMobile/HeaderSubMenuMobile.module.scss new file mode 100644 index 000000000..5480b5d10 --- /dev/null +++ b/src/components/common/Header/components/HeaderSubMenuMobile/HeaderSubMenuMobile.module.scss @@ -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; + } +} diff --git a/src/components/common/Header/components/HeaderSubMenuMobile/HeaderSubMenuMobile.tsx b/src/components/common/Header/components/HeaderSubMenuMobile/HeaderSubMenuMobile.tsx new file mode 100644 index 000000000..d2cf1bf3e --- /dev/null +++ b/src/components/common/Header/components/HeaderSubMenuMobile/HeaderSubMenuMobile.tsx @@ -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: , + isMarked: true, + }, + { + link: ROUTE.PRODUCTS, + name: 'Shopping', + icon: , + isMarked: false, + }, + { + link: `${ROUTE.ACCOUNT}?${QUERY_KEY.TAB}=${ACCOUNT_TAB.FAVOURITE}`, + name: 'Favourites', + icon: , + isMarked: false, + }, + { + link: ROUTE.ACCOUNT, + name: 'Account', + icon: , + isMarked: false, + }, +] + +interface Props { + children?: any +} + +const HeaderSubMenuMobile = memo(({ }: Props) => { + const router = useRouter() + return ( +
+ +
+ ) +}) + +export default HeaderSubMenuMobile diff --git a/src/components/common/HeadingCommon/HeadingCommon.module.scss b/src/components/common/HeadingCommon/HeadingCommon.module.scss index 8e9b62602..4626706a1 100644 --- a/src/components/common/HeadingCommon/HeadingCommon.module.scss +++ b/src/components/common/HeadingCommon/HeadingCommon.module.scss @@ -1,13 +1,13 @@ @import '../../../styles/utilities'; .headingCommon { - @apply heading-1 font-heading uppercase text-left; + @apply heading-1 font-heading text-left; &.highlight { color: var(--negative); } &.light { - color: var(--disabled); + color: var(--white); } &.center { @apply text-center; diff --git a/src/components/common/HeadingCommon/HeadingCommon.tsx b/src/components/common/HeadingCommon/HeadingCommon.tsx index 45c89a3bd..a3c1165bf 100644 --- a/src/components/common/HeadingCommon/HeadingCommon.tsx +++ b/src/components/common/HeadingCommon/HeadingCommon.tsx @@ -3,19 +3,19 @@ import classNames from 'classnames' import s from './HeadingCommon.module.scss' interface HeadingCommonProps { - headingType?: 'highlight' | 'light' | 'default'; - textAlign?: 'center' | 'left'; - headingText?: string; + type?: 'highlight' | 'light' | 'default'; + align?: 'center' | 'left'; + children: string; } -const HeadingCommon = ({ headingType='default', textAlign='left', headingText='categories' }: HeadingCommonProps) => { +const HeadingCommon = ({ type='default', align='left', children }: HeadingCommonProps) => { return ( -
{headingText}
+ >{children} ) } diff --git a/src/components/common/InputCommon/InputCommon.module.scss b/src/components/common/InputCommon/InputCommon.module.scss index 13e27fd5f..27eaed174 100644 --- a/src/components/common/InputCommon/InputCommon.module.scss +++ b/src/components/common/InputCommon/InputCommon.module.scss @@ -16,7 +16,7 @@ } .inputCommon { @apply block w-full transition-all duration-200 rounded; - padding: 1.6rem; + padding: 1.2rem 1.6rem; border: 1px solid var(--border-line); &:hover, &:focus, @@ -31,7 +31,8 @@ } &.custom { - @apply custom-border-radius border-none; + @apply custom-border-radius; + border: 1px solid transparent; background: var(--gray); &:hover, &:focus, diff --git a/src/components/common/Layout/Layout.module.scss b/src/components/common/Layout/Layout.module.scss new file mode 100644 index 000000000..e495667eb --- /dev/null +++ b/src/components/common/Layout/Layout.module.scss @@ -0,0 +1,8 @@ +.mainLayout { + display: flex; + flex-direction: column; + min-height: 100vh; + > main { + flex: 1; + } +} diff --git a/src/components/common/Layout/Layout.tsx b/src/components/common/Layout/Layout.tsx index 356ecfce5..aa5da11e1 100644 --- a/src/components/common/Layout/Layout.tsx +++ b/src/components/common/Layout/Layout.tsx @@ -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 = ({ children }) => { return ( -
-
{children}
+
+
+
{children}
+
+
) diff --git a/src/components/common/MenuDropdown/MenuDropdown.module.scss b/src/components/common/MenuDropdown/MenuDropdown.module.scss new file mode 100644 index 000000000..f8a8a20cc --- /dev/null +++ b/src/components/common/MenuDropdown/MenuDropdown.module.scss @@ -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; + } +} diff --git a/src/components/common/MenuDropdown/MenuDropdown.tsx b/src/components/common/MenuDropdown/MenuDropdown.tsx new file mode 100644 index 000000000..c20ffcaed --- /dev/null +++ b/src/components/common/MenuDropdown/MenuDropdown.tsx @@ -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 ( +
+ + {children} + +
+ +
+
+ ); +}; + +export default MenuDropdown; \ No newline at end of file diff --git a/src/components/common/NotiMessage/NotiMessage.module.scss b/src/components/common/NotiMessage/NotiMessage.module.scss new file mode 100644 index 000000000..a8015ea8e --- /dev/null +++ b/src/components/common/NotiMessage/NotiMessage.module.scss @@ -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; +} diff --git a/src/components/common/NotiMessage/NotiMessage.tsx b/src/components/common/NotiMessage/NotiMessage.tsx new file mode 100644 index 000000000..20eabdfae --- /dev/null +++ b/src/components/common/NotiMessage/NotiMessage.tsx @@ -0,0 +1,16 @@ +import React from 'react' +import s from './NotiMessage.module.scss' + +interface Props { + children?: React.ReactNode +} + +const NotiMessage = ({ children }: Props) => { + return ( +
+ {children} +
+ ) +} + +export default NotiMessage \ No newline at end of file diff --git a/src/components/common/ScrollToTop/ScrollTarget.tsx b/src/components/common/ScrollToTop/ScrollTarget.tsx new file mode 100644 index 000000000..50a839c83 --- /dev/null +++ b/src/components/common/ScrollToTop/ScrollTarget.tsx @@ -0,0 +1,15 @@ +import React, { MutableRefObject } from 'react' + +interface ScrollTargetProps { + refScrollUp: MutableRefObject; +} + +const ScrollTarget = ({ refScrollUp } : ScrollTargetProps) => { + + return ( +
+ ) + +} + +export default ScrollTarget diff --git a/src/components/common/ScrollToTop/ScrollToTop.module.scss b/src/components/common/ScrollToTop/ScrollToTop.module.scss new file mode 100644 index 000000000..c010f08ad --- /dev/null +++ b/src/components/common/ScrollToTop/ScrollToTop.module.scss @@ -0,0 +1,24 @@ +@import '../../../styles/utilities'; + +.scrollToTop { + @apply hidden; + + @screen md { + &.show { + @apply block rounded-lg fixed cursor-pointer; + right: 11.2rem; + bottom: 21.6rem; + width: 6.4rem; + height: 6.4rem; + background-color: var(--border-line); + } + + &.hide { + @apply hidden; + } + } + + .scrollToTopBtn { + @apply outline-none w-full h-full; + } +} \ No newline at end of file diff --git a/src/components/common/ScrollToTop/ScrollToTop.tsx b/src/components/common/ScrollToTop/ScrollToTop.tsx new file mode 100644 index 000000000..98e16168d --- /dev/null +++ b/src/components/common/ScrollToTop/ScrollToTop.tsx @@ -0,0 +1,54 @@ +import React, { useState, useEffect, MutableRefObject } from 'react' +import classNames from 'classnames' +import s from './ScrollToTop.module.scss' + +import ArrowUp from '../../icons/IconArrowUp' + +interface ScrollToTopProps { + target: MutableRefObject; + visibilityHeight?: number; +} + +const ScrollToTop = ({ target, visibilityHeight=450 }: ScrollToTopProps) => { + + const [scrollPosition, setSrollPosition] = useState(0); + const [showScrollToTop, setShowScrollToTop] = useState("hide"); + + function handleVisibleButton() { + const position = window.pageYOffset; + setSrollPosition(position); + + if (scrollPosition > visibilityHeight) { + return setShowScrollToTop("show") + } else if (scrollPosition < visibilityHeight) { + return setShowScrollToTop("hide"); + } + }; + + function handleScrollUp() { + target.current.scrollIntoView({ behavior: "smooth" }); + } + + function addEventScroll() { + window.addEventListener("scroll", handleVisibleButton); + } + + useEffect(() => { + addEventScroll() + }); + + return ( +
+ +
+ ) + +} + +export default ScrollToTop diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 3e0ccbf43..f672564e2 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -12,7 +12,13 @@ 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 InputSearch} from './InputSearch/InputSearch' -export { default as ButtonIconBuy} from './ButtonIconBuy/ButtonIconBuy' 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 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' diff --git a/src/components/icons/IconArrowRight.tsx b/src/components/icons/IconArrowRight.tsx new file mode 100644 index 000000000..f6d2fd609 --- /dev/null +++ b/src/components/icons/IconArrowRight.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconArrowRight = () => { + return ( + + + + ) +} + +export default IconArrowRight diff --git a/src/components/icons/IconArrowUp.tsx b/src/components/icons/IconArrowUp.tsx new file mode 100644 index 000000000..3eac6391b --- /dev/null +++ b/src/components/icons/IconArrowUp.tsx @@ -0,0 +1,10 @@ +const ArrowUp = () => { + + return ( + + + + ) + } + + export default ArrowUp \ No newline at end of file diff --git a/src/components/icons/IconFacebook.tsx b/src/components/icons/IconFacebook.tsx new file mode 100644 index 000000000..f3d6e72ea --- /dev/null +++ b/src/components/icons/IconFacebook.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconFacebook = () => { + return ( + + + + ) +} + +export default IconFacebook diff --git a/src/components/icons/IconHeart.tsx b/src/components/icons/IconHeart.tsx index 0d868c5e7..593e9278e 100644 --- a/src/components/icons/IconHeart.tsx +++ b/src/components/icons/IconHeart.tsx @@ -1,23 +1,11 @@ +import React from 'react' -const IconHeart = ({ ...props }) => { - return ( - - - - ) - } - - export default IconHeart \ No newline at end of file +const IconHeart = () => { + return ( + + + + ) +} + +export default IconHeart diff --git a/src/components/icons/IconHistory.tsx b/src/components/icons/IconHistory.tsx new file mode 100644 index 000000000..c36afe78d --- /dev/null +++ b/src/components/icons/IconHistory.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconHistory = () => { + return ( + + + + ) +} + +export default IconHistory diff --git a/src/components/icons/IconHome.tsx b/src/components/icons/IconHome.tsx new file mode 100644 index 000000000..a79260b35 --- /dev/null +++ b/src/components/icons/IconHome.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconHome = () => { + return ( + + + + ) +} + +export default IconHome diff --git a/src/components/icons/IconInfo.tsx b/src/components/icons/IconInfo.tsx new file mode 100644 index 000000000..027ee236b --- /dev/null +++ b/src/components/icons/IconInfo.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconInfo = () => { + return ( + + + + ) +} + +export default IconInfo diff --git a/src/components/icons/IconInstagram.tsx b/src/components/icons/IconInstagram.tsx new file mode 100644 index 000000000..77b028806 --- /dev/null +++ b/src/components/icons/IconInstagram.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconInstagram = () => { + return ( + + + + ) +} + +export default IconInstagram diff --git a/src/components/icons/IconShopping.tsx b/src/components/icons/IconShopping.tsx new file mode 100644 index 000000000..b0d8c279c --- /dev/null +++ b/src/components/icons/IconShopping.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconShopping = () => { + return ( + + + + ) +} + +export default IconShopping diff --git a/src/components/icons/IconTwitter.tsx b/src/components/icons/IconTwitter.tsx new file mode 100644 index 000000000..3d5220607 --- /dev/null +++ b/src/components/icons/IconTwitter.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconTwitter = () => { + return ( + + + + ) +} + +export default IconTwitter diff --git a/src/components/icons/IconUser.tsx b/src/components/icons/IconUser.tsx new file mode 100644 index 000000000..ea25fa34b --- /dev/null +++ b/src/components/icons/IconUser.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconUser = () => { + return ( + + + + ) +} + +export default IconUser diff --git a/src/components/icons/IconYoutube.tsx b/src/components/icons/IconYoutube.tsx new file mode 100644 index 000000000..105bc3332 --- /dev/null +++ b/src/components/icons/IconYoutube.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconYoutube = () => { + return ( + + + + ) +} + +export default IconYoutube diff --git a/src/components/icons/index.ts b/src/components/icons/index.ts index c82e4fa76..eeaffb85b 100644 --- a/src/components/icons/index.ts +++ b/src/components/icons/index.ts @@ -1,3 +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' diff --git a/src/components/modules/home/HomeBanner/HomeBanner.module.css b/src/components/modules/home/HomeBanner/HomeBanner.module.css deleted file mode 100644 index 3e25230ff..000000000 --- a/src/components/modules/home/HomeBanner/HomeBanner.module.css +++ /dev/null @@ -1,5 +0,0 @@ -/* style demo here */ - -.homeBanner { - color: green; -} \ No newline at end of file diff --git a/src/components/modules/home/HomeBanner/HomeBanner.module.scss b/src/components/modules/home/HomeBanner/HomeBanner.module.scss new file mode 100644 index 000000000..49b3b944b --- /dev/null +++ b/src/components/modules/home/HomeBanner/HomeBanner.module.scss @@ -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; + } + } + } + } +} diff --git a/src/components/modules/home/HomeBanner/HomeBanner.tsx b/src/components/modules/home/HomeBanner/HomeBanner.tsx index 7a254ec10..8bbf75138 100644 --- a/src/components/modules/home/HomeBanner/HomeBanner.tsx +++ b/src/components/modules/home/HomeBanner/HomeBanner.tsx @@ -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 = ({ }) => { +const HomeBanner = ({ }: Props) => { return ( -
This is HomeBanner
+
+
+
+ Freshness
guaranteed +
+
+ +
) } diff --git a/src/components/modules/home/HomeBanner/assets/banner.png b/src/components/modules/home/HomeBanner/assets/banner.png new file mode 100644 index 000000000..fc65bdd68 Binary files /dev/null and b/src/components/modules/home/HomeBanner/assets/banner.png differ diff --git a/src/components/modules/home/HomeBanner/assets/banner_full.png b/src/components/modules/home/HomeBanner/assets/banner_full.png new file mode 100644 index 000000000..082f8aacd Binary files /dev/null and b/src/components/modules/home/HomeBanner/assets/banner_full.png differ diff --git a/src/components/modules/home/HomeBanner/assets/home_banner.png b/src/components/modules/home/HomeBanner/assets/home_banner.png new file mode 100644 index 000000000..8fb683a8b Binary files /dev/null and b/src/components/modules/home/HomeBanner/assets/home_banner.png differ diff --git a/src/components/modules/home/HomeBanner/assets/text-decorative.svg b/src/components/modules/home/HomeBanner/assets/text-decorative.svg new file mode 100644 index 000000000..f29ef0517 --- /dev/null +++ b/src/components/modules/home/HomeBanner/assets/text-decorative.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/styles/_base.scss b/src/styles/_base.scss index 123e581a9..aebbef0c2 100644 --- a/src/styles/_base.scss +++ b/src/styles/_base.scss @@ -42,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; } diff --git a/src/styles/_utilities.scss b/src/styles/_utilities.scss index 251aaf214..e75d344fe 100644 --- a/src/styles/_utilities.scss +++ b/src/styles/_utilities.scss @@ -1,85 +1,86 @@ @layer utilities { .heading-1 { - font-size: 4.8rem; - line-height: 5.6rem; - letter-spacing: -0.03em; - font-weight: bold; - text-transform: uppercase; - @screen md { - font-size: 6.4rem; - line-height: 8rem; - letter-spacing: -0.03em; - } - } - .heading-2 { - font-size: 4rem; - line-height: 4.8rem; - letter-spacing: -0.02em; - font-weight: bold; - text-transform: uppercase; - @screen md { - font-size: 4.8rem; - line-height: 5.6rem; - letter-spacing: -0.02em; - } - } - .heading-3 { - font-size: 2.4rem; - line-height: 3.2rem; + font-size: 24px; + line-height: 28px; letter-spacing: -0.01em; font-weight: bold; text-transform: uppercase; @screen md { - font-size: 3.2rem; - line-height: 4rem; + font-size: 64px; + line-height: 80px; + letter-spacing: -0.03em; + } + } + .heading-2 { + font-size: 32px; + line-height: 40px; + letter-spacing: -0.02em; + font-weight: bold; + text-transform: uppercase; + @screen md { + font-size: 48px; + line-height: 56px; + letter-spacing: -0.02em; + } + } + .heading-3 { + font-size: 24px; + line-height: 32px; + letter-spacing: -0.01em; + font-weight: bold; + text-transform: uppercase; + @screen md { + 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; @@ -99,6 +100,10 @@ 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 { font-family: var(--font-heading); } diff --git a/src/utils/constanst.utils.ts b/src/utils/constanst.utils.ts index 94f253622..0d66ecda0 100644 --- a/src/utils/constanst.utils.ts +++ b/src/utils/constanst.utils.ts @@ -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', } + diff --git a/src/utils/funtion.utils.ts b/src/utils/funtion.utils.ts index 410d3fdcc..b1e7b5536 100644 --- a/src/utils/funtion.utils.ts +++ b/src/utils/funtion.utils.ts @@ -1 +1,3 @@ -// funtion utils here \ No newline at end of file +export function isMobile() { + return window.innerWidth <= 768 +} \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js index 2882c260c..4867fef18 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -51,10 +51,12 @@ module.exports = { '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)', @@ -90,9 +92,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: { diff --git a/yarn.lock b/yarn.lock index 37aeb20a2..8b4ce8da1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2888,11 +2888,6 @@ "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" "version" "1.0.0" -"fsevents@~2.3.1", "fsevents@~2.3.2": - "integrity" "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==" - "resolved" "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" - "version" "2.3.2" - "function-bind@^1.1.1": "integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" "resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"