Fixes & Updates (#704)

* Adding Dropdown Component

* Styling Issues

* Wishlist Fix

* Fixes for Wishlist View

* Hearts now work again

* Rollback ts

* Removing extra config to disable BigCommerce

* Fixes for Wishlist View

* Remove transition/animation for mobile

* New Updates.

* New Updates.

* Dropdown fix

* Polish

* export

* export

* revert tsconfig

Co-authored-by: Luis Alvarez D. <luis@vercel.com>

Co-authored-by: Dom Sip <dom@vercel.com>
Co-authored-by: Luis Alvarez D. <luis@vercel.com>
This commit is contained in:
Bel
2022-03-16 12:05:58 +01:00
committed by GitHub
parent 6e6db0773b
commit 172deeee86
35 changed files with 780 additions and 404 deletions

View File

@@ -0,0 +1,31 @@
.root {
@apply inset-0 fixed;
left: 72px;
z-index: 10;
height: 100vh;
min-width: 100vw;
transition: none;
}
@media screen(lg) {
.root {
@apply static;
min-width: inherit;
height: inherit;
}
}
.link {
@apply text-primary flex cursor-pointer px-6 py-3
transition ease-in-out duration-150 leading-6
font-medium items-center capitalize w-full box-border
outline-0;
}
.link:hover {
@apply bg-accent-1 outline-none;
}
.link.active {
@apply font-bold bg-accent-2;
}

View File

@@ -0,0 +1,86 @@
import cn from 'clsx'
import { useTheme } from 'next-themes'
import { useRouter } from 'next/router'
import { Moon, Sun } from '@components/icons'
import s from './CustomerMenuContent.module.css'
import useLogout from '@framework/auth/use-logout'
import {
DropdownContent,
DropdownMenuItem,
} from '@components/ui/Dropdown/Dropdown'
const LINKS = [
{
name: 'My Orders',
href: '/orders',
},
{
name: 'My Profile',
href: '/profile',
},
{
name: 'My Cart',
href: '/cart',
},
]
export default function CustomerMenuContent() {
const router = useRouter()
const logout = useLogout()
const { pathname } = useRouter()
const { theme, setTheme } = useTheme()
function handleClick(_: React.MouseEvent<HTMLAnchorElement>, href: string) {
router.push(href)
}
return (
<DropdownContent
asChild
side="bottom"
sideOffset={10}
className={s.root}
id="CustomerMenuContent"
>
{LINKS.map(({ name, href }) => (
<DropdownMenuItem key={href}>
<a
className={cn(s.link, {
[s.active]: pathname === href,
})}
onClick={(e) => handleClick(e, href)}
>
{name}
</a>
</DropdownMenuItem>
))}
<DropdownMenuItem>
<a
className={cn(s.link, 'justify-between')}
onClick={() => {
setTheme(theme === 'dark' ? 'light' : 'dark')
}}
>
<div>
Theme: <strong>{theme}</strong>{' '}
</div>
<div className="ml-3">
{theme == 'dark' ? (
<Moon width={20} height={20} />
) : (
<Sun width={20} height={20} />
)}
</div>
</a>
</DropdownMenuItem>
<DropdownMenuItem>
<a
className={cn(s.link, 'border-t border-accent-2 mt-4')}
onClick={() => logout()}
>
Logout
</a>
</DropdownMenuItem>
</DropdownContent>
)
}

View File

@@ -0,0 +1 @@
export { default } from './CustomerMenuContent'

View File

@@ -1,26 +0,0 @@
@screen lg {
.dropdownMenu {
@apply absolute top-10 border border-accent-1 shadow-lg w-56 h-auto;
}
}
.dropdownMenu {
@apply fixed right-0 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full;
}
.link {
@apply text-primary flex cursor-pointer px-6 py-3 flex transition ease-in-out duration-150 leading-6 font-medium items-center;
text-transform: capitalize;
}
.link:hover {
@apply bg-accent-1;
}
.link.active {
@apply font-bold bg-accent-2;
}
.off {
@apply hidden;
}

View File

@@ -1,125 +0,0 @@
import cn from 'clsx'
import Link from 'next/link'
import { FC, useRef, useState, useEffect } from 'react'
import { useTheme } from 'next-themes'
import { useRouter } from 'next/router'
import s from './DropdownMenu.module.css'
import { Avatar } from '@components/common'
import { Moon, Sun } from '@components/icons'
import { useUI } from '@components/ui/context'
import ClickOutside from '@lib/click-outside'
import useLogout from '@framework/auth/use-logout'
import {
disableBodyScroll,
enableBodyScroll,
clearAllBodyScrollLocks,
} from 'body-scroll-lock'
interface DropdownMenuProps {
open?: boolean
}
const LINKS = [
{
name: 'My Orders',
href: '/orders',
},
{
name: 'My Profile',
href: '/profile',
},
{
name: 'My Cart',
href: '/cart',
},
]
const DropdownMenu: FC<DropdownMenuProps> = ({ open = false }) => {
const logout = useLogout()
const { pathname } = useRouter()
const { theme, setTheme } = useTheme()
const [display, setDisplay] = useState(false)
const { closeSidebarIfPresent } = useUI()
const ref = useRef() as React.MutableRefObject<HTMLUListElement>
useEffect(() => {
if (ref.current) {
if (display) {
disableBodyScroll(ref.current)
} else {
enableBodyScroll(ref.current)
}
}
return () => {
clearAllBodyScrollLocks()
}
}, [display])
return (
<ClickOutside active={display} onClick={() => setDisplay(false)}>
<div>
<button
className={s.avatarButton}
onClick={() => setDisplay(!display)}
aria-label="Menu"
>
<Avatar />
</button>
{display && (
<ul className={s.dropdownMenu} ref={ref}>
{LINKS.map(({ name, href }) => (
<li key={href}>
<div>
<Link href={href}>
<a
className={cn(s.link, {
[s.active]: pathname === href,
})}
onClick={() => {
setDisplay(false)
closeSidebarIfPresent()
}}
>
{name}
</a>
</Link>
</div>
</li>
))}
<li>
<a
className={cn(s.link, 'justify-between')}
onClick={() => {
theme === 'dark' ? setTheme('light') : setTheme('dark')
setDisplay(false)
}}
>
<div>
Theme: <strong>{theme}</strong>{' '}
</div>
<div className="ml-3">
{theme == 'dark' ? (
<Moon width={20} height={20} />
) : (
<Sun width="20" height={20} />
)}
</div>
</a>
</li>
<li>
<a
className={cn(s.link, 'border-t border-accent-2 mt-4')}
onClick={() => logout()}
>
Logout
</a>
</li>
</ul>
)}
</div>
</ClickOutside>
)
}
export default DropdownMenu

View File

@@ -3,5 +3,5 @@
}
.item {
@apply text-2xl font-bold;
}
@apply text-xl font-bold py-2;
}

View File

@@ -1,31 +1,32 @@
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 '.'
import type { Link as LinkProps } from './index'
interface MenuProps {
export default function MenuSidebarView({
links = [],
}: {
links?: LinkProps[]
}
const MenuSidebarView: FC<MenuProps> = (props) => {
}) {
const { closeSidebar } = useUI()
const handleClose = () => closeSidebar()
return (
<SidebarLayout handleClose={handleClose}>
<SidebarLayout handleClose={() => closeSidebar()}>
<div className={s.root}>
<nav>
<ul>
<li className={s.item}>
<li className={s.item} onClick={() => closeSidebar()}>
<Link href="/search">
<a>All</a>
</Link>
</li>
{props.links?.map((l: any) => (
<li key={l.href} className={s.item}>
{links.map((l: any) => (
<li
key={l.href}
className={s.item}
onClick={() => closeSidebar()}
>
<Link href={l.href}>
<a>{l.label}</a>
</Link>
@@ -38,4 +39,4 @@ const MenuSidebarView: FC<MenuProps> = (props) => {
)
}
export default MenuSidebarView
MenuSidebarView

View File

@@ -1,6 +1,5 @@
export { default } from './MenuSidebarView'
export interface Link {
href: string
label: string
}
}

View File

@@ -7,20 +7,21 @@
}
.item {
@apply ml-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 {
@apply text-accent-6 transition scale-110 duration-100;
}
.item:hover {
@apply text-accent-6 transition scale-110 duration-100;
}
&:first-child {
@apply ml-0;
}
.item:first-child {
@apply ml-0;
}
&:focus,
&:active {
@apply outline-none;
}
.item:focus,
.item:active {
@apply outline-none;
}
.bagCount {
@@ -36,10 +37,23 @@
}
.mobileMenu {
@apply flex lg:hidden ml-6
@apply flex lg:hidden ml-6 text-white;
}
.avatarButton:focus,
.mobileMenu:focus {
@apply outline-none;
}
}
.dropdownDesktop {
@apply hidden -z-10;
}
@media screen(lg) {
.dropdownDesktop {
@apply block;
}
.dropdownMobile {
@apply hidden;
}
}

View File

@@ -1,29 +1,40 @@
import { FC } from 'react'
import Link from 'next/link'
import cn from 'clsx'
import type { LineItem } from '@commerce/types/cart'
import useCart from '@framework/cart/use-cart'
import useCustomer from '@framework/customer/use-customer'
import { Avatar } from '@components/common'
import { Heart, Bag } from '@components/icons'
import { useUI } from '@components/ui/context'
import Button from '@components/ui/Button'
import DropdownMenu from './DropdownMenu'
import Link from 'next/link'
import s from './UserNav.module.css'
import Menu from '@components/icons/Menu'
import { Avatar } from '@components/common'
import useCart from '@framework/cart/use-cart'
import { useUI } from '@components/ui/context'
import { Heart, Bag, Menu } from '@components/icons'
import CustomerMenuContent from './CustomerMenuContent'
import useCustomer from '@framework/customer/use-customer'
import React from 'react'
import {
Dropdown,
DropdownTrigger as DropdownTriggerInst,
Button,
} from '@components/ui'
interface Props {
className?: string
}
import type { LineItem } from '@commerce/types/cart'
const countItem = (count: number, item: LineItem) => count + item.quantity
const UserNav: FC<Props> = ({ className }) => {
const UserNav: React.FC<{
className?: string
}> = ({ className }) => {
const { data } = useCart()
const { data: customer } = useCustomer()
const { toggleSidebar, closeSidebarIfPresent, openModal, setSidebarView } =
useUI()
const { data: isCustomerLoggedIn } = useCustomer()
const {
toggleSidebar,
closeSidebarIfPresent,
openModal,
setSidebarView,
openSidebar,
} = useUI()
const itemsCount = data?.lineItems.reduce(countItem, 0) ?? 0
const DropdownTrigger = isCustomerLoggedIn
? DropdownTriggerInst
: React.Fragment
return (
<nav className={cn(s.root, className)}>
@@ -57,28 +68,29 @@ const UserNav: FC<Props> = ({ className }) => {
)}
{process.env.COMMERCE_CUSTOMERAUTH_ENABLED && (
<li className={s.item}>
{customer ? (
<DropdownMenu />
) : (
<button
className={s.avatarButton}
aria-label="Menu"
onClick={() => openModal()}
>
<Avatar />
</button>
)}
<Dropdown>
<DropdownTrigger asChild>
<button
aria-label="Menu"
className={s.avatarButton}
onClick={() => (isCustomerLoggedIn ? null : openModal())}
>
<Avatar />
</button>
</DropdownTrigger>
<CustomerMenuContent />
</Dropdown>
</li>
)}
<li className={s.mobileMenu}>
<Button
className={s.item}
aria-label="Menu"
variant="naked"
onClick={() => {
setSidebarView('MOBILEMENU_VIEW')
toggleSidebar()
openSidebar()
setSidebarView('MOBILE_MENU_VIEW')
}}
aria-label="Menu"
>
<Menu />
</Button>

View File

@@ -1 +1,3 @@
export { default } from './UserNav'
export { default as MenuSidebarView } from './MenuSidebarView'
export { default as CustomerMenuContent } from './CustomerMenuContent'