Skip to content
131 changes: 110 additions & 21 deletions docs/faststore/components/molecules/product-card.mdx
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 [Grammar reviewer] reported by reviewdog 🐶
Corrected subject-verb agreement from 'They usually present' to 'It usually presents' because ProductCard is singular. Added a missing space after the period between 'image' and 'The'.

The `ProductCard` displays summarized information about a product. It usually presents a call-to-action button, as well as the product's name, price, and image. The `ProductCard` is composed of the following components:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 [Grammar reviewer] reported by reviewdog 🐶
In a heading, 'Buy Button' is typically written as two words for better readability, even if the corresponding prop is buyButton.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 [Grammar reviewer] reported by reviewdog 🐶
Changed 'on both' to 'to both' for more precise phrasing when referring to adding a prop. Added 'the' before 'outOfStock prop' for better flow.

isVariantOf: { name: "Apple Mouse" },

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 [Grammar reviewer] reported by reviewdog 🐶
Corrected the spelling error from 'Desing' to 'Design'.

return useMemo(() => formatter(price), [formatter, price]);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 [Grammar reviewer] reported by reviewdog 🐶
Corrected the spelling error from 'Desing' to 'Design'.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 [Grammar reviewer] reported by reviewdog 🐶
Improved clarity and conciseness by rephrasing 'all attributes also supported by' to 'the attributes of'. Hyphenated 'product card-related'. Changed 'Besides those attributes' to 'In addition to these attributes' for more formal and precise language.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 [Grammar reviewer] reported by reviewdog 🐶
Changed 'on the store' to 'within the store' for more natural and idiomatic phrasing in this context.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
---
title: "ProductCard"
excerpt: Displays summarized information about a product.
components:
Expand All @@ -25,25 +25,7 @@ Use the `ProductCard` to:
<OverviewSection
containerStyle={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr" }}
>
<ProductCard>
<ProductCardImage>
<img
data-fs-image
src={product.image[1].url}
alt={product.image[1].alternateName}
/>
</ProductCardImage>
<ProductCardContent
title={product.isVariantOf.name}
price={{
value: product.offers.offers[0].price,
listPrice: product.offers.offers[0].listPrice,
formatter: useFormattedPrice,
}}
ratingValue={3.5}
onButtonClick={() => {}}
/>
</ProductCard>
<ProductCardUsage />
</OverviewSection>
</Tab>
<Tab>
Expand Down Expand Up @@ -589,6 +571,111 @@ To replicate this style, add the prop to both `ProductCard` and `ProductCardCont
</Tab>
</Tabs>

### Button Click Action

<Tabs items={["Example", "Code"]} defaultIndex="0">
<Tab>
<OverviewSection containerStyle={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr" }}>
<ProductCard>
<ProductCardImage>
<img
data-fs-image
src={product.image[1].url}
alt={product.image[1].alternateName}
/>
</ProductCardImage>
<ProductCardContent
title={product.isVariantOf.name}
price={{
value: product.offers.offers[0].price,
listPrice: product.offers.offers[0].listPrice,
formatter: useFormattedPrice,
}}
ratingValue={4}
onButtonClick={() => console.log('Product action triggered')}
/>
</ProductCard>
</OverviewSection>
</Tab>
<Tab>
```tsx
import { useCallback, useMemo } from "react";
import {
ProductCard,
ProductCardImage,
ProductCardContent,
} from "@faststore/ui";

const product = {
isVariantOf: { name: "Apple Mouse" },
image: [
{},
{
url: "https://vtexhelp.vtexassets.com/assets/docs/img/faststore/product-placeholder___1e7c8f8d9f38b8a0a8f8a6a8a0f5e07d.png",
alternateName: "Apple Mouse",
},
],
offers: {
offers: [
{
price: 950.04,
listPrice: 999,
availability: "https://schema.org/InStock",
},
],
},
};

interface PriceFormatterOptions {
decimals?: boolean;
}
export const usePriceFormatter = ({ decimals }: PriceFormatterOptions = {}) => {
return useCallback(
(price: number) =>
Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
minimumFractionDigits: decimals ? 2 : 0,
}).format(price),
[decimals]
);
};
export const useFormattedPrice = (price: number) => {
const formatter = usePriceFormatter();
return useMemo(() => formatter(price), [formatter, price]);
};

export function Example() {
const handleClick = () => {
console.log("Product action triggered");
};

return (
<ProductCard>
<ProductCardImage>
<img
data-fs-image
src={product.image[1].url}
alt={product.image[1].alternateName}
/>
</ProductCardImage>
<ProductCardContent
title={product.isVariantOf.name}
price={{
value: product.offers.offers[0].price,
listPrice: product.offers.offers[0].listPrice,
formatter: useFormattedPrice,
}}
ratingValue={4}
onButtonClick={handleClick}
/>
</ProductCard>
);
}
```
</Tab>
</Tabs>

---

## Design tokens
Expand Down Expand Up @@ -766,7 +853,9 @@ Adjusts the bordered variant outline via border width and color for a subtle fra
/>
</TokenTable>

#### Wide
### Design tokens: Wide

Defines layout and spacing for the wide variant, covering padding, content padding, minimum width, and background color.

<TokenTable>
<TokenRow token="--fs-product-card-wide-padding" value="0" />
Expand Down
Loading