mirror of
https://github.com/vercel/commerce.git
synced 2025-07-04 20:21:21 +00:00
✨ feat: show/hide full header when scroll in screen md
:%s
This commit is contained in:
parent
c65bf6aab7
commit
150e1537a2
File diff suppressed because one or more lines are too long
@ -1,11 +1,11 @@
|
|||||||
@import "../../../styles/utilities";
|
@import "../../../styles/utilities";
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
@apply sticky bg-white;
|
@apply sticky bg-white shadow-md;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
@screen md {
|
&.full {
|
||||||
padding-bottom: 1.6rem;
|
@apply shadow-none;
|
||||||
}
|
}
|
||||||
.menu {
|
.menu {
|
||||||
padding-left: 3.2rem;
|
padding-left: 3.2rem;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import React, { memo } 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 HeaderHighLight from './components/HeaderHighLight/HeaderHighLight'
|
||||||
import HeaderMenu from './components/HeaderMenu/HeaderMenu'
|
import HeaderMenu from './components/HeaderMenu/HeaderMenu'
|
||||||
import HeaderSubMenu from './components/HeaderSubMenu/HeaderSubMenu'
|
import HeaderSubMenu from './components/HeaderSubMenu/HeaderSubMenu'
|
||||||
@ -11,13 +13,31 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Header = memo(({ }: 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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<header className={s.header}>
|
<header className={classNames({ [s.header]: true, [s.full]: isFullHeader })}>
|
||||||
<HeaderHighLight />
|
<HeaderHighLight isShow={isFullHeader} />
|
||||||
<div className={s.menu}>
|
<div className={s.menu}>
|
||||||
<HeaderMenu />
|
<HeaderMenu isFull={isFullHeader} />
|
||||||
<HeaderSubMenu />
|
<HeaderSubMenu isShow={isFullHeader} />
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<HeaderSubMenuMobile />
|
<HeaderSubMenuMobile />
|
||||||
|
@ -3,13 +3,19 @@
|
|||||||
.headerHighLight {
|
.headerHighLight {
|
||||||
@apply hidden;
|
@apply hidden;
|
||||||
@screen md {
|
@screen md {
|
||||||
|
transform: translateY(-10rem);
|
||||||
|
height: 0;
|
||||||
|
&.show {
|
||||||
@apply flex justify-between items-center spacing-horizontal bg-primary caption;
|
@apply flex justify-between items-center spacing-horizontal bg-primary caption;
|
||||||
|
animation: showHeaderHightlight 0.2s;
|
||||||
|
height: unset;
|
||||||
|
transform: none;
|
||||||
padding-top: 0.8rem;
|
padding-top: 0.8rem;
|
||||||
padding-bottom: 0.8rem;
|
padding-bottom: 0.8rem;
|
||||||
color: var(--white);
|
color: var(--white);
|
||||||
.menu {
|
.menu {
|
||||||
@apply flex items-center list-none;
|
@apply flex items-center list-none;
|
||||||
padding: .8rem 0;
|
padding: 0.8rem 0;
|
||||||
li {
|
li {
|
||||||
&:not(:last-child) {
|
&:not(:last-child) {
|
||||||
margin-right: 3.2rem;
|
margin-right: 3.2rem;
|
||||||
@ -20,4 +26,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes showHeaderHightlight {
|
||||||
|
0% {
|
||||||
|
transform: translateY(-4rem);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
import classNames from 'classnames'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { memo } from 'react'
|
import { memo, useEffect, useRef } from 'react'
|
||||||
import { ROUTE } from 'src/utils/constanst.utils'
|
import { ROUTE } from 'src/utils/constanst.utils'
|
||||||
import s from './HeaderHighLight.module.scss'
|
import s from './HeaderHighLight.module.scss'
|
||||||
|
|
||||||
@ -19,12 +20,13 @@ const MENU = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children?: any
|
children?: any,
|
||||||
|
isShow: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderHighLight = memo(({ }: Props) => {
|
const HeaderHighLight = memo(({ isShow }: Props) => {
|
||||||
return (
|
return (
|
||||||
<section className={s.headerHighLight}>
|
<section className={classNames({ [s.headerHighLight]: true, [s.show]: isShow })}>
|
||||||
<div>
|
<div>
|
||||||
Free Shipping on order $49+ / Express $99+
|
Free Shipping on order $49+ / Express $99+
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,9 +5,13 @@
|
|||||||
padding-bottom: 0.8rem;
|
padding-bottom: 0.8rem;
|
||||||
@screen md {
|
@screen md {
|
||||||
@apply flex justify-between items-center;
|
@apply flex justify-between items-center;
|
||||||
|
adding-top: 0.8rem;
|
||||||
|
padding-bottom: 0.8rem;
|
||||||
|
&.full {
|
||||||
padding-top: 2.4rem;
|
padding-top: 2.4rem;
|
||||||
padding-bottom: 2.4rem;
|
padding-bottom: 2.4rem;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.left {
|
.left {
|
||||||
.top {
|
.top {
|
||||||
@apply flex justify-between items-center;
|
@apply flex justify-between items-center;
|
||||||
@ -15,8 +19,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.inputSearch {
|
.inputSearch {
|
||||||
//todo: remove
|
|
||||||
border: 1px solid red;
|
|
||||||
margin-top: 2.4rem;
|
margin-top: 2.4rem;
|
||||||
@screen lg {
|
@screen lg {
|
||||||
min-width: 51.2rem;
|
min-width: 51.2rem;
|
||||||
@ -50,8 +52,14 @@
|
|||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
@appy no-underline;
|
@appy no-underline;
|
||||||
|
&.iconFovourite {
|
||||||
|
svg path {
|
||||||
|
fill: var(--negative);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import classNames from 'classnames'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { memo } from 'react'
|
import { memo } from 'react'
|
||||||
import InputSearch from 'src/components/common/InputSearch/InputSearch'
|
import InputSearch from 'src/components/common/InputSearch/InputSearch'
|
||||||
@ -19,12 +20,13 @@ const OPTION_MENU = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children?: any
|
children?: any,
|
||||||
|
isFull: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderMenu = memo(({ }: Props) => {
|
const HeaderMenu = memo(({ isFull }: Props) => {
|
||||||
return (
|
return (
|
||||||
<section className={s.headerMenu}>
|
<section className={classNames({ [s.headerMenu]: true, [s.full]: isFull })}>
|
||||||
<div className={s.left}>
|
<div className={s.left}>
|
||||||
<div className={s.top}>
|
<div className={s.top}>
|
||||||
<div>Online Grocery</div>
|
<div>Online Grocery</div>
|
||||||
@ -46,7 +48,7 @@ const HeaderMenu = memo(({ }: Props) => {
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link href={`${ROUTE.ACCOUNT}?${QUERY_KEY.TAB}=${ACCOUNT_TAB.FAVOURITE}`}>
|
<Link href={`${ROUTE.ACCOUNT}?${QUERY_KEY.TAB}=${ACCOUNT_TAB.FAVOURITE}`}>
|
||||||
<a >
|
<a className={s.iconFovourite}>
|
||||||
<IconHeart />
|
<IconHeart />
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -3,8 +3,13 @@
|
|||||||
.headerSubMenu {
|
.headerSubMenu {
|
||||||
@apply hidden;
|
@apply hidden;
|
||||||
@screen md {
|
@screen md {
|
||||||
|
transform: translateY(-10rem);
|
||||||
|
height: 0;
|
||||||
|
&.show {
|
||||||
@apply block;
|
@apply block;
|
||||||
padding-bottom: 0.8rem;
|
padding-bottom: 2.4rem;
|
||||||
|
transform: none;
|
||||||
|
height: unset;
|
||||||
@screen lg {
|
@screen lg {
|
||||||
@apply flex justify-between items-center;
|
@apply flex justify-between items-center;
|
||||||
}
|
}
|
||||||
@ -33,4 +38,5 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,14 +54,15 @@ const CATEGORY = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
interface Props {
|
interface Props {
|
||||||
children?: any
|
children?: any,
|
||||||
|
isShow: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderSubMenu = memo(({ }: Props) => {
|
const HeaderSubMenu = memo(({ isShow }: Props) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={s.headerSubMenu}>
|
<section className={classNames({ [s.headerSubMenu]: true, [s.show]: isShow })}>
|
||||||
<ul className={s.menu}>
|
<ul className={s.menu}>
|
||||||
{/* todo: handle active item */}
|
{/* todo: handle active item */}
|
||||||
<li>
|
<li>
|
||||||
|
@ -1,21 +1,11 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
const IconHeart = ({ ...props }) => {
|
const IconHeart = () => {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="24"
|
<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" />
|
||||||
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>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default IconHeart
|
export default IconHeart
|
@ -1 +1,3 @@
|
|||||||
// funtion utils here
|
export function isMobile() {
|
||||||
|
return window.innerWidth <= 768
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user