Card
A product card composing the Card Image, a title, description, star rating and price. Built on the LUSTER atoms — the embedded image follows the active brand theme. All values pulled directly from the LUSTER Figma component.

Padding: 16px · Radius: 12px
Title: #24242C (Inter 500 / 20px)
Image bg: #F2EDFF
Rating stars: #EDB000
Price: #794DFF (Inter 700 / 24px)
Component · Card
The product card composes the Card Image (themed), a title + description, a star rating, and the current/old price.



Design Tokens
Token names mirror the LUSTER Figma variable paths one-to-one. Values shown are the Diamond brand, Light mode defaults (the Figma file's default mode). Other brands (Amber, Opal) and Dark mode resolve to different values via the Color Theme & Component Brand collections.
| Token Name | Figma Variable | Default Value |
|---|---|---|
| --cardImageHeight | card/image/height | 230px |
| --cardImageBorderRadius | card/image/border/radius | 0px |
| --cardImageBgColor | card/image/bg/color | #F2EDFF |
| --cardTitleFontColor | card/title/font/color | #24242C |
| --cardTitleMarginBottom | card/title/margin/bottom | 8px |
| --cardDescFontColor | card/desc/font/color | #62626D |
| --cardReviewStarsFontColor | card/review/stars/font/color | #EDB000 |
| --cardReviewStarsGap | card/reviewStars/gap | 2px |
| --cardReviewLabelFontColor | card/review/label/font/color | #62626D |
| --cardReviewsGap | card/reviews/gap | 8px |
| --cardNewPriceFontColor | card/newPrice/font/color | #794DFF |
| --cardOldPriceFontColor | card/oldPrice/font/color | #62626D |
| --cardPricesGap | card/prices/gap | 8px |
| --cardBodyGap | card/body/gap | 24px |
| --cardBodyPaddingX | card/body/padding/x | 0px |
| --cardBodyPaddingYTop | card/body/padding/y/top | 20px |
| --cardBodyPaddingYBottom | card/body/padding/y/bottom | 12px |
| --cardPaddingX | card/padding/x | 16px |
| --cardPaddingY | card/padding/y | 16px |
| --sectionBgColor | section/bg/color | #FFFFFF |
| --sectionBorderRadius | section/border/radius | 0px |
| --sectionShadowColor | section/shadow/color | #CECBDC |
| --sectionShadowOffsetX | section/shadow/offset-x | 0px |
| --sectionShadowOffsetY | section/shadow/offset-y | 0px |
| --sectionShadowBlur | section/shadow/blur | 0px |
| --cardTitleContent | card/title/content | AirPods Max |
| --cardDescContent | card/desc/content | Spatial audio. Noise cancelled. All-day comfort. |
| --cardReviewLabelContent | card/reviewLabel/content | 420 reviews |
| --cardNewPriceContent | card/newPrice/content | $500 |
| --cardOldPriceContent | card/oldPrice/content | $549 |
| --heading2FontSize | typography/heading-2/font/size | 20px |
| --heading2FontLineHeight | typography/heading-2/font/lineHeight | 24px |
| --heading2FontWeight | typography/heading-2/font/weight | 500 |
| --heading1FontSize | typography/heading-1/font/size | 24px |
| --heading1FontLineHeight | typography/heading-1/font/lineHeight | 29px |
| --heading1FontWeight | typography/heading-1/font/weight | 700 |
| --caption1FontSize | typography/caption-1/font/size | 12px |
| --caption1FontLineHeight | typography/caption-1/font/lineHeight | 14px |
| --caption1FontWeight | typography/caption-1/font/weight | 400 |
| --bodyFontFamily | body/font/family | Inter |
Usage Guidelines
✓ DO
Keep the image ratio consistent across a grid of cards.
✓ DO
Show the old price struck-through to highlight the discount.
✗ DON'T
Don't crowd the card with more than title, desc, rating and price.
✗ DON'T
Don't hardcode colors — reuse the palette & typography tokens.
Implementation
Values shown are the Diamond brand, Light mode defaults (the Figma file's default mode). Other brands (Amber, Opal) and Dark mode resolve to different values via the Color Theme & Component Brand collections.
import { CardImage } from '@luster/ui';
import './Card.css';
export interface CardProps {
theme?: 'diamond' | 'dark' | 'amber' | 'opal';
title: string; description: string;
rating: number; reviews: number;
price: string; oldPrice?: string;
}
export const Card = ({ theme, title, description, rating, reviews, price, oldPrice }: CardProps) => (
<article className="card">
<div className="card__image"><CardImage theme={theme} alt={title} /></div>
<h4 className="card__title">{title}</h4>
<p className="card__desc">{description}</p>
<div className="card__rating">
<Stars value={rating} /><span className="card__reviews">{reviews} reviews</span>
</div>
<div className="card__price">
<span className="card__price-now">{price}</span>
{oldPrice && <span className="card__price-old">{oldPrice}</span>}
</div>
</article>
);