Docs Components Commerce

ProductCard

React example follows below.
ts
import * as React from "react";
const productCardFixture = {
id: "product-card",
name: "Forged steel trowel",
price: 3200,
compareAt: 4000,
image:
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 300'%3E%3Crect width='400' height='300' fill='%23e8e8ea'/%3E%3Crect x='140' y='90' width='120' height='120' rx='8' fill='%23c9c9cf'/%3E%3C/svg%3E",
rating: 4.8,
reviewCount: 64,
badge: "Sale",
wishlisted: false,
} satisfies {
id: string;
name: string;
price: number;
compareAt: number;
image: string;
rating: number;
reviewCount: number;
badge: string;
wishlisted: boolean;
};
import { ProductCard } from "@grassroot/ui-react";
export default function ProductCardDemo() {
const [wishlisted, setWishlisted] = React.useState<boolean>(productCardFixture.wishlisted);
return (
<div>
<ProductCard
name={productCardFixture.name}
price={productCardFixture.price}
compareAt={productCardFixture.compareAt}
image={productCardFixture.image}
rating={productCardFixture.rating}
reviewCount={productCardFixture.reviewCount}
badge={productCardFixture.badge}
wishlisted={wishlisted}
onToggleWishlist={setWishlisted}
onAddToCart={() => {}}
/>
</div>
);
}
ts
<script setup lang="ts">
import { ref } from "vue";
const productCardFixture = {
id: "product-card",
name: "Forged steel trowel",
price: 3200,
compareAt: 4000,
image:
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 300'%3E%3Crect width='400' height='300' fill='%23e8e8ea'/%3E%3Crect x='140' y='90' width='120' height='120' rx='8' fill='%23c9c9cf'/%3E%3C/svg%3E",
rating: 4.8,
reviewCount: 64,
badge: "Sale",
wishlisted: false,
} satisfies {
id: string;
name: string;
price: number;
compareAt: number;
image: string;
rating: number;
reviewCount: number;
badge: string;
wishlisted: boolean;
};
import { ProductCard } from "@grassroot/ui-vue";
const wishlisted = ref(productCardFixture.wishlisted);
</script>
<template>
<div>
<ProductCard
:name="productCardFixture.name"
:price="productCardFixture.price"
:compare-at="productCardFixture.compareAt"
:image="productCardFixture.image"
:rating="productCardFixture.rating"
:review-count="productCardFixture.reviewCount"
:badge="productCardFixture.badge"
v-model:wishlisted="wishlisted"
@add-to-cart="undefined"
/>
</div>
</template>
ts
import { Component, signal } from "@angular/core";
const productCardFixture = {
id: "product-card",
name: "Forged steel trowel",
price: 3200,
compareAt: 4000,
image:
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 300'%3E%3Crect width='400' height='300' fill='%23e8e8ea'/%3E%3Crect x='140' y='90' width='120' height='120' rx='8' fill='%23c9c9cf'/%3E%3C/svg%3E",
rating: 4.8,
reviewCount: 64,
badge: "Sale",
wishlisted: false,
} satisfies {
id: string;
name: string;
price: number;
compareAt: number;
image: string;
rating: number;
reviewCount: number;
badge: string;
wishlisted: boolean;
};
import { GrassrootProductCard } from "@grassroot/ui-angular";
@Component({
selector: "app-product-card-demo",
standalone: true,
imports: [GrassrootProductCard],
template: `
<div>
<grassroot-product-card
[name]="fixture.name"
[price]="fixture.price"
[compareAt]="fixture.compareAt"
[image]="fixture.image"
[rating]="fixture.rating"
[reviewCount]="fixture.reviewCount"
[badge]="fixture.badge"
[wishlisted]="wishlisted()"
(wishlistedChange)="wishlisted.set($event)"
(addToCart)="(undefined)"
/>
</div>
`,
})
export class ProductCardDemoComponent {
protected readonly fixture = productCardFixture;
readonly wishlisted = signal(productCardFixture.wishlisted);
}
export default ProductCardDemoComponent;
ts
<script lang="ts">
import { ProductCard } from "@grassroot/ui-svelte";
const productCardFixture = {
id: "product-card",
name: "Forged steel trowel",
price: 3200,
compareAt: 4000,
image:
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 300'%3E%3Crect width='400' height='300' fill='%23e8e8ea'/%3E%3Crect x='140' y='90' width='120' height='120' rx='8' fill='%23c9c9cf'/%3E%3C/svg%3E",
rating: 4.8,
reviewCount: 64,
badge: "Sale",
wishlisted: false,
} satisfies {
id: string;
name: string;
price: number;
compareAt: number;
image: string;
rating: number;
reviewCount: number;
badge: string;
wishlisted: boolean;
};
let wishlisted = $state(productCardFixture.wishlisted);
</script>
<div>
<ProductCard
name={productCardFixture.name}
price={productCardFixture.price}
compareAt={productCardFixture.compareAt}
image={productCardFixture.image}
rating={productCardFixture.rating}
reviewCount={productCardFixture.reviewCount}
badge={productCardFixture.badge}
bind:wishlisted
onAddToCart={() => {}}
/>
</div>
ts
/** @jsxImportSource solid-js */
import { createSignal } from "solid-js";
import { ProductCard } from "@grassroot/ui-solid";
const productCardFixture = {
id: "product-card",
name: "Forged steel trowel",
price: 3200,
compareAt: 4000,
image:
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 300'%3E%3Crect width='400' height='300' fill='%23e8e8ea'/%3E%3Crect x='140' y='90' width='120' height='120' rx='8' fill='%23c9c9cf'/%3E%3C/svg%3E",
rating: 4.8,
reviewCount: 64,
badge: "Sale",
wishlisted: false,
} satisfies {
id: string;
name: string;
price: number;
compareAt: number;
image: string;
rating: number;
reviewCount: number;
badge: string;
wishlisted: boolean;
};
export default function ProductCardDemo() {
const [wishlisted, setWishlisted] = createSignal(productCardFixture.wishlisted);
return (
<div>
<ProductCard
name={productCardFixture.name}
price={productCardFixture.price}
compareAt={productCardFixture.compareAt}
image={productCardFixture.image}
rating={productCardFixture.rating}
reviewCount={productCardFixture.reviewCount}
badge={productCardFixture.badge}
wishlisted={wishlisted()}
onToggleWishlist={setWishlisted}
onAddToCart={() => {}}
/>
</div>
);
}

Installation

API Reference

Import

import * as React from "react";
import { ProductCard } from "@grassroot/ui-react";

Props

Prop
Type
Default
Requirement
Description
name
string
required
price
number
required
Price in minor units.
compareAt
number | undefined
optional
Original price in minor units — shows a struck-through "was".
currency
string | undefined
"USD"
optional
ISO 4217 code.
image
string
required
imageAlt
string | undefined
optional
rating
number | undefined
optional
Average rating 0..5.
reviewCount
number | undefined
optional
badge
string | undefined
optional
Corner flag, e.g.
badgeTone
"info" | "success" | "neutral" | "accent" | undefined
"accent"
optional
wishlisted
boolean | undefined
optional
onToggleWishlist
((pressed: boolean) => void) | undefined
optional
onAddToCart
(() => void) | undefined
optional
className
string | undefined
optional
Prop
name
Type
string
Default
Requirement
required
Description
Prop
price
Type
number
Default
Requirement
required
Description
Price in minor units.
Prop
compareAt
Type
number | undefined
Default
Requirement
optional
Description
Original price in minor units — shows a struck-through "was".
Prop
currency
Type
string | undefined
Default
"USD"
Requirement
optional
Description
ISO 4217 code.
Prop
image
Type
string
Default
Requirement
required
Description
Prop
imageAlt
Type
string | undefined
Default
Requirement
optional
Description
Prop
rating
Type
number | undefined
Default
Requirement
optional
Description
Average rating 0..5.
Prop
reviewCount
Type
number | undefined
Default
Requirement
optional
Description
Prop
badge
Type
string | undefined
Default
Requirement
optional
Description
Corner flag, e.g.
Prop
badgeTone
Type
"info" | "success" | "neutral" | "accent" | undefined
Default
"accent"
Requirement
optional
Description
Prop
wishlisted
Type
boolean | undefined
Default
Requirement
optional
Description
Prop
onToggleWishlist
Type
((pressed: boolean) => void) | undefined
Default
Requirement
optional
Description
Prop
onAddToCart
Type
(() => void) | undefined
Default
Requirement
optional
Description
Prop
className
Type
string | undefined
Default
Requirement
optional
Description

Events

EventPayload
onToggleWishlist((pressed: boolean) => void) | undefined
onAddToCart(() => void) | undefined

Import

import { ref } from "vue";
import { ProductCard } from "@grassroot/ui-vue";

Props

Prop
Type
Default
Requirement
name
string
required
price
number
required
compareAt
number | undefined
optional
currency
string | undefined
"USD"
optional
image
string
required
imageAlt
string | undefined
optional
rating
number | undefined
optional
reviewCount
number | undefined
optional
badge
string | undefined
optional
badgeTone
"accent" | "neutral" | "success" | "info" | undefined
"accent"
optional
wishlisted
boolean | undefined
false
optional
Prop
name
Type
string
Default
Requirement
required
Prop
price
Type
number
Default
Requirement
required
Prop
compareAt
Type
number | undefined
Default
Requirement
optional
Prop
currency
Type
string | undefined
Default
"USD"
Requirement
optional
Prop
image
Type
string
Default
Requirement
required
Prop
imageAlt
Type
string | undefined
Default
Requirement
optional
Prop
rating
Type
number | undefined
Default
Requirement
optional
Prop
reviewCount
Type
number | undefined
Default
Requirement
optional
Prop
badge
Type
string | undefined
Default
Requirement
optional
Prop
badgeTone
Type
"accent" | "neutral" | "success" | "info" | undefined
Default
"accent"
Requirement
optional
Prop
wishlisted
Type
boolean | undefined
Default
false
Requirement
optional

Events

EventPayload
update:wishlisted[pressed: boolean]
addToCart[]

Import

import { Component, signal } from "@angular/core";
import { GrassrootProductCard } from "@grassroot/ui-angular";

Props

Prop
Type
Default
Requirement
name
string
required
price
number
required
compareAt
number
optional
currency
string
"USD"
optional
image
string
required
imageAlt
string
optional
rating
number
optional
reviewCount
number
optional
badge
string
optional
badgeTone
"accent" | "neutral" | "success" | "info"
"accent"
optional
wishlisted
boolean
false
optional
Prop
name
Type
string
Default
Requirement
required
Prop
price
Type
number
Default
Requirement
required
Prop
compareAt
Type
number
Default
Requirement
optional
Prop
currency
Type
string
Default
"USD"
Requirement
optional
Prop
image
Type
string
Default
Requirement
required
Prop
imageAlt
Type
string
Default
Requirement
optional
Prop
rating
Type
number
Default
Requirement
optional
Prop
reviewCount
Type
number
Default
Requirement
optional
Prop
badge
Type
string
Default
Requirement
optional
Prop
badgeTone
Type
"accent" | "neutral" | "success" | "info"
Default
"accent"
Requirement
optional
Prop
wishlisted
Type
boolean
Default
false
Requirement
optional

Events

EventPayload
wishlistedChangeboolean
addToCartvoid

Import

import { ProductCard } from "@grassroot/ui-svelte";

Props

Prop
Type
Default
Requirement
name
string
required
price
number
required
compareAt
number
optional
currency
string
"USD"
optional
image
string
required
imageAlt
string
optional
rating
number
optional
reviewCount
number
optional
badge
string
optional
badgeTone
"accent" | "neutral" | "success" | "info"
"accent"
optional
wishlisted
boolean
false
optional
onToggleWishlist
(pressed: boolean) => void
optional
onAddToCart
() => void
optional
className
string
optional
Prop
name
Type
string
Default
Requirement
required
Prop
price
Type
number
Default
Requirement
required
Prop
compareAt
Type
number
Default
Requirement
optional
Prop
currency
Type
string
Default
"USD"
Requirement
optional
Prop
image
Type
string
Default
Requirement
required
Prop
imageAlt
Type
string
Default
Requirement
optional
Prop
rating
Type
number
Default
Requirement
optional
Prop
reviewCount
Type
number
Default
Requirement
optional
Prop
badge
Type
string
Default
Requirement
optional
Prop
badgeTone
Type
"accent" | "neutral" | "success" | "info"
Default
"accent"
Requirement
optional
Prop
wishlisted
Type
boolean
Default
false
Requirement
optional
Prop
onToggleWishlist
Type
(pressed: boolean) => void
Default
Requirement
optional
Prop
onAddToCart
Type
() => void
Default
Requirement
optional
Prop
className
Type
string
Default
Requirement
optional

Events

EventPayload
onToggleWishlist(pressed: boolean) => void
onAddToCart() => void

Import

import { createSignal } from "solid-js";
import { ProductCard } from "@grassroot/ui-solid";

Props

Prop
Type
Default
Requirement
name
string
required
price
number
required
compareAt
number
optional
currency
string
"USD"
optional
image
string
required
imageAlt
string
optional
rating
number
optional
reviewCount
number
optional
badge
string
optional
badgeTone
"accent" | "neutral" | "success" | "info"
"accent"
optional
wishlisted
boolean
optional
onToggleWishlist
(pressed: boolean) => void
optional
onAddToCart
() => void
optional
className
string
optional
Prop
name
Type
string
Default
Requirement
required
Prop
price
Type
number
Default
Requirement
required
Prop
compareAt
Type
number
Default
Requirement
optional
Prop
currency
Type
string
Default
"USD"
Requirement
optional
Prop
image
Type
string
Default
Requirement
required
Prop
imageAlt
Type
string
Default
Requirement
optional
Prop
rating
Type
number
Default
Requirement
optional
Prop
reviewCount
Type
number
Default
Requirement
optional
Prop
badge
Type
string
Default
Requirement
optional
Prop
badgeTone
Type
"accent" | "neutral" | "success" | "info"
Default
"accent"
Requirement
optional
Prop
wishlisted
Type
boolean
Default
Requirement
optional
Prop
onToggleWishlist
Type
(pressed: boolean) => void
Default
Requirement
optional
Prop
onAddToCart
Type
() => void
Default
Requirement
optional
Prop
className
Type
string
Default
Requirement
optional

Events

EventPayload
onToggleWishlist(pressed: boolean) => void
onAddToCart() => void