New Release (#371)

* Custom Checkout Progress

* Updates to Checkout

* Custom Checkout Progress

* Adding tabs

* Adding Collapse

* Adding Collapse

* Improving Sidebar Scroll

* Modif footer

* Changes

* More design updates

* sidebar cart

* More design updates

* More design updates

* More design updates

* More design updates

* Types

* Types

* Design Updates

* More changes

* More changes

* More changes

* Changes

* Changes

* Changes

* New tailwind required changes

* Sidebar Styling issues with Mobile

* Latest changes - Normalizing cart

* Styling Fixes

* New changes

* Changes

* latest

* Refactor and Renaming some UI Props

* Adding Quantity Component

* Adding Rating Component

* Rating Component

* More updates

* User Select disabled, plus hidding horizontal scroll bars

* Changes

* Adding ProductOptions Component and more helpers

* Styling updates

* Styling updates

* Fix for slim tags

* Missmatch with RightArrow

* Footer updates and some styles

* Latest Updates

* Latest Updates

* Latest Updates

* Removing Portal, since it's not needed. We might add it later I'd rather not to.

* Removing Portal, since it's not needed. We might add it later I'd rather not to.

* Sam backdrop filter

* General UI Improvements

* General UI Improvements

* Search now with Geist Colors

* Now with Geist Colors

* Changes

* Scroll for Mobile on IOs devises

* LoadingDots Working (:

* Changes

* More Changes

* Perf changes

* More perf changes

* Fade to the Nametags in the ProductCard

* changes

* Search issue ui

* Search issue ui

* Make sure to only refresh navbar and modals when required

* Index revalidate

* Fixed image issue

* hide album scroll on windows

* Fix scrollbar

* Changing

* Adding 404 with Layout

* Removing Toast

* Adding Assets

* Adding Assets

* Progress with LocalProvider

* New productTag

* Only images for the drop

* changes

* Empty SWRhooks

* Adding Local Provider

* Working local

* Working view of a LocalProvider

* More updates

* Changes

* Removed react-ticker

* default to local if no env available

* default to local if no env available

* add missing `@` to css import

* rewrite search rewrites to multiple pages

* allow requests in getStaticProps to execute in parallel

* make type import explicit

* add a tsconfig.js file

* use local provider in tsconfig.js

* avoid a circular dependency

* Saleor was not in the providers list

* avoid circular dependency in bigcommerce

* Adding more to the Local Provider (#366)

* Adding more data

* Adding more data

* optimize assets (#370)

* Optimize assets (#372)

* optimize assets

* remove assets

* remove assets

* cart enabled

* Adding saleor

* Changes with Webpack

* Changes

Co-authored-by: Luis Alvarez <luis@vercel.com>
Co-authored-by: Tobias Koppers <tobias.koppers@googlemail.com>
Co-authored-by: Shu Ding <g@shud.in>
This commit is contained in:
B
2021-06-15 20:23:17 -03:00
committed by GitHub
parent 3c9b90f453
commit 78cc378a72
202 changed files with 15406 additions and 2201 deletions

View File

@@ -14,7 +14,7 @@ const Avatar: FC<Props> = ({}) => {
<div
ref={ref}
style={{ backgroundImage: userAvatar }}
className="inline-block h-8 w-8 rounded-full border-2 border-primary hover:border-secondary focus:border-secondary transition linear-out duration-150"
className="inline-block h-8 w-8 rounded-full border-2 border-primary hover:border-secondary focus:border-secondary transition-colors ease-linear"
>
{/* Add an image - We're generating a gradient as placeholder <img></img> */}
</div>

View File

@@ -1,9 +1,7 @@
.root {
@apply text-center p-6 bg-primary text-sm flex-row justify-center items-center font-medium fixed bottom-0 w-full z-30 transition-all duration-300 ease-out;
}
@screen md {
.root {
@screen md {
@apply flex text-left;
}
}

View File

@@ -1,3 +1,7 @@
.root {
@apply border-t border-accent-2;
}
.link {
& > svg {
@apply transform duration-75 ease-linear;

View File

@@ -15,65 +15,50 @@ interface Props {
pages?: Page[]
}
const LEGAL_PAGES = ['terms-of-use', 'shipping-returns', 'privacy-policy']
const links = [
{
name: 'Home',
url: '/',
},
]
const Footer: FC<Props> = ({ className, pages }) => {
const { sitePages, legalPages } = usePages(pages)
const rootClassName = cn(className)
const { sitePages } = usePages(pages)
const rootClassName = cn(s.root, className)
return (
<footer className={rootClassName}>
<Container>
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8 border-b border-accents-2 py-12 text-primary bg-primary transition-colors duration-150">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8 border-b border-accent-2 py-12 text-primary bg-primary transition-colors duration-150">
<div className="col-span-1 lg:col-span-2">
<Link href="/">
<a className="flex flex-initial items-center font-bold md:mr-24">
<span className="rounded-full border border-gray-700 mr-2">
<span className="rounded-full border border-accent-6 mr-2">
<Logo />
</span>
<span>ACME</span>
</a>
</Link>
</div>
<div className="col-span-1 lg:col-span-2">
<ul className="flex flex-initial flex-col md:flex-1">
<li className="py-3 md:py-0 md:pb-4">
<Link href="/">
<a className="text-primary hover:text-accents-6 transition ease-in-out duration-150">
Home
</a>
</Link>
</li>
{sitePages.map((page) => (
<li key={page.url} className="py-3 md:py-0 md:pb-4">
<div className="col-span-1 lg:col-span-8">
<div className="grid md:grid-rows-4 md:grid-cols-3 md:grid-flow-col">
{[...links, ...sitePages].map((page) => (
<span key={page.url} className="py-3 md:py-0 md:pb-4">
<Link href={page.url!}>
<a className="text-primary hover:text-accents-6 transition ease-in-out duration-150">
<a className="text-accent-9 hover:text-accent-6 transition ease-in-out duration-150">
{page.name}
</a>
</Link>
</li>
</span>
))}
</ul>
</div>
</div>
<div className="col-span-1 lg:col-span-2">
<ul className="flex flex-initial flex-col md:flex-1">
{legalPages.map((page) => (
<li key={page.url} className="py-3 md:py-0 md:pb-4">
<Link href={page.url!}>
<a className="text-primary hover:text-accents-6 transition ease-in-out duration-150">
{page.name}
</a>
</Link>
</li>
))}
</ul>
</div>
<div className="col-span-1 lg:col-span-6 flex items-start lg:justify-end text-primary">
<div className="col-span-1 lg:col-span-2 flex items-start lg:justify-end text-primary">
<div className="flex space-x-6 items-center h-10">
<a
className={s.link}
aria-label="Github Repository"
href="https://github.com/vercel/commerce"
className={s.link}
>
<Github />
</a>
@@ -81,12 +66,12 @@ const Footer: FC<Props> = ({ className, pages }) => {
</div>
</div>
</div>
<div className="py-12 flex flex-col md:flex-row justify-between items-center space-y-4">
<div className="pt-6 pb-10 flex flex-col md:flex-row justify-between items-center space-y-4 text-accent-6 text-sm">
<div>
<span>&copy; 2020 ACME, Inc. All rights reserved.</span>
</div>
<div className="flex items-center text-primary">
<span className="text-primary">Crafted by</span>
<div className="flex items-center text-primary text-sm">
<span className="text-primary">Created by</span>
<a
rel="noopener"
href="https://vercel.com"
@@ -95,7 +80,7 @@ const Footer: FC<Props> = ({ className, pages }) => {
className="text-primary"
>
<Vercel
className="inline-block h-6 ml-4 text-primary"
className="inline-block h-6 ml-3 text-primary"
alt="Vercel.com Logo"
/>
</a>
@@ -109,34 +94,21 @@ const Footer: FC<Props> = ({ className, pages }) => {
function usePages(pages?: Page[]) {
const { locale } = useRouter()
const sitePages: Page[] = []
const legalPages: Page[] = []
if (pages) {
pages.forEach((page) => {
const slug = page.url && getSlug(page.url)
if (!slug) return
if (locale && !slug.startsWith(`${locale}/`)) return
if (isLegalPage(slug, locale)) {
legalPages.push(page)
} else {
sitePages.push(page)
}
sitePages.push(page)
})
}
return {
sitePages: sitePages.sort(bySortOrder),
legalPages: legalPages.sort(bySortOrder),
}
}
const isLegalPage = (slug: string, locale?: string) =>
locale
? LEGAL_PAGES.some((p) => `${locale}/${p}` === slug)
: LEGAL_PAGES.includes(slug)
// Sort pages by the sort order assigned in the BC dashboard
function bySortOrder(a: Page, b: Page) {
return (a.sort_order ?? 0) - (b.sort_order ?? 0)

View File

@@ -28,7 +28,7 @@ const HomeAllProductsGrid: FC<Props> = ({
</Link>
</li>
{categories.map((cat: any) => (
<li key={cat.path} className="py-1 text-accents-8 text-base">
<li key={cat.path} className="py-1 text-accent-8 text-base">
<Link href={getCategoryPath(cat.path)}>
<a>{cat.name}</a>
</Link>
@@ -42,7 +42,7 @@ const HomeAllProductsGrid: FC<Props> = ({
</Link>
</li>
{brands.flatMap(({ node }: any) => (
<li key={node.path} className="py-1 text-accents-8 text-base">
<li key={node.path} className="py-1 text-accent-8 text-base">
<Link href={getDesignerPath(node.path)}>
<a>{node.name}</a>
</Link>

View File

@@ -3,11 +3,11 @@
}
.button {
@apply h-10 px-2 rounded-md border border-accents-2 flex items-center justify-center;
@apply h-10 px-2 rounded-md border border-accent-2 flex items-center justify-center transition-colors ease-linear;
}
.button:hover {
@apply border-accents-4 shadow-sm;
@apply border-accent-3 shadow-sm;
}
.button:focus {
@@ -16,16 +16,14 @@
.dropdownMenu {
@apply fixed right-0 top-12 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full;
}
@screen lg {
.dropdownMenu {
@apply absolute border border-accents-1 shadow-lg w-56 h-auto;
@screen lg {
@apply absolute border border-accent-1 shadow-lg w-56 h-auto;
}
}
@screen md {
.closeButton {
.closeButton {
@screen md {
@apply hidden;
}
}
@@ -36,9 +34,13 @@
}
.item:hover {
@apply bg-accents-1;
@apply bg-accent-1;
}
.icon {
transition: transform 0.2s ease;
}
.icon.active {
transform: rotate(180deg);
}

View File

@@ -59,7 +59,7 @@ const I18nWidget: FC = () => {
/>
{options && (
<span className="cursor-pointer">
<ChevronUp className={cn({ [s.icon]: display })} />
<ChevronUp className={cn(s.icon, { [s.active]: display })} />
</span>
)}
</button>

View File

@@ -1,15 +1,19 @@
import React, { FC } from 'react'
import { useRouter } from 'next/router'
import dynamic from 'next/dynamic'
import cn from 'classnames'
import type { Page } from '@commerce/types/page'
import type { Category } from '@commerce/types/site'
import React, { FC } from 'react'
import dynamic from 'next/dynamic'
import { useRouter } from 'next/router'
import { CommerceProvider } from '@framework'
import { useAcceptCookies } from '@lib/hooks/useAcceptCookies'
import { useUI } from '@components/ui/context'
import type { Page } from '@commerce/types/page'
import { Navbar, Footer } from '@components/common'
import { Sidebar, Button, Modal, LoadingDots } from '@components/ui'
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'
import { Sidebar, Button, Modal, LoadingDots } from '@components/ui'
import PaymentMethodView from '@components/checkout/PaymentMethodView'
import CheckoutSidebarView from '@components/checkout/CheckoutSidebarView'
import LoginView from '@components/auth/LoginView'
import s from './Layout.module.css'
@@ -45,15 +49,53 @@ interface Props {
}
}
const ModalView: FC<{ modalView: string; closeModal(): any }> = ({
modalView,
closeModal,
}) => {
return (
<Modal onClose={closeModal}>
{modalView === 'LOGIN_VIEW' && <LoginView />}
{modalView === 'SIGNUP_VIEW' && <SignUpView />}
{modalView === 'FORGOT_VIEW' && <ForgotPassword />}
</Modal>
)
}
const ModalUI: FC = () => {
const { displayModal, closeModal, modalView } = useUI()
return displayModal ? (
<ModalView modalView={modalView} closeModal={closeModal} />
) : null
}
const SidebarView: FC<{ sidebarView: string; closeSidebar(): any }> = ({
sidebarView,
closeSidebar,
}) => {
return (
<Sidebar onClose={closeSidebar}>
{sidebarView === 'CART_VIEW' && <CartSidebarView />}
{sidebarView === 'CHECKOUT_VIEW' && <CheckoutSidebarView />}
{sidebarView === 'PAYMENT_VIEW' && <PaymentMethodView />}
{sidebarView === 'SHIPPING_VIEW' && <ShippingView />}
</Sidebar>
)
}
const SidebarUI: FC = () => {
const { displaySidebar, closeSidebar, sidebarView } = useUI()
return displaySidebar ? (
<SidebarView sidebarView={sidebarView} closeSidebar={closeSidebar} />
) : null
}
const Layout: FC<Props> = ({
children,
pageProps: { categories = [], ...pageProps },
}) => {
const { displaySidebar, displayModal, closeSidebar, closeModal, modalView } =
useUI()
const { acceptedCookies, onAcceptCookies } = useAcceptCookies()
const { locale = 'en-US' } = useRouter()
const navBarlinks = categories.slice(0, 2).map((c) => ({
label: c.name,
href: `/search/${c.slug}`,
@@ -65,17 +107,8 @@ const Layout: FC<Props> = ({
<Navbar links={navBarlinks} />
<main className="fit">{children}</main>
<Footer pages={pageProps.pages} />
<Modal open={displayModal} onClose={closeModal}>
{modalView === 'LOGIN_VIEW' && <LoginView />}
{modalView === 'SIGNUP_VIEW' && <SignUpView />}
{modalView === 'FORGOT_VIEW' && <ForgotPassword />}
</Modal>
<Sidebar open={displaySidebar} onClose={closeSidebar}>
<CartSidebarView />
</Sidebar>
<ModalUI />
<SidebarUI />
<FeatureBar
title="This site uses cookies to improve your experience. By clicking, you agree to our Privacy Policy."
hide={acceptedCookies}

View File

@@ -2,16 +2,26 @@
@apply sticky top-0 bg-primary z-40 transition-all duration-150;
}
.nav {
@apply relative flex flex-row justify-between py-4 md:py-4;
}
.navMenu {
@apply hidden ml-6 space-x-4 lg:block;
}
.link {
@apply inline-flex items-center text-primary leading-6 font-medium transition ease-in-out duration-75 cursor-pointer text-accents-6;
@apply inline-flex items-center leading-6
transition ease-in-out duration-75 cursor-pointer
text-accent-5;
}
.link:hover {
@apply text-accents-9;
@apply text-accent-9;
}
.link:focus {
@apply outline-none text-accents-8;
@apply outline-none text-accent-8;
}
.logo {

View File

@@ -1,9 +1,9 @@
import { FC } from 'react'
import Link from 'next/link'
import s from './Navbar.module.css'
import NavbarRoot from './NavbarRoot'
import { Logo, Container } from '@components/ui'
import { Searchbar, UserNav } from '@components/common'
import NavbarRoot from './NavbarRoot'
import s from './Navbar.module.css'
interface Link {
href: string
@@ -16,14 +16,14 @@ interface NavbarProps {
const Navbar: FC<NavbarProps> = ({ links }) => (
<NavbarRoot>
<Container>
<div className="relative flex flex-row justify-between py-4 align-center md:py-6">
<div className={s.nav}>
<div className="flex items-center flex-1">
<Link href="/">
<a className={s.logo} aria-label="Logo">
<Logo />
</a>
</Link>
<nav className="hidden ml-6 space-x-4 lg:block">
<nav className={s.navMenu}>
<Link href="/search">
<a className={s.link}>All</a>
</Link>
@@ -34,16 +34,13 @@ const Navbar: FC<NavbarProps> = ({ links }) => (
))}
</nav>
</div>
<div className="justify-center flex-1 hidden lg:flex">
<Searchbar />
</div>
<div className="flex justify-end flex-1 space-x-8">
<div className="flex items-center justify-end flex-1 space-x-8">
<UserNav />
</div>
</div>
<div className="flex pb-4 lg:px-6 lg:hidden">
<Searchbar id="mobile-search" />
</div>

View File

@@ -1,9 +1,13 @@
.root {
@apply relative text-sm bg-accent-0 text-base w-full transition-colors duration-150 border border-accent-2;
}
.input {
@apply bg-transparent px-3 py-2 appearance-none w-full transition duration-150 ease-in-out pr-10;
}
@screen sm {
min-width: 300px;
}
.input::placeholder {
@apply text-accent-3;
}
.input:focus {
@@ -17,3 +21,9 @@
.icon {
@apply h-5 w-5;
}
@screen sm {
.input {
min-width: 300px;
}
}

View File

@@ -1,4 +1,4 @@
import { FC, useEffect, useMemo } from 'react'
import { FC, InputHTMLAttributes, useEffect, useMemo } from 'react'
import cn from 'classnames'
import s from './Searchbar.module.css'
import { useRouter } from 'next/router'
@@ -15,14 +15,26 @@ const Searchbar: FC<Props> = ({ className, id = 'search' }) => {
router.prefetch('/search')
}, [])
const handleKeyUp = (e: React.KeyboardEvent<HTMLInputElement>) => {
e.preventDefault()
if (e.key === 'Enter') {
const q = e.currentTarget.value
router.push(
{
pathname: `/search`,
query: q ? { q } : {},
},
undefined,
{ shallow: true }
)
}
}
return useMemo(
() => (
<div
className={cn(
'relative text-sm bg-accents-1 text-base w-full transition-colors duration-150',
className
)}
>
<div className={cn(s.root, className)}>
<label className="hidden" htmlFor={id}>
Search
</label>
@@ -31,22 +43,7 @@ const Searchbar: FC<Props> = ({ className, id = 'search' }) => {
className={s.input}
placeholder="Search for products..."
defaultValue={router.query.q}
onKeyUp={(e) => {
e.preventDefault()
if (e.key === 'Enter') {
const q = e.currentTarget.value
router.push(
{
pathname: `/search`,
query: q ? { q } : {},
},
undefined,
{ shallow: true }
)
}
}}
onKeyUp={handleKeyUp}
/>
<div className={s.iconContainer}>
<svg className={s.icon} fill="currentColor" viewBox="0 0 20 20">

View File

@@ -0,0 +1,20 @@
.root {
@apply relative h-full flex flex-col;
}
.header {
@apply sticky top-0 pl-4 py-4 pr-6
flex items-center justify-between
bg-accent-0 box-border w-full z-10;
min-height: 66px;
}
.container {
@apply flex flex-col flex-1 box-border;
}
@screen lg {
.header {
min-height: 74px;
}
}

View File

@@ -0,0 +1,50 @@
import React, { FC } from 'react'
import { Cross, ChevronLeft } from '@components/icons'
import { UserNav } from '@components/common'
import cn from 'classnames'
import s from './SidebarLayout.module.css'
type ComponentProps = { className?: string } & (
| { handleClose: () => any; handleBack?: never }
| { handleBack: () => any; handleClose?: never }
)
const SidebarLayout: FC<ComponentProps> = ({
children,
className,
handleClose,
handleBack,
}) => {
return (
<div className={cn(s.root, className)}>
<header className={s.header}>
{handleClose && (
<button
onClick={handleClose}
aria-label="Close"
className="hover:text-accent-5 transition ease-in-out duration-150 flex items-center focus:outline-none"
>
<Cross className="h-6 w-6 hover:text-accent-3" />
<span className="ml-2 text-accent-7 text-sm ">Close</span>
</button>
)}
{handleBack && (
<button
onClick={handleBack}
aria-label="Go back"
className="hover:text-accent-5 transition ease-in-out duration-150 flex items-center focus:outline-none"
>
<ChevronLeft className="h-6 w-6 hover:text-accent-3" />
<span className="ml-2 text-accent-7 text-xs">Back</span>
</button>
)}
<span className={s.nav}>
<UserNav />
</span>
</header>
<div className={s.container}>{children}</div>
</div>
)
}
export default SidebarLayout

View File

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

View File

@@ -1,10 +1,8 @@
.dropdownMenu {
@apply fixed right-0 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full;
}
@screen lg {
.dropdownMenu {
@apply absolute top-10 border border-accents-1 shadow-lg w-56 h-auto;
@screen lg {
@apply absolute top-10 border border-accent-1 shadow-lg w-56 h-auto;
}
}
@@ -14,11 +12,11 @@
}
.link:hover {
@apply bg-accents-1;
@apply bg-accent-1;
}
.link.active {
@apply font-bold bg-accents-2;
@apply font-bold bg-accent-2;
}
.off {

View File

@@ -109,7 +109,7 @@ const DropdownMenu: FC<DropdownMenuProps> = ({ open = false }) => {
</li>
<li>
<a
className={cn(s.link, 'border-t border-accents-2 mt-4')}
className={cn(s.link, 'border-t border-accent-2 mt-4')}
onClick={() => logout()}
>
Logout

View File

@@ -10,7 +10,7 @@
@apply mr-6 cursor-pointer relative transition ease-in-out duration-100 flex items-center outline-none text-primary;
&:hover {
@apply text-accents-6 transition scale-110 duration-100;
@apply text-accent-6 transition scale-110 duration-100;
}
&:last-child {
@@ -24,7 +24,7 @@
}
.bagCount {
@apply border border-accents-1 bg-secondary text-secondary absolute rounded-full right-3 top-3 flex items-center justify-center font-bold text-xs;
@apply border border-accent-1 bg-secondary text-secondary absolute rounded-full right-3 top-3 flex items-center justify-center font-bold text-xs;
padding-left: 2.5px;
padding-right: 2.5px;
min-width: 1.25rem;

View File

@@ -24,21 +24,21 @@ const UserNav: FC<Props> = ({ className }) => {
return (
<nav className={cn(s.root, className)}>
<div className={s.mainContainer}>
<ul className={s.list}>
<li className={s.item} onClick={toggleSidebar}>
<Bag />
{itemsCount > 0 && <span className={s.bagCount}>{itemsCount}</span>}
<ul className={s.list}>
<li className={s.item} onClick={toggleSidebar}>
<Bag />
{itemsCount > 0 && <span className={s.bagCount}>{itemsCount}</span>}
</li>
{process.env.COMMERCE_WISHLIST_ENABLED && (
<li className={s.item}>
<Link href="/wishlist">
<a onClick={closeSidebarIfPresent} aria-label="Wishlist">
<Heart />
</a>
</Link>
</li>
{process.env.COMMERCE_WISHLIST_ENABLED && (
<li className={s.item}>
<Link href="/wishlist">
<a onClick={closeSidebarIfPresent} aria-label="Wishlist">
<Heart />
</a>
</Link>
</li>
)}
)}
{process.env.COMMERCE_CUSTOMER_ENABLED && (
<li className={s.item}>
{customer ? (
<DropdownMenu />
@@ -52,8 +52,8 @@ const UserNav: FC<Props> = ({ className }) => {
</button>
)}
</li>
</ul>
</div>
)}
</ul>
</nav>
)
}