4
0
forked from crowetic/commerce

sticky nav, better dropdown exit

This commit is contained in:
Julián Benegas 2020-10-21 18:32:32 -03:00
parent 316801627b
commit c22789176d
4 changed files with 67 additions and 11 deletions

View File

@ -1,4 +1,4 @@
import { FC, useState } from 'react'
import { FC, useEffect, useState } from 'react'
import cn from 'classnames'
import type { Page } from '@lib/bigcommerce/api/operations/get-all-pages'
import { CommerceProvider } from '@lib/bigcommerce'
@ -18,13 +18,37 @@ interface Props {
const Layout: FC<Props> = ({ children, pageProps }) => {
const { displaySidebar, closeSidebar } = useUI()
const [acceptedCookies, setAcceptedCookies] = useState(false)
const [hasScrolled, setHasScrolled] = useState(false)
useEffect(() => {
const offset = 0
function handleScroll() {
const { scrollTop } = document.documentElement
if (scrollTop > offset) setHasScrolled(true)
else setHasScrolled(false)
}
document.addEventListener('scroll', handleScroll)
return () => {
document.removeEventListener('scroll', handleScroll)
}
}, [])
return (
<CommerceProvider locale="en-us">
<div className={cn(s.root)}>
<Container>
<Navbar />
</Container>
<header
className={cn(
'sticky top-0 bg-primary z-40 transition-shadow duration-200',
{
'shadow-magical': hasScrolled,
}
)}
>
<Container>
<Navbar />
</Container>
</header>
<main className="fit">{children}</main>
<Footer pages={pageProps.pages} />
<Sidebar show={displaySidebar} close={closeSidebar}>

View File

@ -1,4 +1,4 @@
import { FC, useState } from 'react'
import { FC, useEffect, useState } from 'react'
import cn from 'classnames'
import useCart from '@lib/bigcommerce/cart/use-cart'
import { Avatar } from '@components/core'
@ -21,6 +21,30 @@ const UserNav: FC<Props> = ({ className }) => {
const { openSidebar, closeSidebar, displaySidebar } = useUI()
const itemsCount = Object.values(data?.line_items ?? {}).reduce(countItems, 0)
useEffect(() => {
function handleClick(e: any) {
const isInside = e?.target?.closest(`#user-dropdown`) !== null
if (isInside) return
setDisplayDropdown(false)
document.removeEventListener('click', handleClick)
}
function handleKeyPress(e: KeyboardEvent) {
if (e.key === 'Escape') {
setDisplayDropdown(false)
document.removeEventListener('keydown', handleKeyPress)
}
}
if (displayDropdown) {
document.addEventListener('click', handleClick)
document.addEventListener('keydown', handleKeyPress)
return () => {
document.removeEventListener('click', handleClick)
document.removeEventListener('keydown', handleKeyPress)
}
}
}, [displayDropdown])
return (
<nav className={cn(s.root, className)}>
<ul className={s.list}>
@ -40,18 +64,21 @@ const UserNav: FC<Props> = ({ className }) => {
<Heart />
</li>
</Link>
<li
className={s.item}
<button
className={cn(
s.item,
'rounded-full focus:shadow-outline-blue focus:outline-none'
)}
onClick={() => {
setDisplayDropdown((i) => !i)
}}
>
<Avatar />
</li>
</button>
</ul>
{displayDropdown && (
<div className={s.dropdownMenu}>
<div className={cn(s.dropdownMenu, 'shadow-lg')} id="user-dropdown">
<nav className={s.dropdownMenuContainer}>
<Link href="#">
<a className={s.link}>My Purchases</a>
@ -59,8 +86,9 @@ const UserNav: FC<Props> = ({ className }) => {
<Link href="#">
<a className={s.link}>My Account</a>
</Link>
<div className="my-1 h-px w-full bg-accents-2" />
<Link href="#">
<a className={cn(s.link, 'mt-4')}>Logout</a>
<a className={cn(s.link)}>Logout</a>
</Link>
</nav>
</div>

View File

@ -34,7 +34,7 @@
}
.nameBox {
@apply absolute top-6 left-0 z-50;
@apply absolute top-6 left-0 z-30;
& .name {
@apply px-6 py-2 bg-primary text-primary font-bold;

View File

@ -37,6 +37,10 @@ module.exports = {
primary: 'var(--text-primary)',
secondary: 'var(--text-secondary)',
},
boxShadow: {
magical:
'rgba(0, 0, 0, 0.02) 0px 30px 30px, rgba(0, 0, 0, 0.03) 0px 0px 8px, rgba(0, 0, 0, 0.05) 0px 1px 0px',
},
},
},
variants: {},