forked from crowetic/commerce
Feature/hamburger menu (#540)
* Setup Mobile Menu Sidebar * Setup Basic Mobile Menu Items Styling * Implement full width styling for mobile devices * Cleanup Co-authored-by: Nine <at059214@Abdurahmans-MacBook-Pro.local>
This commit is contained in:
parent
a01568bc3a
commit
82cb719ad6
@ -13,6 +13,7 @@ import { useAcceptCookies } from '@lib/hooks/useAcceptCookies'
|
|||||||
import { Sidebar, Button, LoadingDots } from '@components/ui'
|
import { Sidebar, Button, LoadingDots } from '@components/ui'
|
||||||
import PaymentMethodView from '@components/checkout/PaymentMethodView'
|
import PaymentMethodView from '@components/checkout/PaymentMethodView'
|
||||||
import CheckoutSidebarView from '@components/checkout/CheckoutSidebarView'
|
import CheckoutSidebarView from '@components/checkout/CheckoutSidebarView'
|
||||||
|
import MenuSidebarView, { Link } from '../UserNav/MenuSidebarView'
|
||||||
|
|
||||||
import LoginView from '@components/auth/LoginView'
|
import LoginView from '@components/auth/LoginView'
|
||||||
import s from './Layout.module.css'
|
import s from './Layout.module.css'
|
||||||
@ -74,12 +75,14 @@ const ModalUI: FC = () => {
|
|||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
const SidebarView: FC<{ sidebarView: string; closeSidebar(): any }> = ({
|
const SidebarView: FC<{
|
||||||
sidebarView,
|
sidebarView: string
|
||||||
closeSidebar,
|
closeSidebar(): any
|
||||||
}) => {
|
links: Link[]
|
||||||
|
}> = ({ sidebarView, closeSidebar, links }) => {
|
||||||
return (
|
return (
|
||||||
<Sidebar onClose={closeSidebar}>
|
<Sidebar onClose={closeSidebar}>
|
||||||
|
{sidebarView === 'MOBILEMENU_VIEW' && <MenuSidebarView links={links} />}
|
||||||
{sidebarView === 'CART_VIEW' && <CartSidebarView />}
|
{sidebarView === 'CART_VIEW' && <CartSidebarView />}
|
||||||
{sidebarView === 'CHECKOUT_VIEW' && <CheckoutSidebarView />}
|
{sidebarView === 'CHECKOUT_VIEW' && <CheckoutSidebarView />}
|
||||||
{sidebarView === 'PAYMENT_VIEW' && <PaymentMethodView />}
|
{sidebarView === 'PAYMENT_VIEW' && <PaymentMethodView />}
|
||||||
@ -88,10 +91,14 @@ const SidebarView: FC<{ sidebarView: string; closeSidebar(): any }> = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const SidebarUI: FC = () => {
|
const SidebarUI: FC<{ links: any }> = ({ links }) => {
|
||||||
const { displaySidebar, closeSidebar, sidebarView } = useUI()
|
const { displaySidebar, closeSidebar, sidebarView } = useUI()
|
||||||
return displaySidebar ? (
|
return displaySidebar ? (
|
||||||
<SidebarView sidebarView={sidebarView} closeSidebar={closeSidebar} />
|
<SidebarView
|
||||||
|
sidebarView={sidebarView}
|
||||||
|
closeSidebar={closeSidebar}
|
||||||
|
links={links}
|
||||||
|
/>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +120,7 @@ const Layout: FC<Props> = ({
|
|||||||
<main className="fit">{children}</main>
|
<main className="fit">{children}</main>
|
||||||
<Footer pages={pageProps.pages} />
|
<Footer pages={pageProps.pages} />
|
||||||
<ModalUI />
|
<ModalUI />
|
||||||
<SidebarUI />
|
<SidebarUI links={navBarlinks} />
|
||||||
<FeatureBar
|
<FeatureBar
|
||||||
title="This site uses cookies to improve your experience. By clicking, you agree to our Privacy Policy."
|
title="This site uses cookies to improve your experience. By clicking, you agree to our Privacy Policy."
|
||||||
hide={acceptedCookies}
|
hide={acceptedCookies}
|
||||||
|
@ -9,6 +9,7 @@ interface Link {
|
|||||||
href: string
|
href: string
|
||||||
label: string
|
label: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NavbarProps {
|
interface NavbarProps {
|
||||||
links?: Link[]
|
links?: Link[]
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ const SidebarLayout: FC<ComponentProps> = ({
|
|||||||
<button
|
<button
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
aria-label="Close"
|
aria-label="Close"
|
||||||
className="hover:text-accent-5 transition ease-in-out duration-150 flex items-center focus:outline-none"
|
className="hover:text-accent-5 transition ease-in-out duration-150 flex items-center focus:outline-none mr-6"
|
||||||
>
|
>
|
||||||
<Cross className="h-6 w-6 hover:text-accent-3" />
|
<Cross className="h-6 w-6 hover:text-accent-3" />
|
||||||
<span className="ml-2 text-accent-7 text-sm ">Close</span>
|
<span className="ml-2 text-accent-7 text-sm ">Close</span>
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
.root {
|
||||||
|
@apply px-4 sm:px-6 sm:w-full flex-1 z-20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
@apply text-2xl font-bold;
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
import Link from 'next/link'
|
||||||
|
import s from './MenuSidebarView.module.css'
|
||||||
|
import { FC } from 'react'
|
||||||
|
import { useUI } from '@components/ui/context'
|
||||||
|
import SidebarLayout from '@components/common/SidebarLayout'
|
||||||
|
import { Link as LinkProps} from '.'
|
||||||
|
|
||||||
|
|
||||||
|
interface MenuProps {
|
||||||
|
links?: LinkProps[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const MenuSidebarView: FC<MenuProps> = (props) => {
|
||||||
|
const { closeSidebar } = useUI()
|
||||||
|
const handleClose = () => closeSidebar()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SidebarLayout handleClose={handleClose}>
|
||||||
|
<div className={s.root}>
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
<li className={s.item}>
|
||||||
|
<Link href="/search">
|
||||||
|
<a>All</a>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
{props.links?.map((l: any) => (
|
||||||
|
<li key={l.href} className={s.item}>
|
||||||
|
<Link href={l.href}>
|
||||||
|
<a>{l.label}</a>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</SidebarLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MenuSidebarView
|
6
components/common/UserNav/MenuSidebarView/index.ts
Normal file
6
components/common/UserNav/MenuSidebarView/index.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export { default } from './MenuSidebarView'
|
||||||
|
|
||||||
|
export interface Link {
|
||||||
|
href: string
|
||||||
|
label: string
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
.root {
|
.root {
|
||||||
@apply relative;
|
@apply relative flex items-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list {
|
.list {
|
||||||
@ -7,14 +7,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
@apply mr-6 cursor-pointer relative transition ease-in-out duration-100 flex items-center outline-none text-primary;
|
@apply ml-6 cursor-pointer relative transition ease-in-out duration-100 flex items-center outline-none text-primary;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@apply text-accent-6 transition scale-110 duration-100;
|
@apply text-accent-6 transition scale-110 duration-100;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:first-child {
|
||||||
@apply mr-0;
|
@apply ml-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus,
|
&:focus,
|
||||||
@ -35,6 +35,11 @@
|
|||||||
@apply inline-flex justify-center rounded-full;
|
@apply inline-flex justify-center rounded-full;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatarButton:focus {
|
.mobileMenu {
|
||||||
@apply outline-none;
|
@apply flex lg:hidden ml-6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.avatarButton:focus,
|
||||||
|
.mobileMenu:focus {
|
||||||
|
@apply outline-none;
|
||||||
|
}
|
@ -10,6 +10,7 @@ import { useUI } from '@components/ui/context'
|
|||||||
import Button from '@components/ui/Button'
|
import Button from '@components/ui/Button'
|
||||||
import DropdownMenu from './DropdownMenu'
|
import DropdownMenu from './DropdownMenu'
|
||||||
import s from './UserNav.module.css'
|
import s from './UserNav.module.css'
|
||||||
|
import Menu from '@components/icons/Menu'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string
|
className?: string
|
||||||
@ -20,7 +21,8 @@ const countItem = (count: number, item: LineItem) => count + item.quantity
|
|||||||
const UserNav: FC<Props> = ({ className }) => {
|
const UserNav: FC<Props> = ({ className }) => {
|
||||||
const { data } = useCart()
|
const { data } = useCart()
|
||||||
const { data: customer } = useCustomer()
|
const { data: customer } = useCustomer()
|
||||||
const { toggleSidebar, closeSidebarIfPresent, openModal } = useUI()
|
const { toggleSidebar, closeSidebarIfPresent, openModal, setSidebarView } =
|
||||||
|
useUI()
|
||||||
const itemsCount = data?.lineItems.reduce(countItem, 0) ?? 0
|
const itemsCount = data?.lineItems.reduce(countItem, 0) ?? 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -31,7 +33,10 @@ const UserNav: FC<Props> = ({ className }) => {
|
|||||||
<Button
|
<Button
|
||||||
className={s.item}
|
className={s.item}
|
||||||
variant="naked"
|
variant="naked"
|
||||||
onClick={toggleSidebar}
|
onClick={() => {
|
||||||
|
setSidebarView('CART_VIEW')
|
||||||
|
toggleSidebar()
|
||||||
|
}}
|
||||||
aria-label={`Cart items: ${itemsCount}`}
|
aria-label={`Cart items: ${itemsCount}`}
|
||||||
>
|
>
|
||||||
<Bag />
|
<Bag />
|
||||||
@ -65,6 +70,19 @@ const UserNav: FC<Props> = ({ className }) => {
|
|||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
|
<li className={s.mobileMenu}>
|
||||||
|
<Button
|
||||||
|
className={s.item}
|
||||||
|
variant="naked"
|
||||||
|
onClick={() => {
|
||||||
|
setSidebarView('MOBILEMENU_VIEW')
|
||||||
|
toggleSidebar()
|
||||||
|
}}
|
||||||
|
aria-label="Menu"
|
||||||
|
>
|
||||||
|
<Menu />
|
||||||
|
</Button>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
)
|
)
|
||||||
|
21
components/icons/Menu.tsx
Normal file
21
components/icons/Menu.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
const Menu = ({ ...props }) => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className="h-6 w-6"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M4 6h16M4 12h16m-7 6h7"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Menu
|
@ -48,7 +48,7 @@ const Sidebar: FC<SidebarProps> = ({ children, onClose }) => {
|
|||||||
>
|
>
|
||||||
<div className="absolute inset-0 overflow-hidden">
|
<div className="absolute inset-0 overflow-hidden">
|
||||||
<div className={s.backdrop} onClick={onClose} />
|
<div className={s.backdrop} onClick={onClose} />
|
||||||
<section className="absolute inset-y-0 right-0 max-w-full flex outline-none pl-10">
|
<section className="absolute inset-y-0 right-0 w-full md:w-auto max-w-full flex outline-none md:pl-10">
|
||||||
<div className="h-full w-full md:w-screen md:max-w-md">
|
<div className="h-full w-full md:w-screen md:max-w-md">
|
||||||
<div className={s.sidebar} ref={contentRef}>
|
<div className={s.sidebar} ref={contentRef}>
|
||||||
{children}
|
{children}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user