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