Update home page UI (#1068)

* home page updated UI design

* prettier

* remove unused bg color prop

* change label margin on carousol labels

* move label ui into own component

* change space-x from 6 to 4 in carousel

---------

Co-authored-by: Michael Novotny <manovotny@gmail.com>
This commit is contained in:
Stephanie Dietz 2023-07-11 15:36:46 -05:00 committed by GitHub
parent 7bad98965a
commit 65bd26b090
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 58 deletions

View File

@ -1,6 +1,7 @@
import { getCollectionProducts } from 'lib/shopify'; import { getCollectionProducts } from 'lib/shopify';
import Image from 'next/image'; import Image from 'next/image';
import Link from 'next/link'; import Link from 'next/link';
import Label from './label';
export async function Carousel() { export async function Carousel() {
// Collections that start with `hidden-*` are hidden from the search page. // Collections that start with `hidden-*` are hidden from the search page.
@ -9,13 +10,13 @@ export async function Carousel() {
if (!products?.length) return null; if (!products?.length) return null;
return ( return (
<div className="relative w-full overflow-hidden bg-black dark:bg-white"> <div className="relative w-full overflow-hidden pb-6">
<div className="flex animate-carousel"> <div className="flex animate-carousel space-x-4">
{[...products, ...products].map((product, i) => ( {[...products, ...products].map((product, i) => (
<Link <Link
key={`${product.handle}${i}`} key={`${product.handle}${i}`}
href={`/product/${product.handle}`} href={`/product/${product.handle}`}
className="relative h-[30vh] w-1/2 flex-none md:w-1/3" className="relative h-[30vh] w-2/3 flex-none rounded-lg border border-gray-200 bg-white dark:border-gray-800 dark:bg-black md:w-1/3"
> >
{product.featuredImage ? ( {product.featuredImage ? (
<Image <Image
@ -26,11 +27,11 @@ export async function Carousel() {
src={product.featuredImage.url} src={product.featuredImage.url}
/> />
) : null} ) : null}
<div className="absolute inset-y-0 right-0 flex items-center justify-center"> <Label
<div className="inline-flex bg-white p-4 text-xl font-semibold text-black dark:bg-black dark:text-white"> title={product.title}
{product.title} amount={product.priceRange.maxVariantPrice.amount}
</div> currencyCode={product.priceRange.maxVariantPrice.currencyCode}
</div> />
</Link> </Link>
))} ))}
</div> </div>

View File

@ -2,7 +2,7 @@ import clsx from 'clsx';
function Grid(props: React.ComponentProps<'ul'>) { function Grid(props: React.ComponentProps<'ul'>) {
return ( return (
<ul {...props} className={clsx('grid grid-flow-row gap-4 py-5', props.className)}> <ul {...props} className={clsx('grid grid-flow-row gap-4 py-5', props.className)}>
{props.children} {props.children}
</ul> </ul>
); );

View File

@ -3,26 +3,18 @@ import { getCollectionProducts } from 'lib/shopify';
import type { Product } from 'lib/shopify/types'; import type { Product } from 'lib/shopify/types';
import Link from 'next/link'; import Link from 'next/link';
function ThreeItemGridItem({ function ThreeItemGridItem({ item, size }: { item: Product; size: 'full' | 'half' }) {
item,
size,
background
}: {
item: Product;
size: 'full' | 'half';
background: 'white' | 'pink' | 'purple' | 'black';
}) {
return ( return (
<div <div
className={size === 'full' ? 'lg:col-span-4 lg:row-span-2' : 'lg:col-span-2 lg:row-span-1'} className={size === 'full' ? 'lg:col-span-4 lg:row-span-2' : 'lg:col-span-2 lg:row-span-1'}
> >
<Link className="block h-full" href={`/product/${item.handle}`}> <Link className="block h-full p-2" href={`/product/${item.handle}`}>
<GridTileImage <GridTileImage
src={item.featuredImage.url} src={item.featuredImage.url}
width={size === 'full' ? 1080 : 540} width={size === 'full' ? 1080 : 540}
height={size === 'full' ? 1080 : 540} height={size === 'full' ? 1080 : 540}
labelPosition={size === 'full' ? 'center' : 'bottom'}
priority={true} priority={true}
background={background}
alt={item.title} alt={item.title}
labels={{ labels={{
title: item.title as string, title: item.title as string,
@ -46,10 +38,10 @@ export async function ThreeItemGrid() {
const [firstProduct, secondProduct, thirdProduct] = homepageItems; const [firstProduct, secondProduct, thirdProduct] = homepageItems;
return ( return (
<section className="lg:grid lg:grid-cols-6 lg:grid-rows-2" data-testid="homepage-products"> <section className="p-2 lg:grid lg:grid-cols-6 lg:grid-rows-2" data-testid="homepage-products">
<ThreeItemGridItem size="full" item={firstProduct} background="purple" /> <ThreeItemGridItem size="full" item={firstProduct} />
<ThreeItemGridItem size="half" item={secondProduct} background="black" /> <ThreeItemGridItem size="half" item={secondProduct} />
<ThreeItemGridItem size="half" item={thirdProduct} background="pink" /> <ThreeItemGridItem size="half" item={thirdProduct} />
</section> </section>
); );
} }

View File

@ -1,18 +1,17 @@
import clsx from 'clsx'; import clsx from 'clsx';
import Image from 'next/image'; import Image from 'next/image';
import Label from '../label';
import Price from 'components/price';
export function GridTileImage({ export function GridTileImage({
isInteractive = true, isInteractive = true,
background,
active, active,
labelPosition,
labels, labels,
...props ...props
}: { }: {
isInteractive?: boolean; isInteractive?: boolean;
background?: 'white' | 'pink' | 'purple' | 'black' | 'purple-dark' | 'blue' | 'cyan' | 'gray';
active?: boolean; active?: boolean;
labelPosition?: 'bottom' | 'center';
labels?: { labels?: {
title: string; title: string;
amount: string; amount: string;
@ -22,18 +21,12 @@ export function GridTileImage({
} & React.ComponentProps<typeof Image>) { } & React.ComponentProps<typeof Image>) {
return ( return (
<div <div
className={clsx('relative flex h-full w-full items-center justify-center overflow-hidden', { className={clsx(
'bg-white dark:bg-white': background === 'white', 'relative flex h-full w-full items-center justify-center overflow-hidden rounded-lg border border-gray-200 bg-white dark:border-gray-800 dark:bg-black',
'bg-[#ff0080] dark:bg-[#ff0080]': background === 'pink', {
'bg-[#7928ca] dark:bg-[#7928ca]': background === 'purple', relative: labels
'bg-gray-900 dark:bg-gray-900': background === 'black', }
'bg-violetDark dark:bg-violetDark': background === 'purple-dark', )}
'bg-blue-500 dark:bg-blue-500': background === 'blue',
'bg-cyan-500 dark:bg-cyan-500': background === 'cyan',
'bg-gray-100 dark:bg-gray-100': background === 'gray',
'bg-gray-100 dark:bg-gray-900': !background,
relative: labels
})}
> >
{active !== undefined && active ? ( {active !== undefined && active ? (
<span className="absolute h-full w-full bg-white opacity-25"></span> <span className="absolute h-full w-full bg-white opacity-25"></span>
@ -48,22 +41,13 @@ export function GridTileImage({
/> />
) : null} ) : null}
{labels ? ( {labels ? (
<div className="absolute left-0 top-0 w-3/4 text-black dark:text-white"> <Label
<h3 title={labels.title}
data-testid="product-name" amount={labels.amount}
className={clsx( currencyCode={labels.currencyCode}
'inline bg-white box-decoration-clone py-3 pl-5 font-semibold leading-loose shadow-[1.25rem_0_0] shadow-white dark:bg-black dark:shadow-black', size="large"
!labels.isSmall ? 'text-3xl' : 'text-lg' position={labelPosition}
)} />
>
{labels.title}
</h3>
<Price
className="w-fit bg-white px-5 py-3 text-sm font-semibold dark:bg-black dark:text-white"
amount={labels.amount}
currencyCode={labels.currencyCode}
/>
</div>
) : null} ) : null}
</div> </div>
); );

41
components/label.tsx Normal file
View File

@ -0,0 +1,41 @@
import clsx from 'clsx';
import Price from './price';
const Label = ({
title,
amount,
currencyCode,
position,
size
}: {
title: string;
amount: string;
currencyCode: string;
position?: 'bottom' | 'center';
size?: 'large' | 'small';
}) => {
return (
<div
className={clsx(
'absolute bottom-0 left-0 flex items-center rounded-full border bg-white/80 p-1 text-black backdrop-blur-md dark:border-gray-800 dark:bg-black/80 dark:text-white',
size === 'large' ? 'text-sm' : 'text-xs',
position === 'center'
? 'mb-4 ml-4 md:mb-8 md:ml-8 lg:mb-[35%] lg:ml-20'
: size === 'large'
? 'mb-4 ml-4 md:mb-8 md:ml-8'
: 'mb-4 ml-4'
)}
>
<h3 data-testid="product-name" className="mr-6 inline pl-2 font-semibold">
{title}
</h3>
<Price
className="flex-none rounded-full bg-blue-600 p-2 font-semibold text-white"
amount={amount}
currencyCode={currencyCode}
/>
</div>
);
};
export default Label;

View File

@ -41,7 +41,6 @@ export function Gallery({
height={600} height={600}
isInteractive={false} isInteractive={false}
priority={true} priority={true}
background="purple"
labels={{ labels={{
title, title,
amount, amount,
@ -86,7 +85,6 @@ export function Gallery({
src={image.src} src={image.src}
width={600} width={600}
height={600} height={600}
background="purple-dark"
active={isActive} active={isActive}
/> />
</button> </button>