Merge branch 'master' into product-filters-mobile

This commit is contained in:
B 2020-12-21 14:16:23 -03:00 committed by GitHub
commit a5f40f65f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 610 additions and 2699 deletions

5
.gitignore vendored
View File

@ -31,4 +31,7 @@ yarn-error.log*
.env.production.local
# vercel
.vercel
.vercel
# dev
framework

View File

@ -17,7 +17,7 @@ This project is currently <b>under development</b>.
- Responsive
- UI Components
- Theming
- Standarized Data Hooks
- Standardized Data Hooks
- Integrations - Integrate seamlessly with the most common ecommerce platforms.
- Dark Mode Support
@ -66,6 +66,15 @@ After Email confirmation, Checkout should be manually enabled through BigCommerc
BigCommerce team has been notified and they plan to add more detailed about this subject.
</details>
<details>
<summary>I have issues with BigCommerce data hooks</summary>
<br>
Report issue with Data Hooks here: https://github.com/bigcommerce/storefront-data-hooks
</details>
## Contribute
Our commitment to Open Source can be found [here](https://vercel.com/oss).

View File

@ -4,7 +4,7 @@ import Link from 'next/link'
import { useRouter } from 'next/router'
import type { Page } from '@bigcommerce/storefront-data-hooks/api/operations/get-all-pages'
import getSlug from '@lib/get-slug'
import { Github } from '@components/icons'
import { Github, Vercel } from '@components/icons'
import { Logo, Container } from '@components/ui'
import { I18nWidget } from '@components/common'
import s from './Footer.module.css'
@ -99,14 +99,10 @@ const Footer: FC<Props> = ({ className, pages }) => {
<div>
<span>&copy; 2020 ACME, Inc. All rights reserved.</span>
</div>
<div className="flex items-center">
<div className="flex items-center text-primary">
<span className="text-primary">Crafted by</span>
<a href="https://vercel.com" aria-label="Vercel.com Link">
<img
src="/vercel.svg"
alt="Vercel.com Logo"
className="inline-block h-6 ml-4 text-primary"
/>
<a href="https://vercel.com" aria-label="Vercel.com Link" target="_blank" className="text-primary">
<Vercel className="inline-block h-6 ml-4 text-primary" alt="Vercel.com Logo" />
</a>
</div>
</div>

View File

@ -1,26 +0,0 @@
.root {
@apply text-lg leading-7 font-medium max-w-6xl mx-auto;
}
.root p {
@apply text-justify;
}
.root h1 {
@apply text-5xl mb-12;
}
.root h2 {
@apply text-3xl mt-12 mb-4 leading-snug;
}
.root h3 {
@apply text-2xl mt-8 mb-4 leading-snug;
}
.root p,
.root ul,
.root ol,
.root blockquote {
@apply mb-6;
}

View File

@ -1,16 +0,0 @@
import cn from 'classnames'
import s from './HTMLContent.module.css'
type Props = {
className?: 'string'
html: string
}
export default function HTMLContent({ className, html }: Props) {
return (
<div
className={cn(s.root, className)}
dangerouslySetInnerHTML={{ __html: html }}
/>
)
}

View File

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

View File

@ -6,6 +6,10 @@
@apply h-10 px-2 rounded-md border border-accents-2 flex items-center justify-center;
}
.button:hover {
@apply border-accents-4 shadow-sm;
}
.button:focus {
@apply outline-none;
}
@ -18,6 +22,12 @@
}
}
.closeButton {
@screen md {
@apply hidden;
}
}
.item {
@apply flex cursor-pointer px-6 py-3 flex transition ease-in-out duration-150 text-primary leading-6 font-medium items-center;
text-transform: capitalize;
@ -26,3 +36,7 @@
.item:hover {
@apply bg-accents-1;
}
.icon {
transform: rotate(180deg);
}

View File

@ -1,11 +1,10 @@
import { FC } from 'react'
import cn from 'classnames'
import { useRouter } from 'next/router'
import Link from 'next/link'
import { Menu } from '@headlessui/react'
import { DoubleChevron } from '@components/icons'
import { FC, useState } from 'react'
import { useRouter } from 'next/router'
import s from './I18nWidget.module.css'
import { Cross, ChevronUp } from '@components/icons'
import ClickOutside from '@lib/click-outside'
interface LOCALE_DATA {
name: string
img: {
@ -32,50 +31,68 @@ const LOCALES_MAP: Record<string, LOCALE_DATA> = {
}
const I18nWidget: FC = () => {
const [display, setDisplay] = useState(false)
const {
locale,
locales,
defaultLocale = 'en-US',
asPath: currentPath,
} = useRouter()
const options = locales?.filter((val) => val !== locale)
const options = locales?.filter((val) => val !== locale)
const currentLocale = locale || defaultLocale
return (
<nav className={s.root}>
<Menu>
<Menu.Button className={s.button} aria-label="Language selector">
<img
className="block mr-2 w-5"
src={`/${LOCALES_MAP[currentLocale].img.filename}`}
alt={LOCALES_MAP[currentLocale].img.alt}
/>
<span className="mr-2">{LOCALES_MAP[currentLocale].name}</span>
{options && (
<span>
<DoubleChevron />
</span>
)}
</Menu.Button>
{options?.length ? (
<Menu.Items className={s.dropdownMenu}>
{options.map((locale) => (
<Menu.Item key={locale}>
{({ active }) => (
<Link href={currentPath} locale={locale}>
<a className={cn(s.item, { [s.active]: active })}>
{LOCALES_MAP[locale].name}
</a>
</Link>
)}
</Menu.Item>
))}
</Menu.Items>
) : null}
</Menu>
</nav>
<ClickOutside active={display} onClick={() => setDisplay(false)} >
<nav className={s.root}>
<div
className="flex items-center relative"
onClick={() => setDisplay(!display)}
>
<button className={s.button} aria-label="Language selector">
<img
className="block mr-2 w-5"
src={`/${LOCALES_MAP[currentLocale].img.filename}`}
alt={LOCALES_MAP[currentLocale].img.alt}
/>
{options && (
<span className="cursor-pointer">
<ChevronUp className={cn({ [s.icon]: display })} />
</span>
)}
</button>
</div>
<div className="absolute top-0 right-0">
{options?.length && display ? (
<div className={s.dropdownMenu}>
<div className="flex flex-row justify-end px-6">
<button
onClick={() => setDisplay(false)}
aria-label="Close panel"
className={s.closeButton}
>
<Cross className="h-6 w-6" />
</button>
</div>
<ul>
{options.map((locale) => (
<li key={locale}>
<Link href={currentPath} locale={locale}>
<a
className={cn(s.item)}
onClick={() => setDisplay(false)}
>
{LOCALES_MAP[locale].name}
</a>
</Link>
</li>
))}
</ul>
</div>
) : null}
</div>
</nav>
</ClickOutside>
)
}

View File

@ -5,13 +5,13 @@ import { useRouter } from 'next/router'
import React, { FC } from 'react'
import { useUI } from '@components/ui/context'
import { Navbar, Footer } from '@components/common'
import { usePreventScroll } from '@react-aria/overlays'
import { useAcceptCookies } from '@lib/hooks/useAcceptCookies'
import { CommerceProvider } from '@bigcommerce/storefront-data-hooks'
import { Sidebar, Button, Modal, LoadingDots } from '@components/ui'
import type { Page } from '@bigcommerce/storefront-data-hooks/api/operations/get-all-pages'
import { CartSidebarView } from '@components/cart'
import { CommerceProvider } from '@bigcommerce/storefront-data-hooks'
import type { Page } from '@bigcommerce/storefront-data-hooks/api/operations/get-all-pages'
const Loading = () => (
<div className="w-80 h-80 flex items-center text-center justify-center p-3">
<LoadingDots />
@ -56,10 +56,6 @@ const Layout: FC<Props> = ({ children, pageProps }) => {
const { acceptedCookies, onAcceptCookies } = useAcceptCookies()
const { locale = 'en-US' } = useRouter()
usePreventScroll({
isDisabled: !(displaySidebar || displayModal),
})
return (
<CommerceProvider locale={locale}>
<div className={cn(s.root)}>
@ -81,7 +77,7 @@ const Layout: FC<Props> = ({ children, pageProps }) => {
title="This site uses cookies to improve your experience. By clicking, you agree to our Privacy Policy."
hide={acceptedCookies}
action={
<Button className="mx-5" onClick={onAcceptCookies}>
<Button className="mx-5" onClick={() => onAcceptCookies()}>
Accept cookies
</Button>
}

View File

@ -9,32 +9,32 @@ import throttle from 'lodash.throttle'
const Navbar: FC = () => {
const [hasScrolled, setHasScrolled] = useState(false)
const handleScroll = () => {
const offset = 0
const { scrollTop } = document.documentElement
const scrolled = scrollTop > offset
setHasScrolled(scrolled)
}
useEffect(() => {
document.addEventListener('scroll', throttle(handleScroll, 200))
const handleScroll = throttle(() => {
const offset = 0
const { scrollTop } = document.documentElement
const scrolled = scrollTop > offset
setHasScrolled(scrolled)
}, 200)
document.addEventListener('scroll', handleScroll)
return () => {
document.removeEventListener('scroll', handleScroll)
}
}, [handleScroll])
}, [])
return (
<div className={cn(s.root, { 'shadow-magical': hasScrolled })}>
<Container>
<div className="flex justify-between align-center flex-row py-4 md:py-6 relative">
<div className="flex flex-1 items-center">
<div className="relative flex flex-row justify-between py-4 align-center md:py-6">
<div className="flex items-center flex-1">
<Link href="/">
<a className={s.logo} aria-label="Logo">
<Logo />
</a>
</Link>
<nav className="space-x-4 ml-6 hidden lg:block">
<Link href="/">
<nav className="hidden ml-6 space-x-4 lg:block">
<Link href="/search">
<a className={s.link}>All</a>
</Link>
<Link href="/search?q=clothes">
@ -46,11 +46,11 @@ const Navbar: FC = () => {
</nav>
</div>
<div className="flex-1 justify-center hidden lg:flex">
<div className="justify-center flex-1 hidden lg:flex">
<Searchbar />
</div>
<div className="flex flex-1 justify-end space-x-8">
<div className="flex justify-end flex-1 space-x-8">
<UserNav />
</div>
</div>

View File

@ -1,2 +0,0 @@
.root {
}

View File

@ -1,55 +0,0 @@
import React, { FC } from 'react'
import { Switch } from '@headlessui/react'
import { Moon, Sun } from '@components/icons'
interface Props {
className?: string
checked: boolean
onChange: any
}
const Toggle: FC<Props> = ({ className, checked, onChange }) => {
return (
<Switch
checked={checked}
onChange={onChange}
className="focus:outline-none"
>
<span
role="checkbox"
aria-checked="false"
tabIndex={0}
className={`${
checked ? 'bg-gray-800' : 'bg-gray-200'
} relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-150 focus:outline-none focus:shadow-outline`}
>
<span
aria-hidden="true"
className={`${
checked ? 'translate-x-5' : 'translate-x-0'
} translate-x-0 relative inline-block h-5 w-5 rounded-full bg-white shadow transform transition ease-in-out duration-150`}
>
<span
className={`${
checked
? 'opacity-0 ease-out duration-150'
: 'opacity-100 ease-in duration-150'
} absolute inset-0 h-full w-full flex items-center justify-center transition-opacity`}
>
<Sun className="h-3 w-3 text-accent-3" />
</span>
<span
className={`${
checked
? 'opacity-100 ease-in duration-150'
: 'opacity-0 ease-out duration-150'
} opacity-0 ease-out duration-150 absolute inset-0 h-full w-full flex items-center justify-center transition-opacity`}
>
<Moon className="h-3 w-3 text-yellow-400" />
</span>
</span>
</span>
</Switch>
)
}
export default Toggle

View File

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

View File

@ -1,8 +1,8 @@
.dropdownMenu {
@apply fixed right-0 mt-7 origin-top-right outline-none bg-primary z-40 w-full h-full;
@apply fixed right-0 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full;
@screen lg {
@apply absolute border border-accents-1 shadow-lg w-56 h-auto;
@apply absolute top-10 border border-accents-1 shadow-lg w-56 h-auto;
}
}

View File

@ -1,16 +1,24 @@
import { FC } from 'react'
import Link from 'next/link'
import { useTheme } from 'next-themes'
import cn from 'classnames'
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 { Menu, Transition } from '@headlessui/react'
import ClickOutside from '@lib/click-outside'
import {
disableBodyScroll,
enableBodyScroll,
clearAllBodyScrollLocks,
} from 'body-scroll-lock'
import useLogout from '@bigcommerce/storefront-data-hooks/use-logout'
import { useRouter } from 'next/router'
interface DropdownMenuProps {
open: boolean
open?: boolean
}
const LINKS = [
@ -29,68 +37,89 @@ const LINKS = [
]
const DropdownMenu: FC<DropdownMenuProps> = ({ open = false }) => {
const { theme, setTheme } = useTheme()
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 (
<Transition
show={open}
enter="transition ease-out duration-150 z-20"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className={s.dropdownMenu}>
{LINKS.map(({ name, href }) => (
<Menu.Item key={href}>
<div>
<Link href={href}>
<a
className={cn(s.link, {
[s.active]: pathname === href,
})}
onClick={closeSidebarIfPresent}
>
{name}
</a>
</Link>
</div>
</Menu.Item>
))}
<Menu.Item>
<a
className={cn(s.link, 'justify-between')}
onClick={() =>
theme === 'dark' ? setTheme('light') : setTheme('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>
</Menu.Item>
<Menu.Item>
<a
className={cn(s.link, 'border-t border-accents-2 mt-4')}
onClick={() => logout()}
>
Logout
</a>
</Menu.Item>
</Menu.Items>
</Transition>
<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-accents-2 mt-4')}
onClick={() => logout()}
>
Logout
</a>
</li>
</ul>
)}
</div>
</ClickOutside>
)
}

View File

@ -3,12 +3,11 @@ import Link from 'next/link'
import cn from 'classnames'
import useCart from '@bigcommerce/storefront-data-hooks/cart/use-cart'
import useCustomer from '@bigcommerce/storefront-data-hooks/use-customer'
import { Menu } from '@headlessui/react'
import { Heart, Bag } from '@components/icons'
import { Avatar } from '@components/common'
import { useUI } from '@components/ui/context'
import DropdownMenu from './DropdownMenu'
import s from './UserNav.module.css'
import { Avatar } from '@components/common'
interface Props {
className?: string
@ -21,9 +20,9 @@ const countItems = (count: number, items: any[]) =>
const UserNav: FC<Props> = ({ className, children, ...props }) => {
const { data } = useCart()
const { data: customer } = useCustomer()
const { toggleSidebar, closeSidebarIfPresent, openModal } = useUI()
const itemsCount = Object.values(data?.line_items ?? {}).reduce(countItems, 0)
return (
<nav className={cn(s.root, className)}>
<div className={s.mainContainer}>
@ -41,16 +40,7 @@ const UserNav: FC<Props> = ({ className, children, ...props }) => {
</li>
<li className={s.item}>
{customer ? (
<Menu>
{({ open }) => (
<>
<Menu.Button className={s.avatarButton} aria-label="Menu">
<Avatar />
</Menu.Button>
<DropdownMenu open={open} />
</>
)}
</Menu>
<DropdownMenu />
) : (
<button
className={s.avatarButton}

View File

@ -5,7 +5,5 @@ export { default as Layout } from './Layout'
export { default as Navbar } from './Navbar'
export { default as Searchbar } from './Searchbar'
export { default as UserNav } from './UserNav'
export { default as Toggle } from './Toggle'
export { default as Head } from './Head'
export { default as HTMLContent } from './HTMLContent'
export { default as I18nWidget } from './I18nWidget'

View 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="M18 15l-6-6-6 6" />
</svg>
)
}
export default ChevronUp

View File

@ -1,4 +1,4 @@
const Sun = ({ ...props }) => {
const Github = ({ ...props }) => {
return (
<svg
width="24"
@ -17,4 +17,4 @@ const Sun = ({ ...props }) => {
)
}
export default Sun
export default Github

View File

@ -0,0 +1,16 @@
const Vercel = ({ ...props }) => {
return (
<svg width="89" height="20" viewBox="0 0 89 20" fill="none" xmlns="http://www.w3.org/2000/svg" { ...props }>
<path d="M11.5625 0L23.125 20H0L11.5625 0Z" fill="currentColor"/>
<path d="M49.875 10.625C49.875 7.40625 47.5 5.15625 44.0937 5.15625C40.6875 5.15625 38.3125 7.40625 38.3125 10.625C38.3125 13.7812 40.875 16.0937 44.4062 16.0937C46.3438 16.0937 48.0938 15.375 49.2188 14.0625L47.0938 12.8437C46.4375 13.5 45.4688 13.9062 44.4062 13.9062C42.8438 13.9062 41.5 13.0625 41.0312 11.7812L40.9375 11.5625H49.7812C49.8438 11.25 49.875 10.9375 49.875 10.625ZM40.9062 9.6875L40.9688 9.5C41.375 8.15625 42.5625 7.34375 44.0625 7.34375C45.5938 7.34375 46.75 8.15625 47.1562 9.5L47.2188 9.6875H40.9062Z" fill="currentColor"/>
<path d="M83.5313 10.625C83.5313 7.40625 81.1563 5.15625 77.75 5.15625C74.3438 5.15625 71.9688 7.40625 71.9688 10.625C71.9688 13.7812 74.5313 16.0937 78.0625 16.0937C80 16.0937 81.75 15.375 82.875 14.0625L80.75 12.8437C80.0938 13.5 79.125 13.9062 78.0625 13.9062C76.5 13.9062 75.1563 13.0625 74.6875 11.7812L74.5938 11.5625H83.4375C83.5 11.25 83.5313 10.9375 83.5313 10.625ZM74.5625 9.6875L74.625 9.5C75.0313 8.15625 76.2188 7.34375 77.7188 7.34375C79.25 7.34375 80.4063 8.15625 80.8125 9.5L80.875 9.6875H74.5625Z" fill="currentColor"/>
<path d="M68.5313 8.84374L70.6563 7.62499C69.6563 6.06249 67.875 5.18749 65.7188 5.18749C62.3125 5.18749 59.9375 7.43749 59.9375 10.6562C59.9375 13.875 62.3125 16.125 65.7188 16.125C67.875 16.125 69.6563 15.25 70.6563 13.6875L68.5313 12.4687C67.9688 13.4062 66.9688 13.9375 65.7188 13.9375C63.75 13.9375 62.4375 12.625 62.4375 10.6562C62.4375 8.68749 63.75 7.37499 65.7188 7.37499C66.9375 7.37499 67.9688 7.90624 68.5313 8.84374Z" fill="currentColor"/>
<path d="M88.2188 1.75H85.7188V15.8125H88.2188V1.75Z" fill="currentColor"/>
<path d="M40.1563 1.75H37.2813L31.7813 11.25L26.2813 1.75H23.375L31.7813 16.25L40.1563 1.75Z" fill="currentColor"/>
<path d="M57.8438 8.0625C58.125 8.0625 58.4062 8.09375 58.6875 8.15625V5.5C56.5625 5.5625 54.5625 6.75 54.5625 8.21875V5.5H52.0625V15.8125H54.5625V11.3437C54.5625 9.40625 55.9062 8.0625 57.8438 8.0625Z" fill="currentColor"/>
</svg>
)
}
export default Vercel

View File

@ -12,3 +12,5 @@ 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'

View File

@ -9,8 +9,8 @@
transform: scale(0.98);
}
& .product-image {
transform: scale(1.05);
& .productImage {
transform: scale(1.2625);
}
& .productTitle > span,
@ -44,10 +44,6 @@
}
}
& .product-image {
@apply transform transition-transform duration-500;
}
&:nth-child(6n + 1) .squareBg {
@apply bg-violet;
}
@ -135,7 +131,6 @@
}
}
.image {
object-fit: cover;
transform: scale(1.2);
.productImage {
@apply transform transition-transform duration-500 object-cover scale-120;
}

View File

@ -1,12 +1,13 @@
import type { FC } from 'react'
import cn from 'classnames'
import Link from 'next/link'
import type { ProductNode } from '@bigcommerce/storefront-data-hooks/api/operations/get-all-products'
import usePrice from '@bigcommerce/storefront-data-hooks/use-price'
import Image from 'next/image'
import type { FC } from 'react'
import s from './ProductCard.module.css'
import WishlistButton from '@components/wishlist/WishlistButton'
import usePrice from '@bigcommerce/storefront-data-hooks/use-price'
import type { ProductNode } from '@bigcommerce/storefront-data-hooks/api/operations/get-all-products'
interface Props {
className?: string
product: ProductNode
@ -82,7 +83,7 @@ const ProductCard: FC<Props> = ({
quality="85"
src={src}
alt={p.name}
className={s.image}
className={s.productImage}
width={imgWidth}
sizes={imgSizes}
height={imgHeight}

View File

@ -6,8 +6,7 @@ import { NextSeo } from 'next-seo'
import s from './ProductView.module.css'
import { useUI } from '@components/ui/context'
import { Swatch, ProductSlider } from '@components/product'
import { Button, Container } from '@components/ui'
import { HTMLContent } from '@components/common'
import { Button, Container, Text } from '@components/ui'
import usePrice from '@bigcommerce/storefront-data-hooks/use-price'
import useAddItem from '@bigcommerce/storefront-data-hooks/cart/use-add-item'
@ -137,7 +136,7 @@ const ProductView: FC<Props> = ({ product }) => {
))}
<div className="pb-14 break-words w-full max-w-xl">
<HTMLContent html={product.description} />
<Text html={product.description} />
</div>
</section>
<div>

View File

@ -6,7 +6,6 @@ import React, {
useRef,
} from 'react'
import mergeRefs from 'react-merge-refs'
import { useButton } from 'react-aria'
import s from './Button.module.css'
import { LoadingDots } from '@components/ui'
@ -28,25 +27,14 @@ const Button: React.FC<ButtonProps> = forwardRef((props, buttonRef) => {
variant = 'flat',
children,
active,
onClick,
width,
Component = 'button',
loading = false,
disabled = false,
style = {},
Component = 'button',
...rest
} = props
const ref = useRef<typeof Component>(null)
const { buttonProps, isPressed } = useButton(
{
...rest,
// @ts-ignore onClick === onPress for our purposes
onPress: onClick,
isDisabled: disabled,
elementType: Component,
},
ref
)
const rootClassName = cn(
s.root,
@ -63,14 +51,13 @@ const Button: React.FC<ButtonProps> = forwardRef((props, buttonRef) => {
aria-pressed={active}
data-variant={variant}
ref={mergeRefs([ref, buttonRef])}
{...buttonProps}
data-active={isPressed ? '' : undefined}
className={rootClassName}
disabled={disabled}
style={{
width,
...style,
}}
{...rest}
>
{children}
{loading && (

View File

@ -1,10 +1,13 @@
import { FC, useRef } from 'react'
import s from './Modal.module.css'
import { FocusScope } from '@react-aria/focus'
import { Transition } from '@headlessui/react'
import { Cross } from '@components/icons'
import { useOverlay, OverlayContainer } from '@react-aria/overlays'
import { FC, useRef, useEffect } from 'react'
import Portal from '@reach/portal'
import s from './Modal.module.css'
import { Cross } from '@components/icons'
import {
disableBodyScroll,
enableBodyScroll,
clearAllBodyScrollLocks,
} from 'body-scroll-lock'
interface Props {
className?: string
children?: any
@ -12,48 +15,41 @@ interface Props {
onClose: () => void
}
const Modal: FC<Props> = ({ children, open = false, onClose, ...props }) => {
let ref = useRef() as React.MutableRefObject<HTMLInputElement>
let { overlayProps } = useOverlay(
{
isOpen: open,
isDismissable: false,
onClose: onClose,
...props,
},
ref
)
const Modal: FC<Props> = ({ children, open, onClose }) => {
const ref = useRef() as React.MutableRefObject<HTMLDivElement>
useEffect(() => {
if (ref.current) {
if (open) {
disableBodyScroll(ref.current)
} else {
enableBodyScroll(ref.current)
}
}
return () => {
clearAllBodyScrollLocks()
}
}, [open])
return (
<Transition show={open}>
<OverlayContainer>
<FocusScope contain restoreFocus autoFocus>
<div className={s.root}>
<Transition.Child
enter="transition-opacity ease-linear duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity ease-linear duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className={s.modal} {...overlayProps} ref={ref}>
<div className="h-7 flex items-center justify-end w-full">
<button
onClick={() => onClose()}
aria-label="Close panel"
className="hover:text-gray-500 transition ease-in-out duration-150 focus:outline-none"
>
<Cross className="h-6 w-6" />
</button>
</div>
{children}
</div>
</Transition.Child>
<Portal>
{open ? (
<div className={s.root} ref={ref}>
<div className={s.modal}>
<div className="h-7 flex items-center justify-end w-full">
<button
onClick={() => onClose()}
aria-label="Close panel"
className="hover:text-gray-500 transition ease-in-out duration-150 focus:outline-none"
>
<Cross className="h-6 w-6" />
</button>
</div>
{children}
</div>
</FocusScope>
</OverlayContainer>
</Transition>
</div>
) : null}
</Portal>
)
}

View File

@ -1,9 +1,11 @@
import { FC, useRef } from 'react'
import s from './Sidebar.module.css'
import { Transition } from '@headlessui/react'
import { useOverlay, OverlayContainer } from '@react-aria/overlays'
import { FocusScope } from '@react-aria/focus'
import Portal from '@reach/portal'
import { FC, useEffect, useRef } from 'react'
import {
disableBodyScroll,
enableBodyScroll,
clearAllBodyScrollLocks,
} from 'body-scroll-lock'
interface Props {
children: any
@ -12,62 +14,40 @@ interface Props {
}
const Sidebar: FC<Props> = ({ children, open = false, onClose }) => {
const ref = useRef<HTMLDivElement>(null)
const { overlayProps } = useOverlay(
{
isOpen: open,
isDismissable: true,
onClose: onClose,
},
ref
)
const ref = useRef() as React.MutableRefObject<HTMLDivElement>
useEffect(() => {
if (ref.current) {
if (open) {
disableBodyScroll(ref.current)
} else {
enableBodyScroll(ref.current)
}
}
return () => {
clearAllBodyScrollLocks()
}
}, [open])
return (
<Portal>
<Transition show={open}>
<OverlayContainer>
<FocusScope contain restoreFocus autoFocus>
<div className={s.root}>
<div className="absolute inset-0 overflow-hidden">
<Transition.Child
enter="transition-opacity ease-linear duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity ease-linear duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div
className="absolute inset-0 bg-black bg-opacity-50 transition-opacity"
// Close the sidebar when clicking on the backdrop
onClick={onClose}
/>
</Transition.Child>
<section
className="absolute inset-y-0 right-0 pl-10 max-w-full flex sm:pl-16 outline-none"
{...overlayProps}
ref={ref}
>
<Transition.Child
enter="transition ease-in-out duration-300 transform"
enterFrom="translate-x-full"
enterTo="translate-x-0"
leave="transition ease-in-out duration-300 transform"
leaveFrom="translate-x-0"
leaveTo="translate-x-full"
>
<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">
{children}
</div>
</div>
</Transition.Child>
</section>
{open ? (
<div className={s.root} ref={ref}>
<div className="absolute inset-0 overflow-hidden">
<div
className="absolute inset-0 bg-black bg-opacity-50 transition-opacity"
onClick={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">
{children}
</div>
</div>
</div>
</FocusScope>
</OverlayContainer>
</Transition>
</section>
</div>
</div>
) : null}
</Portal>
)
}

View File

@ -10,7 +10,8 @@ interface Props {
variant?: Variant
className?: string
style?: CSSProperties
children: React.ReactNode | any
children?: React.ReactNode | any
html?: string
}
type Variant = 'heading' | 'body' | 'pageHeading' | 'sectionHeading'
@ -20,11 +21,12 @@ const Text: FunctionComponent<Props> = ({
className = '',
variant = 'body',
children,
html,
}) => {
const componentsMap: {
[P in Variant]: React.ComponentType<any> | string
} = {
body: 'p',
body: 'div',
heading: 'h1',
pageHeading: 'h1',
sectionHeading: 'h2',
@ -36,6 +38,12 @@ const Text: FunctionComponent<Props> = ({
| React.ComponentType<any>
| string = componentsMap![variant!]
const htmlContentProps = html
? {
dangerouslySetInnerHTML: { __html: html },
}
: {}
return (
<Component
className={cn(
@ -49,6 +57,7 @@ const Text: FunctionComponent<Props> = ({
className
)}
style={style}
{...htmlContentProps}
>
{children}
</Component>

View File

@ -1,9 +0,0 @@
.root {
}
.toast {
@apply absolute bg-primary text-primary flex items-center border border-accents-1
rounded-md z-50 shadow-2xl top-0 right-0 p-6 my-6 mx-3;
width: 420px;
z-index: 20000;
}

View File

@ -1,73 +0,0 @@
import cn from 'classnames'
import { FC, useRef, useEffect, useCallback } from 'react'
import s from './Toast.module.css'
import { useDialog } from '@react-aria/dialog'
import { FocusScope } from '@react-aria/focus'
import { Transition } from '@headlessui/react'
import { useOverlay, useModal, OverlayContainer } from '@react-aria/overlays'
interface Props {
className?: string
children?: any
open?: boolean
onClose: () => void
}
const Toast: FC<Props> = ({
className,
children,
open = false,
onClose,
...props
}) => {
const rootClassName = cn(s.root, className)
let ref = useRef() as React.MutableRefObject<HTMLInputElement>
let { modalProps } = useModal()
let { dialogProps } = useDialog({}, ref)
let { overlayProps } = useOverlay(
{
isOpen: open,
isDismissable: true,
onClose: onClose,
...props,
},
ref
)
// useEffect(() => {
// setTimeout(() => {
// useCallback(onClose, [])
// }, 400)
// })
return (
<Transition show={open}>
<OverlayContainer>
<FocusScope contain restoreFocus autoFocus>
<div className={rootClassName}>
<Transition.Child
enter="transition-opacity ease-linear duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity ease-linear duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div
className={s.toast}
{...overlayProps}
{...dialogProps}
{...modalProps}
ref={ref}
>
{children}
</div>
</Transition.Child>
</div>
</FocusScope>
</OverlayContainer>
</Transition>
)
}
export default Toast

View File

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

View File

@ -1,6 +1,5 @@
import React, { FC, useMemo } from 'react'
import { ThemeProvider } from 'next-themes'
import { SSRProvider, OverlayProvider } from 'react-aria'
export interface State {
displaySidebar: boolean
@ -181,10 +180,6 @@ export const useUI = () => {
export const ManagedUIContext: FC = ({ children }) => (
<UIProvider>
<ThemeProvider>
<SSRProvider>
<OverlayProvider>{children}</OverlayProvider>
</SSRProvider>
</ThemeProvider>
<ThemeProvider>{children}</ThemeProvider>
</UIProvider>
)

View File

@ -10,4 +10,3 @@ export { default as Skeleton } from './Skeleton'
export { default as Modal } from './Modal'
export { default as Text } from './Text'
export { default as Input } from './Input'
export { default as Toast } from './Toast'

View File

@ -7,8 +7,7 @@ import usePrice from '@bigcommerce/storefront-data-hooks/use-price'
import useRemoveItem from '@bigcommerce/storefront-data-hooks/wishlist/use-remove-item'
import useAddItem from '@bigcommerce/storefront-data-hooks/cart/use-add-item'
import { useUI } from '@components/ui/context'
import { Button } from '@components/ui'
import { HTMLContent } from '@components/common'
import { Button, Text } from '@components/ui'
import { Trash } from '@components/icons'
import s from './WishlistCard.module.css'
@ -72,7 +71,7 @@ const WishlistCard: FC<Props> = ({ item }) => {
</Link>
</h3>
<div className="mb-4">
<HTMLContent html={product.description!} />
<Text html={product.description} />
</div>
<Button
aria-label="Add to Cart"

View File

@ -0,0 +1,38 @@
import React, { useRef, useEffect, MouseEvent } from 'react'
import hasParent from './has-parent'
interface ClickOutsideProps {
active: boolean
onClick: (e?: MouseEvent) => void
children: any
}
const ClickOutside = ({ active = true, onClick, children }: ClickOutsideProps) => {
const innerRef = useRef()
const handleClick = (event: any) => {
if (!hasParent(event.target, innerRef?.current)) {
if (typeof onClick === 'function') {
onClick(event)
}
}
}
useEffect(() => {
if (active) {
document.addEventListener('mousedown', handleClick)
document.addEventListener('touchstart', handleClick)
}
return () => {
if (active) {
document.removeEventListener('mousedown', handleClick)
document.removeEventListener('touchstart', handleClick)
}
}
})
return React.cloneElement(children, { ref: innerRef })
}
export default ClickOutside

View File

@ -0,0 +1,5 @@
import isInDOM from './is-in-dom'
export default function hasParent(element, root) {
return root && root.contains(element) && isInDOM(element)
}

View File

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

View File

@ -0,0 +1,3 @@
export default function isInDom(obj) {
return Boolean(obj.closest('body'))
}

14
lib/defaults.ts Normal file
View File

@ -0,0 +1,14 @@
// Fallback to CMS Data
export const defatultPageProps = {
header: {
links: [
{
link: {
title: 'New Arrivals',
url: '/',
},
},
],
},
}

View File

@ -1,5 +1,5 @@
import { useEffect, useState } from 'react'
import Cookies from 'js-cookie'
import { useEffect, useState } from 'react'
const COOKIE_NAME = 'accept_cookies'
@ -14,9 +14,7 @@ export const useAcceptCookies = () => {
const acceptCookies = () => {
setAcceptedCookies(true)
Cookies.set(COOKIE_NAME, 'accepted', {
expires: 365,
})
Cookies.set(COOKIE_NAME, 'accepted', { expires: 365 })
}
return {

View File

@ -53,6 +53,7 @@ module.exports = bundleAnalyzer({
// This rewrite will also handle `/search/designers`
source: '/search/:category',
destination: '/search',
locale: false
},
]
},

View File

@ -43,12 +43,12 @@
},
"dependencies": {
"@bigcommerce/storefront-data-hooks": "^1.0.2",
"@headlessui/react": "^0.2.0",
"@reach/portal": "^0.11.2",
"@react-aria/overlays": "^3.4.0",
"@tailwindcss/ui": "^0.6.2",
"@types/body-scroll-lock": "^2.6.1",
"@types/lodash.throttle": "^4.1.6",
"@vercel/fetch": "^6.1.0",
"body-scroll-lock": "^3.1.5",
"bowser": "^2.11.0",
"classnames": "^2.2.6",
"email-validator": "^2.0.4",
@ -56,12 +56,11 @@
"keen-slider": "^5.2.4",
"lodash.random": "^3.2.0",
"lodash.throttle": "^4.1.1",
"next": "^10.0.1-canary.7",
"next": "^10.0.3-canary.3",
"next-seo": "^4.11.0",
"next-themes": "^0.0.4",
"postcss-nesting": "^7.0.1",
"react": "^16.14.0",
"react-aria": "^3.0.0",
"react-dom": "^16.14.0",
"react-intersection-observer": "^8.30.1",
"react-merge-refs": "^1.1.0",

View File

@ -3,12 +3,14 @@ import type {
GetStaticPropsContext,
InferGetStaticPropsType,
} from 'next'
import getSlug from '@lib/get-slug'
import { missingLocaleInPages } from '@lib/usage-warns'
import { Layout } from '@components/common'
import { Text } from '@components/ui'
import { getConfig } from '@bigcommerce/storefront-data-hooks/api'
import getPage from '@bigcommerce/storefront-data-hooks/api/operations/get-page'
import getAllPages from '@bigcommerce/storefront-data-hooks/api/operations/get-all-pages'
import getSlug from '@lib/get-slug'
import { missingLocaleInPages } from '@lib/usage-warns'
import { Layout, HTMLContent } from '@components/common'
import { defatultPageProps } from '@lib/defaults'
export async function getStaticProps({
preview,
@ -32,7 +34,7 @@ export async function getStaticProps({
}
return {
props: { pages, page },
props: { ...defatultPageProps, pages, page },
revalidate: 60 * 60, // Every hour
}
}
@ -64,7 +66,7 @@ export default function Pages({
}: InferGetStaticPropsType<typeof getStaticProps>) {
return (
<div className="max-w-2xl mx-auto py-20">
{page?.body && <HTMLContent html={page.body} />}
{page?.body && <Text html={page.body} />}
</div>
)
}

View File

@ -51,8 +51,7 @@ export async function getStaticPaths({ locales }: GetStaticPathsContext) {
return arr
}, [])
: products.map((product) => `/product${product.node.path}`),
// If your store has tons of products, enable fallback mode to improve build times!
fallback: false,
fallback: 'blocking',
}
}

View File

@ -4,9 +4,9 @@ import getAllPages from '@bigcommerce/storefront-data-hooks/api/operations/get-a
import useWishlist from '@bigcommerce/storefront-data-hooks/wishlist/use-wishlist'
import { Layout } from '@components/common'
import { Heart } from '@components/icons'
import { Container, Text } from '@components/ui'
import { Text, Container } from '@components/ui'
import { WishlistCard } from '@components/wishlist'
import { Transition } from '@headlessui/react'
import { defatultPageProps } from '@lib/defaults'
export async function getStaticProps({
preview,
@ -15,7 +15,7 @@ export async function getStaticProps({
const config = getConfig({ locale })
const { pages } = await getAllPages({ config, preview })
return {
props: { pages },
props: { ...defatultPageProps, pages },
}
}
@ -28,45 +28,22 @@ export default function Wishlist() {
<Text variant="pageHeading">My Wishlist</Text>
<div className="group flex flex-col">
{isEmpty ? (
<Transition show>
<Transition.Child
enter="transition-opacity ease-linear duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity ease-linear duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="flex-1 px-12 py-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 bg-primary p-12 rounded-lg text-primary">
<Heart className="absolute" />
</span>
<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">
Biscuit oat cake wafer icing ice cream tiramisu pudding
cupcake.
</p>
</div>
</Transition.Child>
</Transition>
<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">
<Heart className="absolute" />
</span>
<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">
Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake.
</p>
</div>
) : (
<Transition show>
{data &&
data.items?.map((item) => (
<Transition.Child
enter="transition-opacity ease-linear duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity ease-linear duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<WishlistCard key={item.id} item={item} />
</Transition.Child>
))}
</Transition>
data &&
data.items?.map((item) => (
<WishlistCard key={item.id} item={item} />
))
)}
</div>
</div>

View File

@ -1,9 +1,9 @@
<svg width="89" height="20" viewBox="0 0 89 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.5625 0L23.125 20H0L11.5625 0Z" fill="black"/>
<path d="M49.875 10.625C49.875 7.40625 47.5 5.15625 44.0937 5.15625C40.6875 5.15625 38.3125 7.40625 38.3125 10.625C38.3125 13.7812 40.875 16.0937 44.4062 16.0937C46.3438 16.0937 48.0938 15.375 49.2188 14.0625L47.0938 12.8437C46.4375 13.5 45.4688 13.9062 44.4062 13.9062C42.8438 13.9062 41.5 13.0625 41.0312 11.7812L40.9375 11.5625H49.7812C49.8438 11.25 49.875 10.9375 49.875 10.625ZM40.9062 9.6875L40.9688 9.5C41.375 8.15625 42.5625 7.34375 44.0625 7.34375C45.5938 7.34375 46.75 8.15625 47.1562 9.5L47.2188 9.6875H40.9062Z" fill="black"/>
<path d="M83.5313 10.625C83.5313 7.40625 81.1563 5.15625 77.75 5.15625C74.3438 5.15625 71.9688 7.40625 71.9688 10.625C71.9688 13.7812 74.5313 16.0937 78.0625 16.0937C80 16.0937 81.75 15.375 82.875 14.0625L80.75 12.8437C80.0938 13.5 79.125 13.9062 78.0625 13.9062C76.5 13.9062 75.1563 13.0625 74.6875 11.7812L74.5938 11.5625H83.4375C83.5 11.25 83.5313 10.9375 83.5313 10.625ZM74.5625 9.6875L74.625 9.5C75.0313 8.15625 76.2188 7.34375 77.7188 7.34375C79.25 7.34375 80.4063 8.15625 80.8125 9.5L80.875 9.6875H74.5625Z" fill="black"/>
<path d="M68.5313 8.84374L70.6563 7.62499C69.6563 6.06249 67.875 5.18749 65.7188 5.18749C62.3125 5.18749 59.9375 7.43749 59.9375 10.6562C59.9375 13.875 62.3125 16.125 65.7188 16.125C67.875 16.125 69.6563 15.25 70.6563 13.6875L68.5313 12.4687C67.9688 13.4062 66.9688 13.9375 65.7188 13.9375C63.75 13.9375 62.4375 12.625 62.4375 10.6562C62.4375 8.68749 63.75 7.37499 65.7188 7.37499C66.9375 7.37499 67.9688 7.90624 68.5313 8.84374Z" fill="black"/>
<path d="M88.2188 1.75H85.7188V15.8125H88.2188V1.75Z" fill="black"/>
<path d="M40.1563 1.75H37.2813L31.7813 11.25L26.2813 1.75H23.375L31.7813 16.25L40.1563 1.75Z" fill="currentColor"/>
<path d="M57.8438 8.0625C58.125 8.0625 58.4062 8.09375 58.6875 8.15625V5.5C56.5625 5.5625 54.5625 6.75 54.5625 8.21875V5.5H52.0625V15.8125H54.5625V11.3437C54.5625 9.40625 55.9062 8.0625 57.8438 8.0625Z" fill="black"/>
<path d="M11.5625 0L23.125 20H0L11.5625 0Z" fill="currentColor"/>
<path d="M49.875 10.625C49.875 7.40625 47.5 5.15625 44.0937 5.15625C40.6875 5.15625 38.3125 7.40625 38.3125 10.625C38.3125 13.7812 40.875 16.0937 44.4062 16.0937C46.3438 16.0937 48.0938 15.375 49.2188 14.0625L47.0938 12.8437C46.4375 13.5 45.4688 13.9062 44.4062 13.9062C42.8438 13.9062 41.5 13.0625 41.0312 11.7812L40.9375 11.5625H49.7812C49.8438 11.25 49.875 10.9375 49.875 10.625ZM40.9062 9.6875L40.9688 9.5C41.375 8.15625 42.5625 7.34375 44.0625 7.34375C45.5938 7.34375 46.75 8.15625 47.1562 9.5L47.2188 9.6875H40.9062Z" fill="currentColor"/>
<path d="M83.5313 10.625C83.5313 7.40625 81.1563 5.15625 77.75 5.15625C74.3438 5.15625 71.9688 7.40625 71.9688 10.625C71.9688 13.7812 74.5313 16.0937 78.0625 16.0937C80 16.0937 81.75 15.375 82.875 14.0625L80.75 12.8437C80.0938 13.5 79.125 13.9062 78.0625 13.9062C76.5 13.9062 75.1563 13.0625 74.6875 11.7812L74.5938 11.5625H83.4375C83.5 11.25 83.5313 10.9375 83.5313 10.625ZM74.5625 9.6875L74.625 9.5C75.0313 8.15625 76.2188 7.34375 77.7188 7.34375C79.25 7.34375 80.4063 8.15625 80.8125 9.5L80.875 9.6875H74.5625Z" fill="currentColor"/>
<path d="M68.5313 8.84374L70.6563 7.62499C69.6563 6.06249 67.875 5.18749 65.7188 5.18749C62.3125 5.18749 59.9375 7.43749 59.9375 10.6562C59.9375 13.875 62.3125 16.125 65.7188 16.125C67.875 16.125 69.6563 15.25 70.6563 13.6875L68.5313 12.4687C67.9688 13.4062 66.9688 13.9375 65.7188 13.9375C63.75 13.9375 62.4375 12.625 62.4375 10.6562C62.4375 8.68749 63.75 7.37499 65.7188 7.37499C66.9375 7.37499 67.9688 7.90624 68.5313 8.84374Z" fill="currentColor"/>
<path d="M88.2188 1.75H85.7188V15.8125H88.2188V1.75Z" fill="currentColor"/>
<path d="M40.1563 1.75H37.2813L31.7813 11.25L26.2813 1.75H23.375L31.7813 16.25L40.1563 1.75Z" fill="currentColor"/>
<path d="M57.8438 8.0625C58.125 8.0625 58.4062 8.09375 58.6875 8.15625V5.5C56.5625 5.5625 54.5625 6.75 54.5625 8.21875V5.5H52.0625V15.8125H54.5625V11.3437C54.5625 9.40625 55.9062 8.0625 57.8438 8.0625Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -51,6 +51,9 @@ module.exports = {
},
lineHeight: {
'extra-loose': '2.2'
},
scale: {
'120': '1.2',
}
},
},

2313
yarn.lock

File diff suppressed because it is too large Load Diff