Layout product grid

This commit is contained in:
Jonatan Schultz 2021-08-26 16:56:23 +02:00
parent 75beec4c94
commit 7f6999629a
15 changed files with 11056 additions and 142 deletions

View File

@ -18,7 +18,7 @@
--accent-0: #fff;
--accent-1: #fafafa;
--accent-2: #eaeaea;
--accent-2: #e2e2e2;
--accent-3: #b4afaf;
--accent-4: #888888;
--accent-5: #666666;
@ -27,8 +27,6 @@
--accent-8: #111111;
--accent-9: #000;
--font-sans: 'Inter', sans-serif;
--cyan: #22b8cf;
--green: #37b679;
--purple: #f81ce5;
@ -39,46 +37,53 @@
--violet-dark: #4c2889;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
@layer base {
*,
*:before,
*:after {
box-sizing: inherit;
letter-spacing: -0.025em;
}
html {
height: 100%;
box-sizing: border-box;
touch-action: manipulation;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@apply text-html;
}
@screen lg {
html {
@apply text-html-lg;
height: 100%;
box-sizing: border-box;
touch-action: manipulation;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@apply text-html;
}
@screen lg {
html {
@apply text-html-lg;
}
}
html,
body {
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: var(--primary);
color: var(--text-primary);
overscroll-behavior-x: none;
}
body {
position: relative;
min-height: 100%;
margin: 0;
}
a {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
}
html,
body {
font-family: var(--font-sans);
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: var(--primary);
color: var(--text-primary);
overscroll-behavior-x: none;
}
body {
position: relative;
min-height: 100%;
margin: 0;
}
a {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
.tag {
@apply inline-block py-2 px-5 text-4xl border border-black rounded-full;
}
.animated {

View File

@ -57,11 +57,6 @@ const HomeAllProductsGrid: FC<Props> = ({
<ProductCard
key={product.path}
product={product}
variant="simple"
imgProps={{
width: 480,
height: 480,
}}
/>
))}
</Grid>

View File

@ -1,15 +1,10 @@
.root {
@apply relative max-h-full w-full box-border overflow-hidden
bg-no-repeat bg-center bg-cover transition-transform
ease-linear cursor-pointer inline-block bg-accent-1;
transition-transform ease-linear cursor-pointer inline-block;
height: 100% !important;
}
.root:hover {
& .productImage {
transform: scale(1.2625);
}
& .header .name span,
& .header .price,
& .wishlistButton {
@ -69,22 +64,23 @@
}
.imageContainer {
@apply flex items-center justify-center overflow-hidden;
@apply relative flex items-center justify-center bg-primary-2 mb-4;
padding: 12% 15%;
}
.imageContainer > div {
min-width: 100%;
}
.imageContainer .productImage {
@apply transform transition-transform duration-500
object-cover scale-120;
.imageContainerInner {
@apply relative w-full;
padding-bottom: 100%;
}
.root .wishlistButton {
@apply top-0 right-0 z-30 absolute;
}
.typeIcon {
@apply absolute bg-accent-2 rounded-full p-1.5 -bottom-2 right-2.5;
font-size: 0;
}
/* Variant Simple */
.simple .header .name {
@apply pt-2 text-lg leading-10 -mt-1;

View File

@ -97,31 +97,35 @@ const ProductCard: FC<Props> = ({
{variant === 'default' && (
<>
{process.env.COMMERCE_WISHLIST_ENABLED && (
<WishlistButton
className={s.wishlistButton}
productId={product.id}
variant={product.variants[0] as any}
/>
)}
<ProductTag
name={product.name}
price={`${price} ${product.price?.currencyCode}`}
/>
<div className={s.imageContainer}>
{product?.images && (
<div className={s.imageContainerInner}>
{product?.images && (
<Image
alt={product.name || 'Product Image'}
className={s.productImage}
src={product.images[0]?.url || placeholderImg}
quality="85"
layout="fill"
objectFit="contain"
{...imgProps}
/>
)}
</div>
<div className={s.typeIcon}>
<Image
alt={product.name || 'Product Image'}
className={s.productImage}
src={product.images[0]?.url || placeholderImg}
height={540}
width={540}
quality="85"
layout="responsive"
{...imgProps}
src="/icon-audiobook.svg"
width={22}
height={23}
/>
)}
</div>
</div>
<div className="font-bold line-clamp-3">
{product.name}
</div>
<div className="italic">
Author (missing data)
</div>
<div>{price}</div>
</>
)}
</a>

View File

@ -38,7 +38,7 @@
}
.relatedProductsGrid {
@apply grid grid-cols-2 py-2 gap-2 md:grid-cols-4 md:gap-7;
@apply grid grid-cols-2 py-2 gap-2 md:grid-cols-6 md:gap-7;
}
@screen lg {

View File

@ -67,18 +67,13 @@ const ProductView: FC<ProductViewProps> = ({ product, relatedProducts }) => {
{relatedProducts.map((p) => (
<div
key={p.path}
className="animated fadeIn bg-accent-0 border border-accent-2"
className="animated fadeIn"
>
<ProductCard
noNameTag
product={p}
key={p.path}
variant="simple"
className="animated fadeIn"
imgProps={{
width: 300,
height: 300,
}}
/>
</div>
))}

View File

@ -313,17 +313,12 @@ export default function Search({ categories, brands }: SearchPropsType) {
</div>
)}
{data ? (
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
{data.products.map((product: Product) => (
<ProductCard
variant="simple"
key={product.path}
className="animated fadeIn"
product={product}
imgProps={{
width: 480,
height: 480,
}}
/>
))}
</div>

View File

@ -1,8 +1,8 @@
.root {
@apply grid grid-cols-1 gap-0;
@apply grid grid-cols-2 gap-0;
@screen lg {
@apply grid-cols-3 grid-rows-2;
@apply grid-cols-6;
}
& > * {
@ -24,7 +24,7 @@
}
.layoutNormal {
@apply gap-3;
@apply gap-6;
}
@screen md {

10932
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,7 @@
},
"dependencies": {
"@react-spring/web": "^9.2.1",
"@tailwindcss/line-clamp": "^0.2.1",
"@vercel/fetch": "^6.1.0",
"autoprefixer": "^10.2.6",
"body-scroll-lock": "^3.1.5",

View File

@ -1,8 +1,7 @@
import commerce from '@lib/api/commerce'
import { Layout } from '@components/common'
import { ProductCard } from '@components/product'
import { Grid, Marquee, Hero } from '@components/ui'
// import HomeAllProductsGrid from '@components/common/HomeAllProductsGrid'
import { Grid, Container, Marquee } from '@components/ui'
import type { GetStaticPropsContext, InferGetStaticPropsType } from 'next'
export async function getStaticProps({
@ -15,8 +14,6 @@ export async function getStaticProps({
variables: { first: 6 },
config,
preview,
// Saleor provider only
...({ featured: true } as any),
})
const pagesPromise = commerce.getAllPages({ config, preview })
const siteInfoPromise = commerce.getSiteInfo({ config, preview })
@ -40,49 +37,26 @@ export default function Home({
}: InferGetStaticPropsType<typeof getStaticProps>) {
return (
<>
<Grid variant="filled">
{products.slice(0, 3).map((product: any, i: number) => (
<ProductCard
key={product.id}
product={product}
imgProps={{
width: i === 0 ? 1080 : 540,
height: i === 0 ? 1080 : 540,
}}
/>
))}
</Grid>
<Marquee variant="secondary">
{products.slice(0, 3).map((product: any, i: number) => (
<ProductCard key={product.id} product={product} variant="slim" />
))}
</Marquee>
<Hero
headline=" Dessert dragée halvah croissant."
description="Cupcake ipsum dolor sit amet lemon drops pastry cotton candy. Sweet carrot cake macaroon bonbon croissant fruitcake jujubes macaroon oat cake. Soufflé bonbon caramels jelly beans. Tiramisu sweet roll cheesecake pie carrot cake. "
/>
<Grid layout="B" variant="filled">
{products.slice(0, 3).map((product: any, i: number) => (
<ProductCard
key={product.id}
product={product}
imgProps={{
width: i === 0 ? 1080 : 540,
height: i === 0 ? 1080 : 540,
}}
/>
))}
</Grid>
<Marquee>
{products.slice(3).map((product: any, i: number) => (
<ProductCard key={product.id} product={product} variant="slim" />
))}
</Marquee>
{/* <HomeAllProductsGrid
newestProducts={products}
categories={categories}
brands={brands}
/> */}
<Container className="py-12">
<h3 className="tag">New releases</h3>
<Grid layout="normal" className="mt-8 mb-16">
{products.slice(0, 6).map((product: any, i: number) => (
<ProductCard
key={product.id}
product={product}
/>
))}
</Grid>
<h3 className="tag">Bestsellers</h3>
<Grid layout="normal" className="mt-8 mb-16">
{products.slice(0, 6).map((product: any, i: number) => (
<ProductCard
key={product.id}
product={product}
/>
))}
</Grid>
</Container>
</>
)
}

View File

@ -24,7 +24,7 @@ export async function getStaticProps({
})
const allProductsPromise = commerce.getAllProducts({
variables: { first: 4 },
variables: { first: 6 },
config,
preview,
})

View File

@ -0,0 +1,3 @@
<svg width="30" height="32" viewBox="3 2.5 26 27.5" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" fill="currentColor" d="M16 4.5c-4.4183 0-8 3.58172-8 8v2c0 .5523-.44772 1-1 1s-1-.4477-1-1v-2c0-5.52285 4.4772-10 10-10s10 4.47715 10 10v2c0 .5523-.4477 1-1 1s-1-.4477-1-1v-2c0-4.41828-3.5817-8-8-8zM9 25v-3.5c0-1.1046-.89543-2-2-2s-2 .8954-2 2V25c0 1.1046.89543 2 2 2s2-.8954 2-2zm-2-7.5c-2.20914 0-4 1.7909-4 4V25c0 2.2091 1.79086 4 4 4s4-1.7909 4-4v-3.5c0-2.2091-1.79086-4-4-4zm20 4V25c0 1.1046-.8954 2-2 2s-2-.8954-2-2v-3.5c0-1.1046.8954-2 2-2s2 .8954 2 2zm-6 0c0-2.2091 1.7909-4 4-4 2.2091 0 4 1.7909 4 4V25c0 2.2091-1.7909 4-4 4-2.2091 0-4-1.7909-4-4v-3.5z"></path>
</svg>

After

Width:  |  Height:  |  Size: 726 B

3
public/icon-ebook.svg Normal file
View File

@ -0,0 +1,3 @@
<svg width="23" height="32" viewBox="6 3 20 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" fill="currentColor" d="M22.5 5h-13C8.67157 5 8 5.67157 8 6.5v20c0 .8284.67157 1.5 1.5 1.5h13c.8284 0 1.5-.6716 1.5-1.5v-20c0-.82843-.6716-1.5-1.5-1.5zm-13-2C7.567 3 6 4.567 6 6.5v20C6 28.433 7.567 30 9.5 30h13c1.933 0 3.5-1.567 3.5-3.5v-20C26 4.567 24.433 3 22.5 3h-13zM22 9c0 .55228-.4477 1-1 1H11c-.5523 0-1-.44772-1-1s.4477-1 1-1h10c.5523 0 1 .44772 1 1zm-1 5c.5523 0 1-.4477 1-1s-.4477-1-1-1H11c-.5523 0-1 .4477-1 1s.4477 1 1 1h10zm-2.5 3c0 .5523-.4477 1-1 1H11c-.5523 0-1-.4477-1-1s.4477-1 1-1h6.5c.5523 0 1 .4477 1 1zM16 26c1.1046 0 2-.8954 2-2s-.8954-2-2-2-2 .8954-2 2 .8954 2 2 2z"></path>
</svg>

After

Width:  |  Height:  |  Size: 749 B

View File

@ -1,4 +1,5 @@
module.exports = {
plugins: [require('@tailwindcss/line-clamp')],
future: {
purgeLayersByDefault: true,
applyComplexClasses: true,
@ -58,9 +59,13 @@ module.exports = {
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',
},
fontFamily: {
sans: '"Inter","Helvetica Neue",HelveticaNeue,"TeX Gyre Heros",TeXGyreHeros,FreeSans,"Nimbus Sans L","Liberation Sans",Arimo,Helvetica,sans-serif',
},
fontSize: {
html: '15px',
'html-lg': '18px',
'4xl': '2rem',
},
lineHeight: {
'extra-loose': '2.2',
@ -68,6 +73,12 @@ module.exports = {
scale: {
120: '1.2',
},
width: {
'9/12': '75%',
},
height: {
'9/12': '75%',
},
},
},
}