mirror of
https://github.com/vercel/commerce.git
synced 2025-05-18 07:26:59 +00:00
Custom Checkout Progress
This commit is contained in:
parent
8fb6c7b206
commit
7c1344a19e
@ -20,16 +20,20 @@
|
||||
--blue: #0070f3;
|
||||
--violet: #5f3dc4;
|
||||
--violet-light: #7048e8;
|
||||
--accents-0: #f8f9fa;
|
||||
--accents-1: #f1f3f5;
|
||||
--accents-2: #e9ecef;
|
||||
--accents-3: #dee2e6;
|
||||
--accents-4: #ced4da;
|
||||
--accents-5: #adb5bd;
|
||||
--accents-6: #868e96;
|
||||
--accents-7: #495057;
|
||||
--accents-8: #343a40;
|
||||
--accents-9: #212529;
|
||||
|
||||
--accent-0: #fff;
|
||||
--accent-05: #f8f9fa;
|
||||
--accent-1: #f1f3f5;
|
||||
--accent-2: #e9ecef;
|
||||
--accent-3: #dee2e6;
|
||||
--accent-4: #ced4da;
|
||||
--accent-5: #adb5bd;
|
||||
--accent-6: #868e96;
|
||||
--accent-7: #495057;
|
||||
--accent-8: #343a40;
|
||||
--accent-9: #212529;
|
||||
--accent-10: #000;
|
||||
|
||||
--font-sans: -apple-system, system-ui, BlinkMacSystemFont, 'Helvetica Neue',
|
||||
'Helvetica', sans-serif;
|
||||
}
|
||||
@ -48,16 +52,18 @@
|
||||
--text-primary: white;
|
||||
--text-secondary: black;
|
||||
|
||||
--accents-0: #212529;
|
||||
--accents-1: #343a40;
|
||||
--accents-2: #495057;
|
||||
--accents-3: #868e96;
|
||||
--accents-4: #adb5bd;
|
||||
--accents-5: #ced4da;
|
||||
--accents-6: #dee2e6;
|
||||
--accents-7: #e9ecef;
|
||||
--accents-8: #f1f3f5;
|
||||
--accents-9: #f8f9fa;
|
||||
--accent-0: #000;
|
||||
--accent-05: #212529;
|
||||
--accent-1: #343a40;
|
||||
--accent-2: #495057;
|
||||
--accent-3: #868e96;
|
||||
--accent-4: #adb5bd;
|
||||
--accent-5: #ced4da;
|
||||
--accent-6: #dee2e6;
|
||||
--accent-7: #e9ecef;
|
||||
--accent-8: #f1f3f5;
|
||||
--accent-9: #f8f9fa;
|
||||
--accent-10: #fff;
|
||||
}
|
||||
|
||||
*,
|
||||
@ -127,4 +133,3 @@ a {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ const ForgotPassword: FC<Props> = () => {
|
||||
</div>
|
||||
|
||||
<span className="pt-3 text-center text-sm">
|
||||
<span className="text-accents-7">Do you have an account?</span>
|
||||
<span className="text-accent-7">Do you have an account?</span>
|
||||
{` `}
|
||||
<a
|
||||
className="text-accent-9 font-bold hover:underline cursor-pointer"
|
||||
|
@ -87,7 +87,7 @@ const LoginView: FC<Props> = () => {
|
||||
Log In
|
||||
</Button>
|
||||
<div className="pt-1 text-center text-sm">
|
||||
<span className="text-accents-7">Don't have an account?</span>
|
||||
<span className="text-accent-7">Don't have an account?</span>
|
||||
{` `}
|
||||
<a
|
||||
className="text-accent-9 font-bold hover:underline cursor-pointer"
|
||||
|
@ -76,7 +76,7 @@ const SignUpView: FC<Props> = () => {
|
||||
<Input placeholder="Last Name" onChange={setLastName} />
|
||||
<Input type="email" placeholder="Email" onChange={setEmail} />
|
||||
<Input type="password" placeholder="Password" onChange={setPassword} />
|
||||
<span className="text-accents-8">
|
||||
<span className="text-accent-8">
|
||||
<span className="inline-block align-middle ">
|
||||
<Info width="15" height="15" />
|
||||
</span>{' '}
|
||||
@ -97,7 +97,7 @@ const SignUpView: FC<Props> = () => {
|
||||
</div>
|
||||
|
||||
<span className="pt-1 text-center text-sm">
|
||||
<span className="text-accents-7">Do you have an account?</span>
|
||||
<span className="text-accent-7">Do you have an account?</span>
|
||||
{` `}
|
||||
<a
|
||||
className="text-accent-9 font-bold hover:underline cursor-pointer"
|
||||
|
@ -1,6 +1,31 @@
|
||||
.root {
|
||||
@apply flex flex-col py-4;
|
||||
}
|
||||
|
||||
.root:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.actions {
|
||||
@apply flex p-1 border-accent-3 border items-center justify-center w-12 text-accent-7;
|
||||
transition-property: border-color, background, color, transform, box-shadow;
|
||||
transition-duration: 0.15s;
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
|
||||
.actions:hover {
|
||||
@apply bg-accent-1 border-accent-4 text-accent-9;
|
||||
transition: border-color;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.actions:focus {
|
||||
@apply bg-accent-2 outline-none;
|
||||
}
|
||||
|
||||
.quantity {
|
||||
appearance: textfield;
|
||||
@apply w-8 border-accents-2 border mx-3 rounded text-center text-sm text-black;
|
||||
@apply w-8 border-accent-2 border mx-3 rounded text-center text-sm text-black;
|
||||
}
|
||||
|
||||
.quantity::-webkit-outer-spin-button,
|
||||
|
@ -3,7 +3,7 @@ import cn from 'classnames'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import s from './CartItem.module.css'
|
||||
import { Trash, Plus, Minus } from '@components/icons'
|
||||
import { Trash, Plus, Minus, Cross } from '@components/icons'
|
||||
import { useUI } from '@components/ui/context'
|
||||
import type { LineItem } from '@framework/types'
|
||||
import usePrice from '@framework/product/use-price'
|
||||
@ -20,8 +20,10 @@ type ItemOption = {
|
||||
const CartItem = ({
|
||||
item,
|
||||
currencyCode,
|
||||
noEdit = false,
|
||||
...rest
|
||||
}: {
|
||||
noEdit?: boolean
|
||||
item: LineItem
|
||||
currencyCode: string
|
||||
}) => {
|
||||
@ -49,6 +51,7 @@ const CartItem = ({
|
||||
setQuantity(Number(e.target.value))
|
||||
}
|
||||
}
|
||||
|
||||
const handleBlur = () => {
|
||||
const val = Number(quantity)
|
||||
|
||||
@ -56,6 +59,7 @@ const CartItem = ({
|
||||
updateQuantity(val)
|
||||
}
|
||||
}
|
||||
|
||||
const increaseQuantity = (n = 1) => {
|
||||
const val = Number(quantity) + n
|
||||
|
||||
@ -64,6 +68,7 @@ const CartItem = ({
|
||||
updateQuantity(val)
|
||||
}
|
||||
}
|
||||
|
||||
const handleRemove = async () => {
|
||||
setRemoving(true)
|
||||
|
||||
@ -87,11 +92,12 @@ const CartItem = ({
|
||||
|
||||
return (
|
||||
<li
|
||||
className={cn('flex flex-row space-x-8 py-8', {
|
||||
'opacity-75 pointer-events-none': removing,
|
||||
className={cn(s.root, {
|
||||
'opacity-50 pointer-events-none': removing,
|
||||
})}
|
||||
{...rest}
|
||||
>
|
||||
<div className="flex flex-row space-x-4 py-4">
|
||||
<div className="w-16 h-16 bg-violet relative overflow-hidden cursor-pointer">
|
||||
<Link href={`/product/${item.path}`}>
|
||||
<Image
|
||||
@ -108,7 +114,7 @@ const CartItem = ({
|
||||
<div className="flex-1 flex flex-col text-base">
|
||||
<Link href={`/product/${item.path}`}>
|
||||
<span
|
||||
className="font-bold text-lg cursor-pointer leading-6"
|
||||
className="font-medium cursor-pointer leading-6"
|
||||
onClick={() => closeSidebarIfPresent()}
|
||||
>
|
||||
{item.name}
|
||||
@ -117,45 +123,69 @@ const CartItem = ({
|
||||
{options && options.length > 0 ? (
|
||||
<div className="">
|
||||
{options.map((option: ItemOption, i: number) => (
|
||||
<span
|
||||
<div
|
||||
key={`${item.id}-${option.name}`}
|
||||
className="text-sm font-semibold text-accents-7"
|
||||
className="text-sm font-semibold text-accent-7 inline-flex items-center justify-center"
|
||||
>
|
||||
{option.name}
|
||||
{option.name === 'Color' ? (
|
||||
<span
|
||||
className="mx-2 rounded-full bg-transparent border w-5 h-5 p-1 text-accent-9 inline-flex items-center justify-center overflow-hidden"
|
||||
style={{
|
||||
backgroundColor: `${option.value}`,
|
||||
}}
|
||||
></span>
|
||||
) : (
|
||||
<span className="mx-2 rounded-full bg-transparent border h-5 p-1 text-accent-9 inline-flex items-center justify-center overflow-hidden">
|
||||
{option.value}
|
||||
{i === options.length - 1 ? '' : ', '}
|
||||
</span>
|
||||
)}
|
||||
{i === options.length - 1 ? '' : <span className="mr-3" />}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="flex items-center mt-3">
|
||||
<button type="button" onClick={() => increaseQuantity(-1)}>
|
||||
<Minus width={18} height={18} />
|
||||
</div>
|
||||
<div className="flex flex-col justify-between space-y-2 text-sm">
|
||||
<span>{price}</span>
|
||||
</div>
|
||||
</div>
|
||||
{!noEdit ? (
|
||||
<div className="flex flex-row h-9">
|
||||
<button className={s.actions} onClick={handleRemove}>
|
||||
<Cross width={20} height={20} />
|
||||
</button>
|
||||
<label>
|
||||
<label className="w-full border-accent-3 border ml-2">
|
||||
<input
|
||||
type="number"
|
||||
max={99}
|
||||
min={0}
|
||||
className={s.quantity}
|
||||
className="bg-transparent px-4 w-full h-full focus:outline-none"
|
||||
value={quantity}
|
||||
onChange={handleQuantity}
|
||||
onBlur={handleBlur}
|
||||
/>
|
||||
</label>
|
||||
<button type="button" onClick={() => increaseQuantity(1)}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => increaseQuantity(-1)}
|
||||
className={s.actions}
|
||||
style={{ marginLeft: '-1px' }}
|
||||
>
|
||||
<Minus width={18} height={18} />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => increaseQuantity(1)}
|
||||
className={cn(s.actions)}
|
||||
style={{ marginLeft: '-1px' }}
|
||||
>
|
||||
<Plus width={18} height={18} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col justify-between space-y-2 text-base">
|
||||
<span>{price}</span>
|
||||
<button
|
||||
className="flex justify-end outline-none"
|
||||
onClick={handleRemove}
|
||||
>
|
||||
<Trash />
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<div>x{quantity}</div>
|
||||
)}
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
.root {
|
||||
@apply h-full flex flex-col;
|
||||
@apply h-full flex flex-col relative w-full relative;
|
||||
}
|
||||
|
||||
.root.empty {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { FC } from 'react'
|
||||
import cn from 'classnames'
|
||||
import Link from 'next/link'
|
||||
import CartItem from '../CartItem'
|
||||
import { FC } from 'react'
|
||||
import s from './CartSidebarView.module.css'
|
||||
import CartItem from '../CartItem'
|
||||
import { Button } from '@components/ui'
|
||||
import { UserNav } from '@components/common'
|
||||
import { useUI } from '@components/ui/context'
|
||||
@ -11,7 +11,7 @@ import useCart from '@framework/cart/use-cart'
|
||||
import usePrice from '@framework/product/use-price'
|
||||
|
||||
const CartSidebarView: FC = () => {
|
||||
const { closeSidebar } = useUI()
|
||||
const { closeSidebar, setSidebarView } = useUI()
|
||||
const { data, isLoading, isEmpty } = useCart()
|
||||
|
||||
const { price: subTotal } = usePrice(
|
||||
@ -27,6 +27,7 @@ const CartSidebarView: FC = () => {
|
||||
}
|
||||
)
|
||||
const handleClose = () => closeSidebar()
|
||||
const goToCheckout = () => setSidebarView('CHECKOUT_VIEW')
|
||||
|
||||
const error = null
|
||||
const success = null
|
||||
@ -43,9 +44,12 @@ const CartSidebarView: FC = () => {
|
||||
<button
|
||||
onClick={handleClose}
|
||||
aria-label="Close panel"
|
||||
className="hover:text-gray-500 transition ease-in-out duration-150"
|
||||
className="hover:text-gray-500 transition ease-in-out duration-150 flex items-center focus:outline-none"
|
||||
>
|
||||
<Cross className="h-6 w-6" />
|
||||
<span className="ml-2 text-accent-7 text-xs hover:text-gray-500">
|
||||
Close
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
@ -62,7 +66,7 @@ const CartSidebarView: FC = () => {
|
||||
<h2 className="pt-6 text-2xl font-bold tracking-wide text-center">
|
||||
Your cart is empty
|
||||
</h2>
|
||||
<p className="text-accents-3 px-10 text-center pt-2">
|
||||
<p className="text-accent-3 px-10 text-center pt-2">
|
||||
Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake.
|
||||
</p>
|
||||
</div>
|
||||
@ -90,13 +94,13 @@ const CartSidebarView: FC = () => {
|
||||
<div className="px-4 sm:px-6 flex-1">
|
||||
<Link href="/cart">
|
||||
<h2
|
||||
className="pt-1 pb-4 text-2xl leading-7 font-bold text-base tracking-wide cursor-pointer inline-block"
|
||||
className="pt-1 pb-8 text-2xl font-semibold tracking-wide cursor-pointer inline-block"
|
||||
onClick={handleClose}
|
||||
>
|
||||
My Cart
|
||||
</h2>
|
||||
</Link>
|
||||
<ul className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-accents-3 border-t border-accents-3">
|
||||
<ul className="py-4 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-accent-3 border-accent-3">
|
||||
{data!.lineItems.map((item: any) => (
|
||||
<CartItem
|
||||
key={item.id}
|
||||
@ -107,9 +111,8 @@ const CartSidebarView: FC = () => {
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="flex-shrink-0 px-4 py-5 sm:px-6">
|
||||
<div className="border-t border-accents-3">
|
||||
<ul className="py-3">
|
||||
<div className="flex-shrink-0 px-6 py-6 sm:px-6 sticky z-20 bottom-0 w-full right-0 left-0 bg-accent-0 shadow-outline-normal text-sm">
|
||||
<ul className="pb-2">
|
||||
<li className="flex justify-between py-1">
|
||||
<span>Subtotal</span>
|
||||
<span>{subTotal}</span>
|
||||
@ -119,18 +122,30 @@ const CartSidebarView: FC = () => {
|
||||
<span>Calculated at checkout</span>
|
||||
</li>
|
||||
<li className="flex justify-between py-1">
|
||||
<span>Estimated Shipping</span>
|
||||
<span>Shipping</span>
|
||||
<span className="font-bold tracking-wide">FREE</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="flex justify-between border-t border-accents-3 py-3 font-bold mb-10">
|
||||
<div className="flex justify-between border-t border-accent-3 py-3 font-bold mb-2">
|
||||
<span>Total</span>
|
||||
<span>{total}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{process.env.COMMERCE_CHECKOUT_ENABLED ? (
|
||||
<Button
|
||||
Component="a"
|
||||
width="100%"
|
||||
variant="ghost"
|
||||
onClick={goToCheckout}
|
||||
>
|
||||
Continue to Checkout
|
||||
</Button>
|
||||
) : (
|
||||
<Button href="/checkout" Component="a" width="100%">
|
||||
Proceed to Checkout
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
@ -0,0 +1,3 @@
|
||||
.root {
|
||||
@apply h-full flex flex-col relative w-full relative;
|
||||
}
|
190
components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx
Normal file
190
components/checkout/CheckoutSidebarView/CheckoutSidebarView.tsx
Normal file
@ -0,0 +1,190 @@
|
||||
import cn from 'classnames'
|
||||
import Link from 'next/link'
|
||||
import { FC } from 'react'
|
||||
import s from './CheckoutSidebarView.module.css'
|
||||
import CartItem from '@components/cart/CartItem'
|
||||
import { Button } from '@components/ui'
|
||||
import { UserNav } from '@components/common'
|
||||
import { useUI } from '@components/ui/context'
|
||||
import {
|
||||
Bag,
|
||||
Cross,
|
||||
Check,
|
||||
MapPin,
|
||||
CreditCard,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
} from '@components/icons'
|
||||
import useCart from '@framework/cart/use-cart'
|
||||
import usePrice from '@framework/product/use-price'
|
||||
|
||||
const CheckoutSidebarView: FC = () => {
|
||||
const { closeSidebar, setSidebarView } = useUI()
|
||||
const { data, isLoading, isEmpty } = useCart()
|
||||
|
||||
const { price: subTotal } = usePrice(
|
||||
data && {
|
||||
amount: Number(data.subtotalPrice),
|
||||
currencyCode: data.currency.code,
|
||||
}
|
||||
)
|
||||
const { price: total } = usePrice(
|
||||
data && {
|
||||
amount: Number(data.totalPrice),
|
||||
currencyCode: data.currency.code,
|
||||
}
|
||||
)
|
||||
const handleClose = () => closeSidebar()
|
||||
|
||||
const error = null
|
||||
const success = null
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(s.root, {
|
||||
[s.empty]: error || success || isLoading || isEmpty,
|
||||
})}
|
||||
>
|
||||
<header className="px-4 pt-6 pb-4 sm:px-6">
|
||||
<div className="flex items-start justify-between space-x-3">
|
||||
<div className="h-7 flex items-center">
|
||||
<button
|
||||
onClick={() => setSidebarView('CART_VIEW')}
|
||||
aria-label="Close panel"
|
||||
className="hover:text-gray-500 transition ease-in-out duration-150 flex items-center focus:outline-none"
|
||||
>
|
||||
<ChevronLeft className="h-6 w-6" />
|
||||
<span className="ml-2 text-accent-7 text-xs hover:text-gray-500">
|
||||
Back
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<UserNav />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{isLoading || isEmpty ? (
|
||||
<div className="flex-1 px-4 flex flex-col justify-center items-center">
|
||||
<span className="border border-dashed border-primary rounded-full flex items-center justify-center w-16 h-16 p-12 bg-secondary text-secondary">
|
||||
<Bag className="absolute" />
|
||||
</span>
|
||||
<h2 className="pt-6 text-2xl font-bold tracking-wide text-center">
|
||||
Your cart is empty
|
||||
</h2>
|
||||
<p className="text-accent-3 px-10 text-center pt-2">
|
||||
Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake.
|
||||
</p>
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="flex-1 px-4 flex flex-col justify-center items-center">
|
||||
<span className="border border-white rounded-full flex items-center justify-center w-16 h-16">
|
||||
<Cross width={24} height={24} />
|
||||
</span>
|
||||
<h2 className="pt-6 text-xl font-light text-center">
|
||||
We couldn’t process the purchase. Please check your card information
|
||||
and try again.
|
||||
</h2>
|
||||
</div>
|
||||
) : success ? (
|
||||
<div className="flex-1 px-4 flex flex-col justify-center items-center">
|
||||
<span className="border border-white rounded-full flex items-center justify-center w-16 h-16">
|
||||
<Check />
|
||||
</span>
|
||||
<h2 className="pt-6 text-xl font-light text-center">
|
||||
Thank you for your order.
|
||||
</h2>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="px-4 sm:px-6 flex-1">
|
||||
<Link href="/cart">
|
||||
<h2 className="pt-1 pb-8 text-2xl font-semibold tracking-wide cursor-pointer inline-block">
|
||||
Checkout
|
||||
</h2>
|
||||
</Link>
|
||||
|
||||
{/* Payment Method */}
|
||||
{/* Only available with checkout set to true - Meaning that the provider does offer checkout functionality. */}
|
||||
<div
|
||||
onClick={() => setSidebarView('PAYMENT_VIEW')}
|
||||
className="border border-accent-2 px-6 py-5 mb-4 text-center flex items-center cursor-pointer hover:border-accent-4"
|
||||
>
|
||||
<div className="flex flex-1 items-center">
|
||||
<CreditCard className="w-5 flex" />
|
||||
<span className="ml-5 text-sm text-center font-medium">
|
||||
Add Payment Method
|
||||
</span>
|
||||
{/* <span>VISA #### #### #### 2345</span> */}
|
||||
</div>
|
||||
<div>
|
||||
<ChevronRight />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Shipping Address */}
|
||||
{/* Only available with checkout set to true - Meaning that the provider does offer checkout functionality. */}
|
||||
<div
|
||||
onClick={() => setSidebarView('SHIPPING_VIEW')}
|
||||
className="border border-accent-2 px-6 py-5 mb-4 text-center flex items-center cursor-pointer hover:border-accent-4"
|
||||
>
|
||||
<div className="flex flex-1 items-center">
|
||||
<MapPin className="w-5 flex" />
|
||||
<span className="ml-5 text-sm text-center font-medium">
|
||||
Add Shipping Address
|
||||
</span>
|
||||
{/* <span>
|
||||
1046 Kearny Street.<br/>
|
||||
San Franssisco, California
|
||||
</span> */}
|
||||
</div>
|
||||
<div>
|
||||
<ChevronRight />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul className="py-4 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-accent-3 border-accent-3">
|
||||
{data!.lineItems.map((item: any) => (
|
||||
<CartItem
|
||||
key={item.id}
|
||||
item={item}
|
||||
currencyCode={data!.currency.code}
|
||||
noEdit
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="flex-shrink-0 px-6 py-6 sm:px-6 sticky z-20 bottom-0 w-full right-0 left-0 bg-accent-0 shadow-outline-normal text-sm">
|
||||
<ul className="pb-2">
|
||||
<li className="flex justify-between py-1">
|
||||
<span>Subtotal</span>
|
||||
<span>{subTotal}</span>
|
||||
</li>
|
||||
<li className="flex justify-between py-1">
|
||||
<span>Taxes</span>
|
||||
<span>Calculated at checkout</span>
|
||||
</li>
|
||||
<li className="flex justify-between py-1">
|
||||
<span>Shipping</span>
|
||||
<span className="font-bold tracking-wide">FREE</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="flex justify-between border-t border-accent-3 py-3 font-bold mb-2">
|
||||
<span>Total</span>
|
||||
<span>{total}</span>
|
||||
</div>
|
||||
<div>
|
||||
<Button href="/checkout" Component="a" width="100%">
|
||||
Confirm Purchase
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CheckoutSidebarView
|
1
components/checkout/CheckoutSidebarView/index.ts
Normal file
1
components/checkout/CheckoutSidebarView/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './CheckoutSidebarView'
|
@ -0,0 +1,21 @@
|
||||
.root {
|
||||
@apply h-full flex flex-col relative w-full relative;
|
||||
}
|
||||
|
||||
.fieldset {
|
||||
@apply flex flex-col my-3;
|
||||
}
|
||||
|
||||
.fieldset .label {
|
||||
@apply text-accent-7 uppercase text-xs font-medium mb-2;
|
||||
}
|
||||
|
||||
.fieldset .input,
|
||||
.fieldset .select {
|
||||
@apply p-2 border border-accent-3 w-full text-sm font-normal;
|
||||
}
|
||||
|
||||
.fieldset .input:focus,
|
||||
.fieldset .select:focus {
|
||||
@apply outline-none shadow-outline-normal;
|
||||
}
|
106
components/checkout/PaymentMethodView/PaymentMethodView.tsx
Normal file
106
components/checkout/PaymentMethodView/PaymentMethodView.tsx
Normal file
@ -0,0 +1,106 @@
|
||||
import { FC } from 'react'
|
||||
import s from './PaymentMethodView.module.css'
|
||||
import { ChevronLeft } from '@components/icons'
|
||||
import { UserNav } from '@components/common'
|
||||
import { useUI } from '@components/ui/context'
|
||||
import Button from '@components/ui/Button'
|
||||
import cn from 'classnames'
|
||||
|
||||
const PaymentMethodView: FC = () => {
|
||||
const { setSidebarView } = useUI()
|
||||
|
||||
return (
|
||||
<div className={s.root}>
|
||||
<header className="px-4 pt-6 pb-4 sm:px-6">
|
||||
<div className="flex items-start justify-between space-x-3">
|
||||
<div className="h-7 flex items-center">
|
||||
<button
|
||||
onClick={() => setSidebarView('CHECKOUT_VIEW')}
|
||||
aria-label="Close panel"
|
||||
className="hover:text-gray-500 transition ease-in-out duration-150 flex items-center focus:outline-none"
|
||||
>
|
||||
<ChevronLeft className="h-6 w-6" />
|
||||
<span className="ml-2 text-accent-7 text-xs hover:text-gray-500">
|
||||
Back
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<UserNav />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div className="px-4 sm:px-6 flex-1">
|
||||
<h2 className="pt-1 pb-6 text-2xl font-semibold tracking-wide cursor-pointer inline-block">
|
||||
Payment Method
|
||||
</h2>
|
||||
<div>
|
||||
<div className={s.fieldset}>
|
||||
<label className={s.label}>Cardholder Name</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
<div className="grid gap-3 grid-flow-row grid-cols-12">
|
||||
<div className={cn(s.fieldset, 'col-span-7')}>
|
||||
<label className={s.label}>Card Number</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
<div className={cn(s.fieldset, 'col-span-3')}>
|
||||
<label className={s.label}>Expires</label>
|
||||
<input className={s.input} placeholder="MM/YY" />
|
||||
</div>
|
||||
<div className={cn(s.fieldset, 'col-span-2')}>
|
||||
<label className={s.label}>CVC</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
</div>
|
||||
<hr className="border-accent-3 my-6" />
|
||||
<div className="grid gap-3 grid-flow-row grid-cols-12">
|
||||
<div className={cn(s.fieldset, 'col-span-6')}>
|
||||
<label className={s.label}>First Name</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
<div className={cn(s.fieldset, 'col-span-6')}>
|
||||
<label className={s.label}>Last Name</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.fieldset}>
|
||||
<label className={s.label}>Company (Optional)</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
<div className={s.fieldset}>
|
||||
<label className={s.label}>Street and House Number</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
<div className={s.fieldset}>
|
||||
<label className={s.label}>Apartment, Suite, Etc. (Optional)</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
<div className="grid gap-3 grid-flow-row grid-cols-12">
|
||||
<div className={cn(s.fieldset, 'col-span-6')}>
|
||||
<label className={s.label}>Postal Code</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
<div className={cn(s.fieldset, 'col-span-6')}>
|
||||
<label className={s.label}>City</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.fieldset}>
|
||||
<label className={s.label}>Country/Region</label>
|
||||
<select className={s.select}>
|
||||
<option>Hong Kong</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="mt-10 sticky z-20 bottom-0 w-full right-0 left-0 ">
|
||||
<Button Component="a" width="100%" variant="ghost">
|
||||
Continue
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PaymentMethodView
|
1
components/checkout/PaymentMethodView/index.ts
Normal file
1
components/checkout/PaymentMethodView/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './PaymentMethodView'
|
12
components/checkout/README.md
Normal file
12
components/checkout/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Checkout
|
||||
|
||||
Checkout is only enabled in those providers that specify Custom Checkout to be enabled.
|
||||
|
||||
This feature enables:
|
||||
|
||||
- Shipping
|
||||
- Payment
|
||||
|
||||
```
|
||||
COMMERCE_CHECKOUT_ENABLED
|
||||
```
|
25
components/checkout/ShippingView/ShippingView.module.css
Normal file
25
components/checkout/ShippingView/ShippingView.module.css
Normal file
@ -0,0 +1,25 @@
|
||||
.root {
|
||||
@apply h-full flex flex-col relative w-full relative;
|
||||
}
|
||||
|
||||
.fieldset {
|
||||
@apply flex flex-col my-3;
|
||||
}
|
||||
|
||||
.fieldset .label {
|
||||
@apply text-accent-7 uppercase text-xs font-medium mb-2;
|
||||
}
|
||||
|
||||
.fieldset .input,
|
||||
.fieldset .select {
|
||||
@apply p-2 border border-accent-3 w-full text-sm font-normal;
|
||||
}
|
||||
|
||||
.fieldset .input:focus,
|
||||
.fieldset .select:focus {
|
||||
@apply outline-none shadow-outline-normal;
|
||||
}
|
||||
|
||||
.radio {
|
||||
@apply bg-black;
|
||||
}
|
98
components/checkout/ShippingView/ShippingView.tsx
Normal file
98
components/checkout/ShippingView/ShippingView.tsx
Normal file
@ -0,0 +1,98 @@
|
||||
import { FC } from 'react'
|
||||
import s from './ShippingView.module.css'
|
||||
import { ChevronLeft } from '@components/icons'
|
||||
import { UserNav } from '@components/common'
|
||||
import { useUI } from '@components/ui/context'
|
||||
import Button from '@components/ui/Button'
|
||||
import cn from 'classnames'
|
||||
|
||||
const PaymentMethodView: FC = () => {
|
||||
const { setSidebarView } = useUI()
|
||||
|
||||
return (
|
||||
<div className={s.root}>
|
||||
<header className="px-4 pt-6 pb-4 sm:px-6">
|
||||
<div className="flex items-start justify-between space-x-3">
|
||||
<div className="h-7 flex items-center">
|
||||
<button
|
||||
onClick={() => setSidebarView('CHECKOUT_VIEW')}
|
||||
aria-label="Close panel"
|
||||
className="hover:text-gray-500 transition ease-in-out duration-150 flex items-center focus:outline-none"
|
||||
>
|
||||
<ChevronLeft className="h-6 w-6" />
|
||||
<span className="ml-2 text-accent-7 text-xs hover:text-gray-500">
|
||||
Back
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<UserNav />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div className="px-4 sm:px-6 flex-1">
|
||||
<h2 className="pt-1 pb-8 text-2xl font-semibold tracking-wide cursor-pointer inline-block">
|
||||
Shipping
|
||||
</h2>
|
||||
<div>
|
||||
<div className="flex flex-row my-3 items-center">
|
||||
<input className={s.radio} type="radio" />
|
||||
<span className="ml-3 text-sm">Same as billing address</span>
|
||||
</div>
|
||||
<div className="flex flex-row my-3 items-center">
|
||||
<input className={s.radio} type="radio" />
|
||||
<span className="ml-3 text-sm">
|
||||
Use a different shipping address
|
||||
</span>
|
||||
</div>
|
||||
<hr className="border-accent-3 my-6" />
|
||||
<div className="grid gap-3 grid-flow-row grid-cols-12">
|
||||
<div className={cn(s.fieldset, 'col-span-6')}>
|
||||
<label className={s.label}>First Name</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
<div className={cn(s.fieldset, 'col-span-6')}>
|
||||
<label className={s.label}>Last Name</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.fieldset}>
|
||||
<label className={s.label}>Company (Optional)</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
<div className={s.fieldset}>
|
||||
<label className={s.label}>Street and House Number</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
<div className={s.fieldset}>
|
||||
<label className={s.label}>Apartment, Suite, Etc. (Optional)</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
<div className="grid gap-3 grid-flow-row grid-cols-12">
|
||||
<div className={cn(s.fieldset, 'col-span-6')}>
|
||||
<label className={s.label}>Postal Code</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
<div className={cn(s.fieldset, 'col-span-6')}>
|
||||
<label className={s.label}>City</label>
|
||||
<input className={s.input} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.fieldset}>
|
||||
<label className={s.label}>Country/Region</label>
|
||||
<select className={s.select}>
|
||||
<option>Hong Kong</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-10 sticky z-20 bottom-0 w-full right-0 left-0 p-6">
|
||||
<Button href="/checkout" Component="a" width="100%" variant="ghost">
|
||||
Continue
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PaymentMethodView
|
1
components/checkout/ShippingView/index.ts
Normal file
1
components/checkout/ShippingView/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './ShippingView'
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ const Footer: FC<Props> = ({ className, pages }) => {
|
||||
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">
|
||||
@ -39,15 +39,29 @@ const Footer: FC<Props> = ({ className, pages }) => {
|
||||
<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">
|
||||
<a className="text-primary hover:text-accent-6 transition ease-in-out duration-150">
|
||||
Home
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li className="py-3 md:py-0 md:pb-4">
|
||||
<Link href="/">
|
||||
<a className="text-primary hover:text-accent-6 transition ease-in-out duration-150">
|
||||
Careers
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li className="py-3 md:py-0 md:pb-4">
|
||||
<Link href="/blog">
|
||||
<a className="text-primary hover:text-accent-6 transition ease-in-out duration-150">
|
||||
Blog
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
{sitePages.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">
|
||||
<a className="text-primary hover:text-accent-6 transition ease-in-out duration-150">
|
||||
{page.name}
|
||||
</a>
|
||||
</Link>
|
||||
@ -60,7 +74,7 @@ const Footer: FC<Props> = ({ className, pages }) => {
|
||||
{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">
|
||||
<a className="text-primary hover:text-accent-6 transition ease-in-out duration-150">
|
||||
{page.name}
|
||||
</a>
|
||||
</Link>
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
@apply border-accents-4 shadow-sm;
|
||||
@apply border-accent-4 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,7 +34,7 @@
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
@apply bg-accents-1;
|
||||
@apply bg-accent-1;
|
||||
}
|
||||
|
||||
.icon {
|
||||
|
@ -8,6 +8,9 @@ import { Navbar, Footer } from '@components/common'
|
||||
import { useAcceptCookies } from '@lib/hooks/useAcceptCookies'
|
||||
import { Sidebar, Button, Modal, LoadingDots } from '@components/ui'
|
||||
import CartSidebarView from '@components/cart/CartSidebarView'
|
||||
import CheckoutSidebarView from '@components/checkout/CheckoutSidebarView'
|
||||
import PaymentMethodView from '@components/checkout/PaymentMethodView'
|
||||
import ShippingView from '@components/checkout/ShippingView'
|
||||
|
||||
import LoginView from '@components/auth/LoginView'
|
||||
import { CommerceProvider } from '@framework'
|
||||
@ -55,6 +58,7 @@ const Layout: FC<Props> = ({
|
||||
closeSidebar,
|
||||
closeModal,
|
||||
modalView,
|
||||
sidebarView,
|
||||
} = useUI()
|
||||
const { acceptedCookies, onAcceptCookies } = useAcceptCookies()
|
||||
const { locale = 'en-US' } = useRouter()
|
||||
@ -72,7 +76,10 @@ const Layout: FC<Props> = ({
|
||||
</Modal>
|
||||
|
||||
<Sidebar open={displaySidebar} onClose={closeSidebar}>
|
||||
<CartSidebarView />
|
||||
{sidebarView === 'CART_VIEW' && <CartSidebarView />}
|
||||
{sidebarView === 'CHECKOUT_VIEW' && <CheckoutSidebarView />}
|
||||
{sidebarView === 'PAYMENT_VIEW' && <PaymentMethodView />}
|
||||
{sidebarView === 'SHIPPING_VIEW' && <ShippingView />}
|
||||
</Sidebar>
|
||||
|
||||
<FeatureBar
|
||||
|
@ -3,15 +3,15 @@
|
||||
}
|
||||
|
||||
.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 text-primary leading-6 font-medium transition ease-in-out duration-75 cursor-pointer text-accent-6;
|
||||
}
|
||||
|
||||
.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 {
|
||||
|
@ -19,7 +19,7 @@ const Searchbar: FC<Props> = ({ className, id = 'search' }) => {
|
||||
() => (
|
||||
<div
|
||||
className={cn(
|
||||
'relative text-sm bg-accents-1 text-base w-full transition-colors duration-150',
|
||||
'relative text-sm bg-accent-1 text-base w-full transition-colors duration-150',
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
20
components/icons/ChevronLeft.tsx
Normal file
20
components/icons/ChevronLeft.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
const ChevronUp = ({ ...props }) => {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
fill="none"
|
||||
shapeRendering="geometricPrecision"
|
||||
{...props}
|
||||
>
|
||||
<path d="M15 18l-6-6 6-6" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChevronUp
|
20
components/icons/ChevronRight.tsx
Normal file
20
components/icons/ChevronRight.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
const ChevronUp = ({ ...props }) => {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
fill="none"
|
||||
shapeRendering="geometricPrecision"
|
||||
{...props}
|
||||
>
|
||||
<path d="M9 18l6-6-6-6" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChevronUp
|
@ -10,6 +10,7 @@ const CreditCard = ({ ...props }) => {
|
||||
strokeLinejoin="round"
|
||||
fill="none"
|
||||
shapeRendering="geometricPrecision"
|
||||
{...props}
|
||||
>
|
||||
<rect x="1" y="4" width="22" height="16" rx="2" ry="2" />
|
||||
<path d="M1 10h22" />
|
||||
|
@ -9,10 +9,12 @@ 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 DoubleChevron } from './DoubleChevron'
|
||||
export { default as RightArrow } from './RightArrow'
|
||||
export { default as Info } from './Info'
|
||||
export { default as ChevronUp } from './ChevronUp'
|
||||
export { default as Vercel } from './Vercel'
|
||||
export { default as MapPin } from './MapPin'
|
||||
export { default as CreditCard } from './CreditCard'
|
||||
export { default as ChevronUp } from './ChevronUp'
|
||||
export { default as ChevronLeft } from './ChevronLeft'
|
||||
export { default as ChevronRight } from './ChevronRight'
|
||||
export { default as DoubleChevron } from './DoubleChevron'
|
||||
|
@ -81,7 +81,7 @@
|
||||
|
||||
.simple {
|
||||
& .squareBg {
|
||||
@apply bg-accents-0 !important;
|
||||
@apply bg-accent-0 !important;
|
||||
background-image: url('/bg-products.svg');
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,6 @@
|
||||
|
||||
.active {
|
||||
&.size {
|
||||
@apply border-accents-9 border-2;
|
||||
@apply border-accent-9 border-2;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
.root {
|
||||
@apply bg-secondary text-accents-1 cursor-pointer inline-flex px-10 rounded-sm leading-6 transition ease-in-out duration-150 shadow-sm font-semibold text-center justify-center uppercase py-4 border border-transparent items-center;
|
||||
@apply bg-secondary text-accent-1 cursor-pointer inline-flex
|
||||
px-10 rounded-sm leading-6 transition ease-in-out duration-150
|
||||
shadow-sm font-semibold text-center justify-center uppercase
|
||||
py-4 border border-transparent items-center;
|
||||
}
|
||||
|
||||
.root:hover {
|
||||
@apply bg-accents-0 text-primary border border-secondary;
|
||||
@apply bg-accent-0 text-primary border border-secondary;
|
||||
}
|
||||
|
||||
.root:focus {
|
||||
@ -15,16 +18,20 @@
|
||||
}
|
||||
|
||||
.loading {
|
||||
@apply bg-accents-1 text-accents-3 border-accents-2 cursor-not-allowed;
|
||||
@apply bg-accent-1 text-accent-3 border-accent-2 cursor-not-allowed;
|
||||
}
|
||||
|
||||
.slim {
|
||||
@apply py-2 transform-none normal-case;
|
||||
}
|
||||
|
||||
.ghost {
|
||||
@apply border border-accent-3 bg-accent-0 text-accent-9 text-sm;
|
||||
}
|
||||
|
||||
.disabled,
|
||||
.disabled:hover {
|
||||
@apply text-accents-4 border-accents-2 bg-accents-1 cursor-not-allowed;
|
||||
@apply text-accent-4 border-accent-2 bg-accent-1 cursor-not-allowed;
|
||||
filter: grayscale(1);
|
||||
-webkit-transform: translateZ(0);
|
||||
-webkit-perspective: 1000;
|
||||
|
@ -12,7 +12,7 @@ import { LoadingDots } from '@components/ui'
|
||||
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
href?: string
|
||||
className?: string
|
||||
variant?: 'flat' | 'slim'
|
||||
variant?: 'flat' | 'slim' | 'ghost'
|
||||
active?: boolean
|
||||
type?: 'submit' | 'reset' | 'button'
|
||||
Component?: string | JSXElementConstructor<any>
|
||||
@ -39,6 +39,7 @@ const Button: React.FC<ButtonProps> = forwardRef((props, buttonRef) => {
|
||||
const rootClassName = cn(
|
||||
s.root,
|
||||
{
|
||||
[s.ghost]: variant === 'ghost',
|
||||
[s.slim]: variant === 'slim',
|
||||
[s.loading]: loading,
|
||||
[s.disabled]: disabled,
|
||||
|
@ -3,6 +3,10 @@
|
||||
@apply grid grid-cols-1 gap-0;
|
||||
min-height: var(--row-height);
|
||||
|
||||
@screen lg {
|
||||
@apply grid-cols-3 grid-rows-2;
|
||||
}
|
||||
|
||||
& > * {
|
||||
@apply row-span-1 bg-transparent box-border overflow-hidden;
|
||||
height: 500px;
|
||||
@ -15,17 +19,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
@screen lg {
|
||||
.root {
|
||||
@apply grid-cols-3 grid-rows-2;
|
||||
}
|
||||
|
||||
.root & > * {
|
||||
@apply col-span-1;
|
||||
height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.default {
|
||||
& > * {
|
||||
@apply bg-transparent;
|
||||
|
@ -1,9 +1,6 @@
|
||||
.root {
|
||||
@apply mx-auto grid grid-cols-1 py-32 gap-4;
|
||||
}
|
||||
|
||||
@screen md {
|
||||
.root {
|
||||
@screen md {
|
||||
@apply grid-cols-2;
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ const Hero: FC<Props> = ({ headline, description }) => {
|
||||
<p className="mt-5 text-xl leading-7 text-accent-2 text-white">
|
||||
{description}
|
||||
</p>
|
||||
<Link href="/">
|
||||
<Link href="/blog">
|
||||
<a className="text-white pt-3 font-bold hover:underline flex flex-row cursor-pointer w-max-content">
|
||||
Read it here
|
||||
<RightArrow width="20" heigh="20" className="ml-1" />
|
||||
|
@ -1,5 +1,5 @@
|
||||
.root {
|
||||
@apply bg-primary py-2 px-6 w-full appearance-none transition duration-150 ease-in-out pr-10 border border-accents-3 text-accents-6;
|
||||
@apply bg-primary py-2 px-6 w-full appearance-none transition duration-150 ease-in-out pr-10 border border-accent-3 text-accent-6;
|
||||
}
|
||||
|
||||
.root:focus {
|
||||
|
@ -2,7 +2,7 @@
|
||||
@apply inline-flex text-center items-center leading-7;
|
||||
|
||||
& span {
|
||||
@apply bg-accents-6 rounded-full h-2 w-2;
|
||||
@apply bg-accent-6 rounded-full h-2 w-2;
|
||||
animation-name: blink;
|
||||
animation-duration: 1.4s;
|
||||
animation-iteration-count: infinite;
|
||||
|
@ -4,7 +4,7 @@
|
||||
}
|
||||
|
||||
.modal {
|
||||
@apply bg-primary p-12 border border-accents-2 relative;
|
||||
@apply bg-primary p-12 border border-accent-2 relative;
|
||||
}
|
||||
|
||||
.modal:focus {
|
||||
|
@ -40,7 +40,7 @@ const Sidebar: FC<Props> = ({ children, open = false, onClose }) => {
|
||||
/>
|
||||
<section className="absolute inset-y-0 right-0 pl-10 max-w-full flex sm:pl-16 outline-none">
|
||||
<div className="h-full md:w-screen md:max-w-md">
|
||||
<div className="h-full flex flex-col text-base bg-accents-1 shadow-xl overflow-y-auto">
|
||||
<div className="h-full flex flex-col text-base bg-accent-0 shadow-xl overflow-y-auto">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -2,10 +2,10 @@
|
||||
@apply block;
|
||||
background-image: linear-gradient(
|
||||
270deg,
|
||||
var(--accents-1),
|
||||
var(--accents-2),
|
||||
var(--accents-2),
|
||||
var(--accents-1)
|
||||
var(--accent-1),
|
||||
var(--accent-2),
|
||||
var(--accent-2),
|
||||
var(--accent-1)
|
||||
);
|
||||
background-size: 400% 100%;
|
||||
animation: loading 8s ease-in-out infinite;
|
||||
@ -28,10 +28,10 @@
|
||||
z-index: 100;
|
||||
background-image: linear-gradient(
|
||||
270deg,
|
||||
var(--accents-1),
|
||||
var(--accents-2),
|
||||
var(--accents-2),
|
||||
var(--accents-1)
|
||||
var(--accent-1),
|
||||
var(--accent-2),
|
||||
var(--accent-2),
|
||||
var(--accent-1)
|
||||
);
|
||||
background-size: 400% 100%;
|
||||
animation: loading 8s ease-in-out infinite;
|
||||
|
@ -1,5 +1,5 @@
|
||||
.body {
|
||||
@apply text-lg leading-7 font-medium max-w-6xl mx-auto;
|
||||
@apply text-base leading-7 max-w-6xl mx-auto;
|
||||
}
|
||||
|
||||
.heading {
|
||||
@ -11,5 +11,5 @@
|
||||
}
|
||||
|
||||
.sectionHeading {
|
||||
@apply pt-1 pb-2 font-semibold leading-7 tracking-wider uppercase border-b border-accents-2 mb-3;
|
||||
@apply pt-1 pb-2 font-semibold leading-7 tracking-wider uppercase border-b border-accent-2 mb-3;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ export interface State {
|
||||
displayModal: boolean
|
||||
displayToast: boolean
|
||||
modalView: string
|
||||
sidebarView: string
|
||||
toastText: string
|
||||
userAvatar: string
|
||||
}
|
||||
@ -16,6 +17,7 @@ const initialState = {
|
||||
displayDropdown: false,
|
||||
displayModal: false,
|
||||
modalView: 'LOGIN_VIEW',
|
||||
sidebarView: 'CART_VIEW',
|
||||
displayToast: false,
|
||||
toastText: '',
|
||||
userAvatar: '',
|
||||
@ -54,6 +56,10 @@ type Action =
|
||||
type: 'SET_MODAL_VIEW'
|
||||
view: MODAL_VIEWS
|
||||
}
|
||||
| {
|
||||
type: 'SET_SIDEBAR_VIEW'
|
||||
view: SIDEBAR_VIEWS
|
||||
}
|
||||
| {
|
||||
type: 'SET_USER_AVATAR'
|
||||
value: string
|
||||
@ -65,6 +71,9 @@ type MODAL_VIEWS =
|
||||
| 'FORGOT_VIEW'
|
||||
| 'NEW_SHIPPING_ADDRESS'
|
||||
| 'NEW_PAYMENT_METHOD'
|
||||
|
||||
type SIDEBAR_VIEWS = 'CART_VIEW' | 'CHECKOUT_VIEW' | 'PAYMENT_METHOD_VIEW'
|
||||
|
||||
type ToastText = string
|
||||
|
||||
export const UIContext = React.createContext<State | any>(initialState)
|
||||
@ -128,6 +137,12 @@ function uiReducer(state: State, action: Action) {
|
||||
modalView: action.view,
|
||||
}
|
||||
}
|
||||
case 'SET_SIDEBAR_VIEW': {
|
||||
return {
|
||||
...state,
|
||||
sidebarView: action.view,
|
||||
}
|
||||
}
|
||||
case 'SET_TOAST_TEXT': {
|
||||
return {
|
||||
...state,
|
||||
@ -170,6 +185,9 @@ export const UIProvider: FC = (props) => {
|
||||
const setModalView = (view: MODAL_VIEWS) =>
|
||||
dispatch({ type: 'SET_MODAL_VIEW', view })
|
||||
|
||||
const setSidebarView = (view: SIDEBAR_VIEWS) =>
|
||||
dispatch({ type: 'SET_SIDEBAR_VIEW', view })
|
||||
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
...state,
|
||||
@ -182,6 +200,7 @@ export const UIProvider: FC = (props) => {
|
||||
openModal,
|
||||
closeModal,
|
||||
setModalView,
|
||||
setSidebarView,
|
||||
openToast,
|
||||
closeToast,
|
||||
setUserAvatar,
|
||||
|
@ -1,5 +1,5 @@
|
||||
.root {
|
||||
@apply grid grid-cols-12 w-full gap-6 px-3 py-6 border-b border-accents-2 transition duration-100 ease-in-out;
|
||||
@apply grid 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 {
|
||||
|
@ -9,6 +9,7 @@ const fetchGraphqlApi: GraphQLFetcher = async (
|
||||
{ variables } = {},
|
||||
fetchOptions
|
||||
) => {
|
||||
try {
|
||||
const res = await fetch(API_URL, {
|
||||
...fetchOptions,
|
||||
method: 'POST',
|
||||
@ -30,5 +31,15 @@ const fetchGraphqlApi: GraphQLFetcher = async (
|
||||
}
|
||||
|
||||
return { data, res }
|
||||
} catch (err) {
|
||||
throw getError(
|
||||
[
|
||||
{
|
||||
message: `${err} \n Most likely related to an unexpected output. e.g the store might be protected with password or not available.`,
|
||||
},
|
||||
],
|
||||
500
|
||||
)
|
||||
}
|
||||
}
|
||||
export default fetchGraphqlApi
|
||||
|
@ -10,15 +10,11 @@ export const handler: SWRHook<Customer | null> = {
|
||||
query: getCustomerQuery,
|
||||
},
|
||||
async fetcher({ options, fetch }) {
|
||||
const customerAccessToken = getCustomerToken()
|
||||
if (customerAccessToken) {
|
||||
const data = await fetch({
|
||||
const data = await fetch<any | null>({
|
||||
...options,
|
||||
variables: { customerAccessToken: getCustomerToken() },
|
||||
})
|
||||
return data.customer
|
||||
}
|
||||
return null
|
||||
return data.customer ?? null
|
||||
},
|
||||
useHook: ({ useData }) => (input) => {
|
||||
return useData({
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { Product } from '@commerce/types'
|
||||
import { getConfig, ShopifyConfig } from '../api'
|
||||
import fetchAllProducts from '../api/utils/fetch-all-products'
|
||||
import { ProductEdge } from '../schema'
|
||||
import getAllProductsPathsQuery from '../utils/queries/get-all-products-paths-query'
|
||||
|
||||
@ -19,22 +21,21 @@ const getAllProductPaths = async (options?: {
|
||||
config?: ShopifyConfig
|
||||
preview?: boolean
|
||||
}): Promise<ReturnType> => {
|
||||
let { config, variables = { first: 100, sortKey: 'BEST_SELLING' } } =
|
||||
options ?? {}
|
||||
let { config, variables = { first: 250 } } = options ?? {}
|
||||
config = getConfig(config)
|
||||
|
||||
const { data } = await config.fetch(getAllProductsPathsQuery, {
|
||||
const products = await fetchAllProducts({
|
||||
config,
|
||||
query: getAllProductsPathsQuery,
|
||||
variables,
|
||||
})
|
||||
|
||||
return {
|
||||
products: data.products?.edges?.map(
|
||||
({ node: { handle } }: ProductEdge) => ({
|
||||
products: products?.map(({ node: { handle } }: ProductEdge) => ({
|
||||
node: {
|
||||
path: `/${handle}`,
|
||||
},
|
||||
})
|
||||
),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,9 +27,10 @@ const getAllProducts = async (options: {
|
||||
{ variables }
|
||||
)
|
||||
|
||||
const products = data.products?.edges?.map(({ node: p }: ProductEdge) =>
|
||||
const products =
|
||||
data.products?.edges?.map(({ node: p }: ProductEdge) =>
|
||||
normalizeProduct(p)
|
||||
)
|
||||
) ?? []
|
||||
|
||||
return {
|
||||
products,
|
||||
|
@ -21,6 +21,7 @@ const getProduct = async (options: {
|
||||
const { data }: GraphQLFetcherResult = await config.fetch(getProductQuery, {
|
||||
variables,
|
||||
})
|
||||
|
||||
const { productByHandle } = data
|
||||
|
||||
return {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { FetcherError } from '@commerce/utils/errors'
|
||||
|
||||
export function getError(errors: any[], status: number) {
|
||||
export function getError(errors: any[] | null, status: number) {
|
||||
errors = errors ?? [{ message: 'Failed to fetch Shopify API' }]
|
||||
return new FetcherError({ errors, status })
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ const normalizeProductVariants = ({ edges }: ProductVariantConnection) => {
|
||||
name,
|
||||
values: [value],
|
||||
})
|
||||
|
||||
return options
|
||||
}),
|
||||
}
|
||||
@ -154,12 +155,6 @@ function normalizeLineItem({
|
||||
discounts: [],
|
||||
options:
|
||||
// By default Shopify adds a default variant with default names, we're removing it. https://community.shopify.com/c/Shopify-APIs-SDKs/Adding-new-product-variant-is-automatically-adding-quot-Default/td-p/358095
|
||||
variant?.title == 'Default Title'
|
||||
? []
|
||||
: [
|
||||
{
|
||||
value: variant?.title,
|
||||
},
|
||||
],
|
||||
variant?.title == 'Default Title' ? [] : variant?.selectedOptions,
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,10 @@ export const checkoutDetailsFragment = `
|
||||
id
|
||||
sku
|
||||
title
|
||||
selectedOptions {
|
||||
name
|
||||
value
|
||||
}
|
||||
image {
|
||||
originalSrc
|
||||
altText
|
||||
|
@ -48,7 +48,7 @@ export default function Cart() {
|
||||
<h2 className="pt-6 text-2xl font-bold tracking-wide text-center">
|
||||
Your cart is empty
|
||||
</h2>
|
||||
<p className="text-accents-6 px-10 text-center pt-2">
|
||||
<p className="text-accent-6 px-10 text-center pt-2">
|
||||
Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake.
|
||||
</p>
|
||||
</div>
|
||||
@ -75,7 +75,7 @@ export default function Cart() {
|
||||
<div className="px-4 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-accents-2 border-b border-accents-2">
|
||||
<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">
|
||||
{data!.lineItems.map((item) => (
|
||||
<CartItem
|
||||
key={item.id}
|
||||
@ -93,7 +93,7 @@ export default function Cart() {
|
||||
{[1, 2, 3, 4, 5, 6].map((x) => (
|
||||
<div
|
||||
key={x}
|
||||
className="border border-accents-3 w-full h-24 bg-accents-2 bg-opacity-50 transform cursor-pointer hover:scale-110 duration-75"
|
||||
className="border border-accent-3 w-full h-24 bg-accent-2 bg-opacity-50 transform cursor-pointer hover:scale-110 duration-75"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@ -107,7 +107,7 @@ export default function Cart() {
|
||||
<>
|
||||
{/* Shipping Address */}
|
||||
{/* Only available with customCheckout set to true - Meaning that the provider does offer checkout functionality. */}
|
||||
<div className="rounded-md border border-accents-2 px-6 py-6 mb-4 text-center flex items-center justify-center cursor-pointer hover:border-accents-4">
|
||||
<div className="rounded-md border border-accent-2 px-6 py-6 mb-4 text-center flex items-center justify-center cursor-pointer hover:border-accent-4">
|
||||
<div className="mr-5">
|
||||
<MapPin />
|
||||
</div>
|
||||
@ -121,7 +121,7 @@ export default function Cart() {
|
||||
</div>
|
||||
{/* Payment Method */}
|
||||
{/* Only available with customCheckout set to true - Meaning that the provider does offer checkout functionality. */}
|
||||
<div className="rounded-md border border-accents-2 px-6 py-6 mb-4 text-center flex items-center justify-center cursor-pointer hover:border-accents-4">
|
||||
<div className="rounded-md border border-accent-2 px-6 py-6 mb-4 text-center flex items-center justify-center cursor-pointer hover:border-accent-4">
|
||||
<div className="mr-5">
|
||||
<CreditCard />
|
||||
</div>
|
||||
@ -132,7 +132,7 @@ export default function Cart() {
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="border-t border-accents-2">
|
||||
<div className="border-t border-accent-2">
|
||||
<ul className="py-3">
|
||||
<li className="flex justify-between py-1">
|
||||
<span>Subtotal</span>
|
||||
@ -147,7 +147,7 @@ export default function Cart() {
|
||||
<span className="font-bold tracking-wide">FREE</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="flex justify-between border-t border-accents-2 py-3 font-bold mb-10">
|
||||
<div className="flex justify-between border-t border-accent-2 py-3 font-bold mb-10">
|
||||
<span>Total</span>
|
||||
<span>{total}</span>
|
||||
</div>
|
||||
|
@ -27,7 +27,7 @@ export default function Orders() {
|
||||
<h2 className="pt-6 text-2xl font-bold tracking-wide text-center">
|
||||
No orders found
|
||||
</h2>
|
||||
<p className="text-accents-6 px-10 text-center pt-2">
|
||||
<p className="text-accent-6 px-10 text-center pt-2">
|
||||
Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake.
|
||||
</p>
|
||||
</div>
|
||||
|
@ -48,7 +48,7 @@ export default function Wishlist() {
|
||||
<h2 className="pt-6 text-2xl font-bold tracking-wide text-center">
|
||||
Your wishlist is empty
|
||||
</h2>
|
||||
<p className="text-accents-6 px-10 text-center pt-2">
|
||||
<p className="text-accent-6 px-10 text-center pt-2">
|
||||
Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake.
|
||||
</p>
|
||||
</div>
|
||||
|
@ -27,16 +27,16 @@ module.exports = {
|
||||
hover: 'var(--hover)',
|
||||
'hover-1': 'var(--hover-1)',
|
||||
'hover-2': 'var(--hover-2)',
|
||||
'accents-0': 'var(--accents-0)',
|
||||
'accents-1': 'var(--accents-1)',
|
||||
'accents-2': 'var(--accents-2)',
|
||||
'accents-3': 'var(--accents-3)',
|
||||
'accents-4': 'var(--accents-4)',
|
||||
'accents-5': 'var(--accents-5)',
|
||||
'accents-6': 'var(--accents-6)',
|
||||
'accents-7': 'var(--accents-7)',
|
||||
'accents-8': 'var(--accents-8)',
|
||||
'accents-9': 'var(--accents-9)',
|
||||
'accent-0': 'var(--accent-0)',
|
||||
'accent-1': 'var(--accent-1)',
|
||||
'accent-2': 'var(--accent-2)',
|
||||
'accent-3': 'var(--accent-3)',
|
||||
'accent-4': 'var(--accent-4)',
|
||||
'accent-5': 'var(--accent-5)',
|
||||
'accent-6': 'var(--accent-6)',
|
||||
'accent-7': 'var(--accent-7)',
|
||||
'accent-8': 'var(--accent-8)',
|
||||
'accent-9': 'var(--accent-9)',
|
||||
violet: 'var(--violet)',
|
||||
'violet-light': 'var(--violet-light)',
|
||||
pink: 'var(--pink)',
|
||||
@ -51,7 +51,7 @@ module.exports = {
|
||||
secondary: 'var(--text-secondary)',
|
||||
},
|
||||
boxShadow: {
|
||||
'outline-normal': '0 0 0 2px var(--accents-2)',
|
||||
'outline-normal': '0 0 0 2px var(--accent-2)',
|
||||
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',
|
||||
},
|
||||
|
@ -22,8 +22,8 @@
|
||||
"@components/*": ["components/*"],
|
||||
"@commerce": ["framework/commerce"],
|
||||
"@commerce/*": ["framework/commerce/*"],
|
||||
"@framework": ["framework/bigcommerce"],
|
||||
"@framework/*": ["framework/bigcommerce/*"]
|
||||
"@framework": ["framework/shopify"],
|
||||
"@framework/*": ["framework/shopify/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"],
|
||||
|
Loading…
x
Reference in New Issue
Block a user