mirror of
https://github.com/vercel/commerce.git
synced 2025-07-06 13:01:22 +00:00
Layout product grid
This commit is contained in:
parent
75beec4c94
commit
7f6999629a
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
--accent-0: #fff;
|
--accent-0: #fff;
|
||||||
--accent-1: #fafafa;
|
--accent-1: #fafafa;
|
||||||
--accent-2: #eaeaea;
|
--accent-2: #e2e2e2;
|
||||||
--accent-3: #b4afaf;
|
--accent-3: #b4afaf;
|
||||||
--accent-4: #888888;
|
--accent-4: #888888;
|
||||||
--accent-5: #666666;
|
--accent-5: #666666;
|
||||||
@ -27,8 +27,6 @@
|
|||||||
--accent-8: #111111;
|
--accent-8: #111111;
|
||||||
--accent-9: #000;
|
--accent-9: #000;
|
||||||
|
|
||||||
--font-sans: 'Inter', sans-serif;
|
|
||||||
|
|
||||||
--cyan: #22b8cf;
|
--cyan: #22b8cf;
|
||||||
--green: #37b679;
|
--green: #37b679;
|
||||||
--purple: #f81ce5;
|
--purple: #f81ce5;
|
||||||
@ -39,10 +37,12 @@
|
|||||||
--violet-dark: #4c2889;
|
--violet-dark: #4c2889;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
*,
|
*,
|
||||||
*:before,
|
*:before,
|
||||||
*:after {
|
*:after {
|
||||||
box-sizing: inherit;
|
box-sizing: inherit;
|
||||||
|
letter-spacing: -0.025em;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
@ -62,7 +62,6 @@ html {
|
|||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
font-family: var(--font-sans);
|
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
@ -80,6 +79,12 @@ body {
|
|||||||
a {
|
a {
|
||||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
-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 {
|
.animated {
|
||||||
-webkit-animation-duration: 1s;
|
-webkit-animation-duration: 1s;
|
||||||
|
@ -57,11 +57,6 @@ const HomeAllProductsGrid: FC<Props> = ({
|
|||||||
<ProductCard
|
<ProductCard
|
||||||
key={product.path}
|
key={product.path}
|
||||||
product={product}
|
product={product}
|
||||||
variant="simple"
|
|
||||||
imgProps={{
|
|
||||||
width: 480,
|
|
||||||
height: 480,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -1,15 +1,10 @@
|
|||||||
.root {
|
.root {
|
||||||
@apply relative max-h-full w-full box-border overflow-hidden
|
@apply relative max-h-full w-full box-border overflow-hidden
|
||||||
bg-no-repeat bg-center bg-cover transition-transform
|
transition-transform ease-linear cursor-pointer inline-block;
|
||||||
ease-linear cursor-pointer inline-block bg-accent-1;
|
|
||||||
height: 100% !important;
|
height: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.root:hover {
|
.root:hover {
|
||||||
& .productImage {
|
|
||||||
transform: scale(1.2625);
|
|
||||||
}
|
|
||||||
|
|
||||||
& .header .name span,
|
& .header .name span,
|
||||||
& .header .price,
|
& .header .price,
|
||||||
& .wishlistButton {
|
& .wishlistButton {
|
||||||
@ -69,22 +64,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.imageContainer {
|
.imageContainer {
|
||||||
@apply flex items-center justify-center overflow-hidden;
|
@apply relative flex items-center justify-center bg-primary-2 mb-4;
|
||||||
|
padding: 12% 15%;
|
||||||
}
|
}
|
||||||
|
.imageContainerInner {
|
||||||
.imageContainer > div {
|
@apply relative w-full;
|
||||||
min-width: 100%;
|
padding-bottom: 100%;
|
||||||
}
|
|
||||||
|
|
||||||
.imageContainer .productImage {
|
|
||||||
@apply transform transition-transform duration-500
|
|
||||||
object-cover scale-120;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.root .wishlistButton {
|
.root .wishlistButton {
|
||||||
@apply top-0 right-0 z-30 absolute;
|
@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 */
|
/* Variant Simple */
|
||||||
.simple .header .name {
|
.simple .header .name {
|
||||||
@apply pt-2 text-lg leading-10 -mt-1;
|
@apply pt-2 text-lg leading-10 -mt-1;
|
||||||
|
@ -97,31 +97,35 @@ const ProductCard: FC<Props> = ({
|
|||||||
|
|
||||||
{variant === 'default' && (
|
{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}>
|
<div className={s.imageContainer}>
|
||||||
|
<div className={s.imageContainerInner}>
|
||||||
{product?.images && (
|
{product?.images && (
|
||||||
<Image
|
<Image
|
||||||
alt={product.name || 'Product Image'}
|
alt={product.name || 'Product Image'}
|
||||||
className={s.productImage}
|
className={s.productImage}
|
||||||
src={product.images[0]?.url || placeholderImg}
|
src={product.images[0]?.url || placeholderImg}
|
||||||
height={540}
|
|
||||||
width={540}
|
|
||||||
quality="85"
|
quality="85"
|
||||||
layout="responsive"
|
layout="fill"
|
||||||
|
objectFit="contain"
|
||||||
{...imgProps}
|
{...imgProps}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className={s.typeIcon}>
|
||||||
|
<Image
|
||||||
|
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>
|
</a>
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.relatedProductsGrid {
|
.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 {
|
@screen lg {
|
||||||
|
@ -67,18 +67,13 @@ const ProductView: FC<ProductViewProps> = ({ product, relatedProducts }) => {
|
|||||||
{relatedProducts.map((p) => (
|
{relatedProducts.map((p) => (
|
||||||
<div
|
<div
|
||||||
key={p.path}
|
key={p.path}
|
||||||
className="animated fadeIn bg-accent-0 border border-accent-2"
|
className="animated fadeIn"
|
||||||
>
|
>
|
||||||
<ProductCard
|
<ProductCard
|
||||||
noNameTag
|
noNameTag
|
||||||
product={p}
|
product={p}
|
||||||
key={p.path}
|
key={p.path}
|
||||||
variant="simple"
|
|
||||||
className="animated fadeIn"
|
className="animated fadeIn"
|
||||||
imgProps={{
|
|
||||||
width: 300,
|
|
||||||
height: 300,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
@ -313,17 +313,12 @@ export default function Search({ categories, brands }: SearchPropsType) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{data ? (
|
{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) => (
|
{data.products.map((product: Product) => (
|
||||||
<ProductCard
|
<ProductCard
|
||||||
variant="simple"
|
|
||||||
key={product.path}
|
key={product.path}
|
||||||
className="animated fadeIn"
|
className="animated fadeIn"
|
||||||
product={product}
|
product={product}
|
||||||
imgProps={{
|
|
||||||
width: 480,
|
|
||||||
height: 480,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
.root {
|
.root {
|
||||||
@apply grid grid-cols-1 gap-0;
|
@apply grid grid-cols-2 gap-0;
|
||||||
|
|
||||||
@screen lg {
|
@screen lg {
|
||||||
@apply grid-cols-3 grid-rows-2;
|
@apply grid-cols-6;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > * {
|
& > * {
|
||||||
@ -24,7 +24,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.layoutNormal {
|
.layoutNormal {
|
||||||
@apply gap-3;
|
@apply gap-6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@screen md {
|
@screen md {
|
||||||
|
10932
package-lock.json
generated
Normal file
10932
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-spring/web": "^9.2.1",
|
"@react-spring/web": "^9.2.1",
|
||||||
|
"@tailwindcss/line-clamp": "^0.2.1",
|
||||||
"@vercel/fetch": "^6.1.0",
|
"@vercel/fetch": "^6.1.0",
|
||||||
"autoprefixer": "^10.2.6",
|
"autoprefixer": "^10.2.6",
|
||||||
"body-scroll-lock": "^3.1.5",
|
"body-scroll-lock": "^3.1.5",
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import commerce from '@lib/api/commerce'
|
import commerce from '@lib/api/commerce'
|
||||||
import { Layout } from '@components/common'
|
import { Layout } from '@components/common'
|
||||||
import { ProductCard } from '@components/product'
|
import { ProductCard } from '@components/product'
|
||||||
import { Grid, Marquee, Hero } from '@components/ui'
|
import { Grid, Container, Marquee } from '@components/ui'
|
||||||
// import HomeAllProductsGrid from '@components/common/HomeAllProductsGrid'
|
|
||||||
import type { GetStaticPropsContext, InferGetStaticPropsType } from 'next'
|
import type { GetStaticPropsContext, InferGetStaticPropsType } from 'next'
|
||||||
|
|
||||||
export async function getStaticProps({
|
export async function getStaticProps({
|
||||||
@ -15,8 +14,6 @@ export async function getStaticProps({
|
|||||||
variables: { first: 6 },
|
variables: { first: 6 },
|
||||||
config,
|
config,
|
||||||
preview,
|
preview,
|
||||||
// Saleor provider only
|
|
||||||
...({ featured: true } as any),
|
|
||||||
})
|
})
|
||||||
const pagesPromise = commerce.getAllPages({ config, preview })
|
const pagesPromise = commerce.getAllPages({ config, preview })
|
||||||
const siteInfoPromise = commerce.getSiteInfo({ config, preview })
|
const siteInfoPromise = commerce.getSiteInfo({ config, preview })
|
||||||
@ -40,49 +37,26 @@ export default function Home({
|
|||||||
}: InferGetStaticPropsType<typeof getStaticProps>) {
|
}: InferGetStaticPropsType<typeof getStaticProps>) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Grid variant="filled">
|
<Container className="py-12">
|
||||||
{products.slice(0, 3).map((product: any, i: number) => (
|
<h3 className="tag">New releases</h3>
|
||||||
|
<Grid layout="normal" className="mt-8 mb-16">
|
||||||
|
{products.slice(0, 6).map((product: any, i: number) => (
|
||||||
<ProductCard
|
<ProductCard
|
||||||
key={product.id}
|
key={product.id}
|
||||||
product={product}
|
product={product}
|
||||||
imgProps={{
|
|
||||||
width: i === 0 ? 1080 : 540,
|
|
||||||
height: i === 0 ? 1080 : 540,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
<Marquee variant="secondary">
|
<h3 className="tag">Bestsellers</h3>
|
||||||
{products.slice(0, 3).map((product: any, i: number) => (
|
<Grid layout="normal" className="mt-8 mb-16">
|
||||||
<ProductCard key={product.id} product={product} variant="slim" />
|
{products.slice(0, 6).map((product: any, i: number) => (
|
||||||
))}
|
|
||||||
</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
|
<ProductCard
|
||||||
key={product.id}
|
key={product.id}
|
||||||
product={product}
|
product={product}
|
||||||
imgProps={{
|
|
||||||
width: i === 0 ? 1080 : 540,
|
|
||||||
height: i === 0 ? 1080 : 540,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
<Marquee>
|
</Container>
|
||||||
{products.slice(3).map((product: any, i: number) => (
|
|
||||||
<ProductCard key={product.id} product={product} variant="slim" />
|
|
||||||
))}
|
|
||||||
</Marquee>
|
|
||||||
{/* <HomeAllProductsGrid
|
|
||||||
newestProducts={products}
|
|
||||||
categories={categories}
|
|
||||||
brands={brands}
|
|
||||||
/> */}
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ export async function getStaticProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const allProductsPromise = commerce.getAllProducts({
|
const allProductsPromise = commerce.getAllProducts({
|
||||||
variables: { first: 4 },
|
variables: { first: 6 },
|
||||||
config,
|
config,
|
||||||
preview,
|
preview,
|
||||||
})
|
})
|
||||||
|
3
public/icon-audiobook.svg
Normal file
3
public/icon-audiobook.svg
Normal 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
3
public/icon-ebook.svg
Normal 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 |
@ -1,4 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
|
plugins: [require('@tailwindcss/line-clamp')],
|
||||||
future: {
|
future: {
|
||||||
purgeLayersByDefault: true,
|
purgeLayersByDefault: true,
|
||||||
applyComplexClasses: true,
|
applyComplexClasses: true,
|
||||||
@ -58,9 +59,13 @@ module.exports = {
|
|||||||
magical:
|
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',
|
'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: {
|
fontSize: {
|
||||||
html: '15px',
|
html: '15px',
|
||||||
'html-lg': '18px',
|
'html-lg': '18px',
|
||||||
|
'4xl': '2rem',
|
||||||
},
|
},
|
||||||
lineHeight: {
|
lineHeight: {
|
||||||
'extra-loose': '2.2',
|
'extra-loose': '2.2',
|
||||||
@ -68,6 +73,12 @@ module.exports = {
|
|||||||
scale: {
|
scale: {
|
||||||
120: '1.2',
|
120: '1.2',
|
||||||
},
|
},
|
||||||
|
width: {
|
||||||
|
'9/12': '75%',
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
'9/12': '75%',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user