Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tech: Create Card UI component #4690

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions apps/store/src/blocks/ProductGridBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use client'

import { storyblokEditable } from '@storyblok/react'
import type { ProductCardBlockProps } from '@/blocks/ProductCardBlock'
import { ProductCardBlock } from '@/blocks/ProductCardBlock'
import type { ProductCardBlockProps } from '@/blocks/ProductGridItemBlock/ProductGridItemBlock'
import { ProductGridItemBlock } from '@/blocks/ProductGridItemBlock/ProductGridItemBlock'
import { ProductGrid } from '@/components/ProductGrid/ProductGrid'
import type { ExpectedBlockType, SbBaseBlockProps } from '@/services/storyblok/storyblok'

Expand All @@ -15,7 +15,7 @@ export const ProductGridBlock = ({ blok }: ProductGridBlockProps) => {
return (
<ProductGrid title={blok.title} {...storyblokEditable(blok)}>
{blok.items.map((nestedBlock) => (
<ProductCardBlock key={nestedBlock._uid || nestedBlock.title} blok={nestedBlock} />
<ProductGridItemBlock key={nestedBlock._uid || nestedBlock.title} blok={nestedBlock} />
))}
</ProductGrid>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { type useProductMetadata } from '@/components/LayoutWithMenu/productMetadataHooks'
import { isSameLink } from '@/utils/url'


export type LinkType = 'product' | 'category'

export const getLinkType = (
productMetadata: ReturnType<typeof useProductMetadata> = [],
link: string,
): LinkType | 'content' => {
const isProductLink = productMetadata?.some((product) => isSameLink(link, product.pageLink))
if (isProductLink) {
return 'product'
}

const isCategoryLink = productMetadata?.some(
(product) => product.categoryPageLink && isSameLink(link, product.categoryPageLink),
)
if (isCategoryLink) {
return 'category'
}

return 'content'
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
'use client'

import { storyblokEditable } from '@storyblok/react'
import { useProductMetadata } from '@/components/LayoutWithMenu/productMetadataHooks'
import { type LinkType, ProductCard } from '@/components/ProductCard/ProductCard'
import { ProductGridItem } from '@/components/ProductGridItem/ProductGridItem'
import type { LinkField, SbBaseBlockProps, StoryblokAsset } from '@/services/storyblok/storyblok'
import { getImgSrc, getLinkFieldURL } from '@/services/storyblok/Storyblok.helpers'
import { isSameLink } from '@/utils/url'
import { getLinkType } from './ProductGridItemBlock.helpers'

export type ImageSize = {
aspectRatio?: '1 / 1' | '3 / 2' | '4 / 3' | '5 / 4' | '2 / 3' | '3 / 4' | '4 / 5'
Expand All @@ -20,20 +21,21 @@ export type ProductCardBlockProps = SbBaseBlockProps<
} & ImageSize
>

export const ProductCardBlock = ({ blok }: ProductCardBlockProps) => {
export const ProductGridItemBlock = ({ blok }: ProductCardBlockProps) => {
const link = getLinkFieldURL(blok.link, blok.title)
const productMetadata = useProductMetadata()
const linkType = getLinkType(productMetadata, link)

if (linkType === 'content') {
console.warn(
'[ProductCardBlock]: provided "link" does not refer to a product neither a category. Skipping ProductCard render!',
'[ProductGridItemBlock]: provided "link" does not refer to a product neither a category. Skipping ProductGridItem render!',
)

return null
}

return (
<ProductCard
<ProductGridItem
title={blok.title}
subtitle={blok.subtitle}
image={{ src: getImgSrc(blok.image.filename), alt: blok.image.alt, priority: blok.priority }}
Expand All @@ -43,22 +45,3 @@ export const ProductCardBlock = ({ blok }: ProductCardBlockProps) => {
/>
)
}

const getLinkType = (
productMetadata: ReturnType<typeof useProductMetadata> = [],
link: string,
): LinkType | 'content' => {
const isProductLink = productMetadata?.some((product) => isSameLink(link, product.pageLink))
if (isProductLink) {
return 'product'
}

const isCategoryLink = productMetadata?.some(
(product) => product.categoryPageLink && isSameLink(link, product.categoryPageLink),
)
if (isCategoryLink) {
return 'category'
}

return 'content'
}
64 changes: 13 additions & 51 deletions apps/store/src/components/Pillow/Pillow.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,21 @@
import clsx from 'clsx'
import Image from 'next/image'
import { memo } from 'react'
import { type Level } from 'ui'
import { BasePillow, type PillowProps } from 'ui'
import { getImgSrc } from '@/services/storyblok/Storyblok.helpers'
import { pillowVariants } from './Pillow.css'

type PillowSize =
| 'mini'
| 'xxsmall'
| 'xsmall'
| 'small'
| 'medium'
| 'large'
| 'xlarge'
| 'xxlarge'

type PillowProps = {
size: PillowSize | Partial<Record<Level | '_', PillowSize>>
src?: string
alt?: string | null
priority?: boolean
className?: string
}

export const Pillow = memo(({ alt, src, priority, className, size, ...props }: PillowProps) => {
if (!src) return <FallbackPillow {...props} size={size} />
export const Pillow = memo(({ alt, src, ...props }: PillowProps) => {
return (
<Image
{...props}
className={clsx(pillowVariants(size), className)}
src={getImgSrc(src)}
alt={alt ?? ''}
width={208}
height={208}
decoding="sync"
priority={priority}
quality={70}
/>
<BasePillow shouldFallback={!src} {...props}>
<Image
// Just to make TS happy, will fallback if `src` is unavailable
src={getImgSrc(src!)}
alt={alt ?? ''}
width={208}
height={208}
decoding="sync"
quality={70}
/>
</BasePillow>
)
})
Pillow.displayName = 'Pillow'

const FallbackPillow = ({ size, className, ...props }: PillowProps) => {
return (
<svg
{...props}
className={clsx(pillowVariants(size), className)}
viewBox="0 0 480 480"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M3.79613e-05 240C2.56137e-05 428.992 101.382 480 240.298 480C379.214 480 480 432.012 480 240C480 47.9875 396.228 -5.43757e-05 240.298 -4.198e-05C84.3668 -6.01019e-05 5.03089e-05 51.0075 3.79613e-05 240Z"
fill="#F5F5F5"
/>
</svg>
)
}
168 changes: 0 additions & 168 deletions apps/store/src/components/ProductCard/ProductCard.tsx

This file was deleted.

10 changes: 6 additions & 4 deletions apps/store/src/components/ProductGrid/ProductGrid.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { Meta, StoryFn } from '@storybook/react'
import type { ProductCardProps } from '@/components/ProductCard/ProductCard'
import { ProductCard } from '@/components/ProductCard/ProductCard'
import {
ProductGridItem,
type ProductGridItemProps,
} from '@/components/ProductGridItem/ProductGridItem'
import type { ProductGridProps } from './ProductGrid'
import { ProductGrid } from './ProductGrid'

Expand All @@ -16,13 +18,13 @@ const meta: Meta<typeof ProductGrid> = {

export default meta

type ProductItem = ProductCardProps
type ProductItem = ProductGridItemProps

const Template: StoryFn<ProductGridProps & { items: Array<ProductItem> }> = (props) => {
return (
<ProductGrid {...props}>
{props.items.map((itemProps) => (
<ProductCard key={itemProps.title} {...itemProps} />
<ProductGridItem key={itemProps.title} {...itemProps} />
))}
</ProductGrid>
)
Expand Down
Loading