ResultCard
StableOne thing in an answer: a picture, its name, a few facts, a price and one action.
Also known as product card, listing card, item card, search result card
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
Hotels in a row
<CardRow label="Hotels in Paris">
{hotels.map((h) => (
<ResultCard key={h.id} title={h.name} subtitle={h.area} image={h.image}
facts={[{ label: "Rating", value: h.rating }, { label: "Check-in", value: h.checkIn }]}
price={{ value: h.price, currency: "EUR", note: "a night" }}
action={{ label: "View rooms", onClick: () => open(h) }} />
))}
</CardRow>Three results with the same fields, laid out with CardRow.
When to use it
Turns the things an answer recommends into something people can compare and act on, instead of a paragraph to read.
Made of: Picture · Name · Short line · Tag · Facts · Price · Action
Use it for
- Hotels, products, places, people or plans the AI suggests.
- Results laid out side by side with CardRow.
- A result that is still arriving.
Not for
- A source behind a claim: use SourceCard.
- A file the AI made: use FileResultCard.
- A single headline number: use StatTile.
- A prompt the person can pick: use SuggestionCard.
Do and avoid
Hôtel des Arts
Montmartre, Paris
- Rating
- 4.6 of 5
- Check-in
- From 3pm
€182a night
Hôtel des Arts
A lovely boutique hotel in the heart of Montmartre with charming rooms, friendly staff and easy access to the metro.
- Rating
- 4.6 of 5
- Check-in
- From 3pm
- Check-out
- By 11am
- Wi-Fi
- Free
- Pets
- Allowed
- Floors
- 5
Do
- Give every card in a row the same fields.
- Keep facts to the ones people compare.
- Hold the action until the answer is complete.
Avoid
- Do not put more than one main action on a card.
- Do not make the whole card a link and also give it a button.
- Do not invent a price or rating the data does not have.
On a phone
- The card fills the width; in a CardRow it swipes sideways with the next card peeking in.
- The price and the action wrap onto two lines when there is no room.
Seen in products
- OpenUI's library has five card blocks and a Carousel for things in an answer, and every item in a block must have the same structure.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| titlerequired | string | none | The thing's name, shown as a heading. |
| subtitle | string | none | One short line under the name. |
| image | { src: string; alt: string } | none | A picture of the thing; alt says what it shows. |
| facts | { label: string; value: ReactNode }[] | none | Two to four facts that help choose. |
| price | { value: number; currency?: string; locale?: string; decimals?: number; note?: string } | none | The price, formatted for the locale, with what it is for. |
| tag | { label: string; tone?: Tone } | none | One short tag, such as Free cancellation. |
| action | { label: string; onClick: () => void } | none | The one thing to do with this result. |
| streaming | boolean | false | The answer is still arriving; the action waits until it is complete. |
| loading | boolean | false | Draws placeholders. |
| headingLevel | 2 | 3 | 4 | 5 | 6 | 3 | Level of the name's heading. |
| className | string | none | Extra classes on the root. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one ResultCard switches all of this from its properties panel, across 4 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| Streaming | streaming | On or off |
| Loading | loading | On or off |
| Title | title | Any text |
| Subtitle | subtitle | Any text |
States
States this part has beyond its default look. Build each one your screen can reach. States set by a property are in the Code tab.
- ready
- Picture, name, short line, facts, price, tag and the action.
- streaming
- The card shows but its action is turned off and the card is marked busy until the answer is complete.
- loading
- Placeholders for the picture, the name and the facts.
- no picture
- The card starts with the name; nothing else moves.
- picture failed
- The picture frame shows its own fallback tile with Retry.
- focus
- The action shows a focus ring on keyboard focus.
Tokens
Change one of these and every part that uses it follows.
--surface--line--fg--fg-muted--radius-card
Built in
- An article with the name as a heading, so people can jump between results.
- The action's label includes the result's name.
- While streaming the action is turned off and the card is marked busy.
What you need to do
- Write alt text that says what the picture shows.
- Give every card in a row the same fields, so people can compare them.
- Name the action for what happens next, such as View rooms, not Click here.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide