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

@@ -4,11 +4,9 @@
--secondary: #000000;
--secondary-2: #111;
--selection: var(--cyan);
--text-base: #000000;
--text-primary: #000000;
--text-secondary: white;
--hover: rgba(0, 0, 0, 0.075);
--hover-1: rgba(0, 0, 0, 0.15);
--hover-2: rgba(0, 0, 0, 0.25);
@@ -17,15 +15,11 @@
--red: #da3c3c;
--purple: #f81ce5;
--blue: #0070f3;
--pink: #ff0080;
--pink-light: #ff379c;
--magenta: #eb367f;
--violet: #7928ca;
--violet-dark: #4c2889;
--accent-0: #fff;
--accent-1: #fafafa;
--accent-2: #eaeaea;
@@ -36,7 +30,6 @@
--accent-7: #333333;
--accent-8: #111111;
--accent-9: #000;
--font-sans: -apple-system, system-ui, BlinkMacSystemFont, 'Helvetica Neue',
'Helvetica', sans-serif;
}
@@ -50,11 +43,9 @@
--hover-1: rgba(255, 255, 255, 0.15);
--hover-2: rgba(255, 255, 255, 0.25);
--selection: var(--purple);
--text-base: white;
--text-primary: white;
--text-secondary: black;
--accent-9: #fff;
--accent-8: #fafafa;
--accent-7: #eaeaea;
@@ -73,17 +64,11 @@
box-sizing: inherit;
}
html {
html,
body {
height: 100%;
box-sizing: border-box;
touch-action: manipulation;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
html,
body {
font-family: var(--font-sans);
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
@@ -104,15 +89,15 @@ a {
}
.animated {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
-webkit-animation-duration: 1s;
-webkit-animation-fill-mode: both;
}
.fadeIn {
-webkit-animation-name: fadeIn;
animation-name: fadeIn;
-webkit-animation-name: fadeIn;
}
@-webkit-keyframes fadeIn {

View File

@@ -5,11 +5,5 @@
"wishlist": false,
"customerAuth": false,
"customCheckout": false
},
"@vercel/commerce-bigcommerce": {
"features": {
"wishlist": false,
"customerAuth": false
}
}
}

View File

@@ -1,12 +1,11 @@
import cn from 'clsx'
import React, { FC } from 'react'
import s from './Layout.module.css'
import dynamic from 'next/dynamic'
import { useRouter } from 'next/router'
import { CommerceProvider } from '@framework'
import LoginView from '@components/auth/LoginView'
import { useUI } from '@components/ui/context'
import type { Page } from '@commerce/types/page'
import { Navbar, Footer } from '@components/common'
import type { Category } from '@commerce/types/site'
import ShippingView from '@components/checkout/ShippingView'
import CartSidebarView from '@components/cart/CartSidebarView'
import { useAcceptCookies } from '@lib/hooks/useAcceptCookies'
@@ -14,10 +13,10 @@ import { Sidebar, Button, LoadingDots } from '@components/ui'
import PaymentMethodView from '@components/checkout/PaymentMethodView'
import CheckoutSidebarView from '@components/checkout/CheckoutSidebarView'
import { CheckoutProvider } from '@components/checkout/context'
import MenuSidebarView, { Link } from '../UserNav/MenuSidebarView'
import LoginView from '@components/auth/LoginView'
import s from './Layout.module.css'
import { MenuSidebarView } from '@components/common/UserNav'
import type { Page } from '@commerce/types/page'
import type { Category } from '@commerce/types/site'
import type { Link as LinkProps } from '../UserNav/MenuSidebarView'
const Loading = () => (
<div className="w-80 h-80 flex items-center text-center justify-center p-3">
@@ -29,35 +28,26 @@ const dynamicProps = {
loading: Loading,
}
const SignUpView = dynamic(
() => import('@components/auth/SignUpView'),
{
...dynamicProps
}
)
const SignUpView = dynamic(() => import('@components/auth/SignUpView'), {
...dynamicProps,
})
const ForgotPassword = dynamic(
() => import('@components/auth/ForgotPassword'),
{
...dynamicProps
}
)
const FeatureBar = dynamic(
() => import('@components/common/FeatureBar'),
{
...dynamicProps
}
)
const Modal = dynamic(
() => import('@components/ui/Modal'),
{
...dynamicProps,
ssr: false
}
)
const FeatureBar = dynamic(() => import('@components/common/FeatureBar'), {
...dynamicProps,
})
const Modal = dynamic(() => import('@components/ui/Modal'), {
...dynamicProps,
ssr: false,
})
interface Props {
pageProps: {
pages?: Page[]
@@ -65,7 +55,7 @@ interface Props {
}
}
const ModalView: FC<{ modalView: string; closeModal(): any }> = ({
const ModalView: React.FC<{ modalView: string; closeModal(): any }> = ({
modalView,
closeModal,
}) => {
@@ -78,41 +68,41 @@ const ModalView: FC<{ modalView: string; closeModal(): any }> = ({
)
}
const ModalUI: FC = () => {
const ModalUI: React.FC = () => {
const { displayModal, closeModal, modalView } = useUI()
return displayModal ? (
<ModalView modalView={modalView} closeModal={closeModal} />
) : null
}
const SidebarView: FC<{
const SidebarView: React.FC<{
sidebarView: string
closeSidebar(): any
links: Link[]
links: LinkProps[]
}> = ({ sidebarView, closeSidebar, links }) => {
return (
<Sidebar onClose={closeSidebar}>
{sidebarView === 'MOBILEMENU_VIEW' && <MenuSidebarView links={links} />}
{sidebarView === 'CART_VIEW' && <CartSidebarView />}
{sidebarView === 'CHECKOUT_VIEW' && <CheckoutSidebarView />}
{sidebarView === 'PAYMENT_VIEW' && <PaymentMethodView />}
{sidebarView === 'SHIPPING_VIEW' && <ShippingView />}
{sidebarView === 'PAYMENT_VIEW' && <PaymentMethodView />}
{sidebarView === 'CHECKOUT_VIEW' && <CheckoutSidebarView />}
{sidebarView === 'MOBILE_MENU_VIEW' && <MenuSidebarView links={links} />}
</Sidebar>
)
}
const SidebarUI: FC<{ links: any }> = ({ links }) => {
const SidebarUI: React.FC<{ links: LinkProps[] }> = ({ links }) => {
const { displaySidebar, closeSidebar, sidebarView } = useUI()
return displaySidebar ? (
<SidebarView
links={links}
sidebarView={sidebarView}
closeSidebar={closeSidebar}
links={links}
/>
) : null
}
const Layout: FC<Props> = ({
const Layout: React.FC<Props> = ({
children,
pageProps: { categories = [], ...pageProps },
}) => {

View File

@@ -16,7 +16,7 @@ interface NavbarProps {
const Navbar: FC<NavbarProps> = ({ links }) => (
<NavbarRoot>
<Container>
<Container clean className="mx-auto max-w-8xl px-6">
<div className={s.nav}>
<div className="flex items-center flex-1">
<Link href="/">

View File

@@ -12,8 +12,8 @@ type ComponentProps = { className?: string } & (
const SidebarLayout: FC<ComponentProps> = ({
children,
className,
handleClose,
handleBack,
handleClose,
}) => {
return (
<div className={cn(s.root, className)}>
@@ -38,9 +38,8 @@ const SidebarLayout: FC<ComponentProps> = ({
<span className="ml-2 text-accent-7 text-xs">Back</span>
</button>
)}
<span className={s.nav}>
<UserNav />
</span>
<UserNav />
</header>
<div className={s.container}>{children}</div>
</div>

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'

View File

@@ -1,17 +1,18 @@
export { default as Bag } from './Bag'
export { default as Sun } from './Sun'
export { default as Moon } from './Moon'
export { default as Menu } from './Menu'
export { default as Info } from './Info'
export { default as Star } from './Star'
export { default as Plus } from './Plus'
export { default as Heart } from './Heart'
export { default as Trash } from './Trash'
export { default as Cross } from './Cross'
export { default as Plus } from './Plus'
export { default as Minus } from './Minus'
export { default as Check } from './Check'
export { default as Sun } from './Sun'
export { default as Moon } from './Moon'
export { default as Github } from './Github'
export { default as Info } from './Info'
export { default as Vercel } from './Vercel'
export { default as MapPin } from './MapPin'
export { default as Star } from './Star'
export { default as ArrowLeft } from './ArrowLeft'
export { default as ArrowRight } from './ArrowRight'
export { default as CreditCard } from './CreditCard'

View File

@@ -12,10 +12,10 @@ const Container: FC<ContainerProps> = ({
children,
className,
el = 'div',
clean,
clean = false, // Full Width Screen
}) => {
const rootClassName = cn(className, {
'mx-auto max-w-8xl px-6': !clean,
'mx-auto max-w-7xl px-6 w-full': !clean,
})
let Component: React.ComponentType<React.HTMLAttributes<HTMLDivElement>> =

View File

@@ -0,0 +1,32 @@
.root {
@apply bg-accent-0;
animation: none;
transition: none;
min-width: 100%;
}
@media screen(lg) {
.root {
@apply bg-accent-0;
box-shadow: hsl(206 22% 7% / 45%) 0px 10px 38px -10px,
hsl(206 22% 7% / 20%) 0px 10px 20px -15px;
min-width: 14rem;
will-change: transform, opacity;
animation-duration: 600ms;
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
animation-fill-mode: forwards;
transform-origin: var(--radix-dropdown-menu-content-transform-origin);
animation-name: slideIn;
}
}
@keyframes slideIn {
0% {
opacity: 0;
transform: translateY(2px);
}
100% {
opacity: 1;
transform: translateY(0px);
}
}

View File

@@ -0,0 +1,22 @@
import cn from 'clsx'
import React from 'react'
import s from './Dropdown.module.css'
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
export const Dropdown = DropdownMenu.Root
export const DropdownMenuItem = DropdownMenu.Item
export const DropdownTrigger = DropdownMenu.Trigger
export const DropdownMenuLabel = DropdownMenu.Label
export const DropdownMenuGroup = DropdownMenu.Group
export const DropdownContent = React.forwardRef<
HTMLDivElement,
{ children: React.ReactNode } & DropdownMenu.DropdownMenuContentProps &
React.RefAttributes<HTMLDivElement>
>(function DropdownContent({ children, className, ...props }, forwardedRef) {
return (
<DropdownMenu.Content ref={forwardedRef} sideOffset={8} {...props}>
<div className={cn(s.root, className)}>{children}</div>
</DropdownMenu.Content>
)
})

View File

@@ -1,14 +1,13 @@
import { FC, useEffect, useRef } from 'react'
import s from './Sidebar.module.css'
import cn from 'clsx'
import s from './Sidebar.module.css'
import { useEffect, useRef } from 'react'
import { disableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock'
interface SidebarProps {
children: any
onClose: () => void
}
const Sidebar: FC<SidebarProps> = ({ children, onClose }) => {
const Sidebar: React.FC<SidebarProps> = ({ children, onClose }) => {
const sidebarRef = useRef() as React.MutableRefObject<HTMLDivElement>
const contentRef = useRef() as React.MutableRefObject<HTMLDivElement>

View File

@@ -13,4 +13,5 @@ export { default as Input } from './Input'
export { default as Collapse } from './Collapse'
export { default as Quantity } from './Quantity'
export { default as Rating } from './Rating'
export * from './Dropdown/Dropdown'
export { useUI } from './context'

View File

@@ -31,8 +31,8 @@ const WishlistButton: FC<Props> = ({
const itemInWishlist = data?.items?.find(
// @ts-ignore Wishlist is not always enabled
(item) =>
item.product_id === productId &&
item.variant_id === variant.id
item.product_id === Number(productId) &&
item.variant_id === Number(variant.id)
)
const handleWishlistChange = async (e: any) => {

View File

@@ -1,21 +1,38 @@
.root {
@apply grid grid-cols-12 w-full gap-6 px-3 py-6 border-b border-accent-2 transition duration-100 ease-in-out;
@apply relative grid sm:grid-cols-1 lg:grid-cols-12
w-full gap-6 px-3 py-6 border-b border-accent-2
transition duration-100 ease-in-out;
}
&:nth-child(3n + 1) {
& .productBg {
@apply bg-violet;
}
}
.root:nth-child(3n + 1) .imageWrapper {
@apply bg-violet;
}
&:nth-child(3n + 2) {
& .productBg {
@apply bg-pink;
}
}
.root:nth-child(3n + 2) .imageWrapper {
@apply bg-pink;
}
&:nth-child(3n + 3) {
& .productBg {
@apply bg-blue;
}
.root:nth-child(3n + 3) .imageWrapper {
@apply bg-blue;
}
.imageWrapper {
@apply col-span-3;
min-width: 230px;
width: 230px;
height: 230px;
}
.description {
@apply col-span-7 flex flex-col;
}
.actions {
@apply absolute bg-accent-0 p-3 top-0 right-4;
}
@media screen(lg) {
.actions {
@apply static col-span-2 flex flex-col justify-between space-y-4;
}
}

View File

@@ -13,13 +13,11 @@ import useAddItem from '@framework/cart/use-add-item'
import useRemoveItem from '@framework/wishlist/use-remove-item'
import type { Wishlist } from '@commerce/types/wishlist'
interface Props {
item: Wishlist
}
const placeholderImg = '/product-img-placeholder.svg'
const WishlistCard: FC<Props> = ({ item }) => {
const WishlistCard: React.FC<{
item: Wishlist
}> = ({ item }) => {
const product: Product = item.product
const { price } = usePrice({
amount: product.price?.value,
@@ -63,41 +61,41 @@ const WishlistCard: FC<Props> = ({ item }) => {
return (
<div className={cn(s.root, { 'opacity-75 pointer-events-none': removing })}>
<div className={`col-span-3 ${s.productBg}`}>
<div>
<Image
src={product.images[0]?.url || placeholderImg}
width={400}
height={400}
alt={product.images[0]?.alt || 'Product Image'}
/>
</div>
<div className={s.imageWrapper}>
<Image
width={230}
height={230}
src={product.images[0]?.url || placeholderImg}
alt={product.images[0]?.alt || 'Product Image'}
/>
</div>
<div className="col-span-7">
<h3 className="text-2xl mb-2">
<Link href={`/product${product.path}`}>
<a>{product.name}</a>
</Link>
</h3>
<div className="mb-4">
<Text html={product.description} />
<div className={s.description}>
<div className="flex-1 mb-6">
<h3 className="text-2xl mb-2 -mt-1">
<Link href={`/product${product.path}`}>
<a>{product.name}</a>
</Link>
</h3>
<div className="mb-4">
<Text html={product.description} />
</div>
</div>
<div>
<Button
width={260}
aria-label="Add to Cart"
type="button"
onClick={addToCart}
loading={loading}
>
Add to Cart
</Button>
</div>
<Button
aria-label="Add to Cart"
type="button"
className={
'py-1 px-3 border border-secondary rounded-md shadow-sm hover:bg-primary-hover'
}
onClick={addToCart}
loading={loading}
>
Add to Cart
</Button>
</div>
<div className="col-span-2 flex flex-col justify-between">
<div className={s.actions}>
<div className="flex justify-end font-bold">{price}</div>
<div className="flex justify-end">
<div className="flex justify-end mt-4 lg:mt-0">
<button onClick={handleRemove}>
<Trash />
</button>

View File

@@ -13,6 +13,7 @@
},
"sideEffects": false,
"dependencies": {
"@radix-ui/react-dropdown-menu": "^0.1.6",
"@react-spring/web": "^9.4.1",
"@vercel/commerce": "^0.0.1",
"@vercel/commerce-bigcommerce": "^0.0.1",

View File

@@ -3,7 +3,7 @@ import useCart from '@framework/cart/use-cart'
import usePrice from '@framework/product/use-price'
import commerce from '@lib/api/commerce'
import { Layout } from '@components/common'
import { Button, Text } from '@components/ui'
import { Button, Text, Container } from '@components/ui'
import { Bag, Cross, Check, MapPin, CreditCard } from '@components/icons'
import { CartItem } from '@components/cart'
import { useUI } from '@components/ui/context'
@@ -48,8 +48,8 @@ export default function Cart() {
}
return (
<div className="grid lg:grid-cols-12 w-full max-w-7xl mx-auto">
<div className="lg:col-span-8">
<Container className="grid lg:grid-cols-12 pt-4 gap-20">
<div className="lg:col-span-7">
{isLoading || isEmpty ? (
<div className="flex-1 px-12 py-24 flex flex-col justify-center items-center ">
<span className="border border-dashed border-secondary flex items-center justify-center w-16 h-16 bg-primary p-12 rounded-lg text-primary">
@@ -82,7 +82,7 @@ export default function Cart() {
</h2>
</div>
) : (
<div className="px-4 sm:px-6 flex-1">
<div className="lg:px-0 sm:px-6 flex-1">
<Text variant="pageHeading">My Cart</Text>
<Text variant="sectionHeading">Review your Order</Text>
<ul className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-accent-2 border-b border-accent-2">
@@ -111,7 +111,7 @@ export default function Cart() {
</div>
)}
</div>
<div className="lg:col-span-4">
<div className="lg:col-span-5">
<div className="flex-shrink-0 px-4 py-24 sm:px-6">
{process.env.COMMERCE_CUSTOMCHECKOUT_ENABLED && (
<>
@@ -185,7 +185,7 @@ export default function Cart() {
</div>
</div>
</div>
</div>
</Container>
)
}

View File

@@ -22,7 +22,7 @@ export async function getStaticProps({
export default function Orders() {
return (
<Container>
<Container className="pt-4">
<Text variant="pageHeading">My Orders</Text>
<div className="flex-1 p-24 flex flex-col justify-center items-center ">
<span className="border border-dashed border-secondary rounded-full flex items-center justify-center w-16 h-16 p-12 bg-primary text-primary">

View File

@@ -23,24 +23,28 @@ export async function getStaticProps({
export default function Profile() {
const { data } = useCustomer()
return (
<Container>
<Container className="pt-4">
<Text variant="pageHeading">My Profile</Text>
{data && (
<div className="grid lg:grid-cols-12">
<div className="lg:col-span-8 pr-4">
<div>
<Text variant="sectionHeading">Full Name</Text>
<div className="grid grid-cols-4">
{data && (
<div className="flex flex-col divide-accent-2 divide-y">
<div className="flex flex-row items-center space-x-4 py-4">
<span className="text-lg font-medium text-accent-600 flex-1">
Full Name
</span>
<span>
{data.firstName} {data.lastName}
</span>
</div>
<div className="mt-5">
<Text variant="sectionHeading">Email</Text>
<div className="flex flex-row items-center space-x-4 py-4">
<span className="text-lg font-medium text-accent-600 flex-1">
Email
</span>
<span>{data.email}</span>
</div>
</div>
</div>
)}
)}
</div>
</Container>
)
}

View File

@@ -40,8 +40,8 @@ export default function Wishlist() {
const { data, isLoading, isEmpty } = useWishlist({ includeProducts: true })
return (
<Container>
<div className="mt-3 mb-20">
<Container className="pt-4">
<div className="mb-20">
<Text variant="pageHeading">My Wishlist</Text>
<div className="group flex flex-col">
{isLoading ? (
@@ -65,9 +65,9 @@ export default function Wishlist() {
</p>
</div>
) : (
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
<div className="grid grid-cols-1 gap-6 ">
{data &&
// @ts-ignore Shopify - Fix this types
// @ts-ignore - Wishlist Item Type
data.items?.map((item) => (
<WishlistCard key={item.id} item={item!} />
))}