Bento Card
A visually-rich feature showcase card. The Bento Card renders a tiered information block with an icon, badge, title, hero metric, feature list, and call-to-action. Ideal for plan comparisons, service tiers, product offerings, and KPI summaries.
A Bento Card (bento_card) is a self-contained presentation card designed for side-by-side tier comparisons and feature showcases. It combines four optional zones into a single cohesive block:
- Header - icon composite tile, badge, title, and subtitle
- Hero - large metric with period and description (for example, price, score, or capacity)
- Feature list - icon rows with optional labels and values
- CTA - one or two action labels
Four pre-built variants (light, standard, premium, dark) automatically adapt colors, backgrounds, and accent tones to the active theme. Every color property can be overridden from the payload at runtime.
Bento Cards are designed to sit inside a Layout Group for side-by-side column arrangements. When placed inside a Layout Group, borders and backgrounds are promoted to the parent cell so all columns share equal heights.
Variants
| Variant | Background | Accent | Best for |
|---|---|---|---|
light | theme.headerShade (light grey tint) | theme.primary | Entry-level or free tiers |
standard | #FFFFFF (white) | theme.primary | Mid-range plans, default |
premium | Soft tint of theme.secondary | theme.secondary | Featured or recommended tiers |
dark | #1F2937 (slate) | #FBBF24 (amber) | Enterprise, top-tier, highlight |
The premium variant automatically computes its background by blending theme.secondary at 25% opacity onto white. For a blue primary or indigo secondary theme, this produces a soft lavender (approximately #D8D9FC). The icon tile uses theme.primary at 25% opacity to ensure hue contrast against the blended background.
The variant can be set statically on the node or driven from the data payload. See Payload-driven overrides.
Top-level Properties
| Property | Type | Default | Description |
|---|---|---|---|
variant | "light" | "standard" | "premium" | "dark" | "standard" | Visual treatment. Can be overridden at runtime via _repeatItem.variant. |
title | string | "BentoCard" | Main card heading. Supports {{FIELDNAME}} tokens. |
subtitle | string | — | Optional secondary line rendered beneath the title in muted grey. |
icon | string | — | Icon key from the icon registry (for example, "star", "shield", "zap", "box"). Rendered as a 30×30 composite tile with background fill. |
badge | string | — | Short label rendered above the title in accent color (for example, "BEST VALUE", "POPULAR"). Supports {{FIELDNAME}} tokens. |
backgroundColor | color | (variant default) | Override the card background. Accepts any hex color or theme token. |
textColor | color | (variant default) | Override the main text color for title, period, and feature labels. |
accentColor | color | (variant default) | Override the accent color used for badge, hero value, feature icons, and CTA. |
iconBackgroundColor | color | (variant default) | Override the icon tile background fill. Accepts full hex (#RRGGBB) or 8-digit hex (#RRGGBBAA) for opacity. |
Hero Section
The hero section displays a large primary metric — typically a price, score, or capacity — with optional period and description text below it.
Add it by setting the heroSection property object on the card.
| Property | Type | Default | Description |
|---|---|---|---|
heroSection.value | string | — | The main hero metric (for example, "$299", "{{price}}", "99.9%"). Rendered at 28pt bold in accent color. Supports {{FIELDNAME}} tokens. |
heroSection.period | string | — | Unit or frequency label below the hero value (for example, "/ month", "per user"). Rendered at 14pt in text color. |
heroSection.description | string | — | Supporting text below the period (for example, "billed annually", "includes tax"). Rendered at 11pt in muted grey. |
heroSection.hasSeparator | boolean | true | When true, draws a hairline separator between the header and hero sections at 85% card width. Set to false to suppress the divider. |
Features
The features array renders a vertical list of icon and label rows below the hero section. Each feature shows a check icon by default, with an optional custom icon, secondary value, and highlight treatment.
| Property | Type | Default | Description |
|---|---|---|---|
features | Feature[] | [] | Array of feature objects. Can also be a {{path}} token resolving to an array at runtime. |
Feature object
| Property | Type | Default | Description |
|---|---|---|---|
label | string | — | Feature name or description. Supports {{FIELDNAME}} tokens. |
value | string | — | Optional secondary value rendered below the label in a smaller font (for example, "Up to 50 users", "{{storageLimit}} GB"). |
icon | string | — | Override the row icon. Defaults to "check" when omitted. |
color | color | (accent color) | Override the icon and value color for this row. |
highlighted | boolean | false | When true, renders the label in accent color and bold. Useful for marking key differentiators. |
Zebra striping
When there are more than 5 features and the card has a light background, alternate rows automatically receive a subtle #F8FAFC background tint. This improves scannability on long feature lists without requiring any configuration.
CTA Section
The cta object renders one or two call-to-action labels at the bottom of the card, centered, in accent color.
| Property | Type | Default | Description |
|---|---|---|---|
cta.primary | string | — | Primary action label (for example, "Get Started", "{{ctaLabel}}"). |
cta.secondary | string | — | Secondary action label separated from primary by ` |
Payload-driven Overrides
Every visual property — including the variant itself — can be driven entirely from the JSON data payload. This is the recommended approach for generating tier-comparison grids from a CRM or product catalogue.
When the card is used inside a _repeat context, properties are read from _repeatItem first:
_repeatItem.variant— sets the card variant_repeatItem.features— replaces the staticfeaturesarray_repeatItem.badge,_repeatItem.title,_repeatItem.subtitle, etc. — all standard card props can be sourced from payload
You can also pass a {{path}} binding for the features property to resolve a nested array from any path in the payload:
"features": "{{plans.professional.features}}"Usage in a Layout Group
Bento Cards are designed to be placed as direct children of a Layout Group. The Layout Group assigns equal column widths and the cards automatically delegate their border and background to the parent cell, ensuring all cards in a row share the same height regardless of content length.
{
"type": "layout_group",
"props": { "columns": [{"width": "star"}, {"width": "star"}, {"width": "star"}], "columnGap": 12 },
"children": [
{ "type": "bento_card", "props": { "variant": "light", ... } },
{ "type": "bento_card", "props": { "variant": "standard", ... } },
{ "type": "bento_card", "props": { "variant": "premium", ... } }
]
}Examples
Simple Static Card
A minimal card with a title, icon, and feature list — no hero section, no data binding.
{
"type": "bento_card",
"props": {
"variant": "standard",
"title": "Starter",
"subtitle": "For individuals and small teams",
"icon": "zap",
"features": [
{ "label": "5 active projects" },
{ "label": "2 GB storage" },
{ "label": "Email support" }
]
}
}Card with Hero Pricing
A standard pricing card with badge, hero price, period, and CTA.
{
"type": "bento_card",
"props": {
"variant": "premium",
"title": "Professional",
"subtitle": "For growing teams",
"icon": "shield",
"badge": "MOST POPULAR",
"heroSection": {
"value": "$149",
"period": "/ month",
"description": "billed annually, per workspace",
"hasSeparator": true
},
"features": [
{ "label": "Unlimited projects" },
{ "label": "50 GB storage" },
{ "label": "Priority support", "highlighted": true },
{ "label": "SSO & SCIM provisioning" },
{ "label": "Audit logs (90 days)" }
],
"cta": {
"primary": "Start Free Trial",
"secondary": "Talk to Sales"
}
}
}Full Tier Comparison Grid (Static)
A 4-column grid using all four variants, demonstrating a complete service tier comparison.
{
"type": "layout_group",
"props": {
"columns": [
{"width": "star"}, {"width": "star"}, {"width": "star"}, {"width": "star"}
],
"columnGap": 10
},
"children": [
{
"type": "bento_card",
"props": {
"variant": "light",
"title": "Starter",
"subtitle": "Individuals & freelancers",
"icon": "zap",
"heroSection": { "value": "Free", "period": "forever" },
"features": [
{ "label": "3 active projects" },
{ "label": "1 GB storage" },
{ "label": "Community support" }
],
"cta": { "primary": "Sign Up Free" }
}
},
{
"type": "bento_card",
"props": {
"variant": "standard",
"title": "Team",
"subtitle": "Growing companies",
"icon": "users",
"heroSection": { "value": "$49", "period": "/ month", "description": "up to 10 seats" },
"features": [
{ "label": "20 active projects" },
{ "label": "25 GB storage" },
{ "label": "Email & chat support" },
{ "label": "Role-based access control" }
],
"cta": { "primary": "Start Trial" }
}
},
{
"type": "bento_card",
"props": {
"variant": "premium",
"title": "Business",
"subtitle": "Scaling organisations",
"icon": "star",
"badge": "BEST VALUE",
"heroSection": { "value": "$149", "period": "/ month", "description": "billed annually" },
"features": [
{ "label": "Unlimited projects" },
{ "label": "200 GB storage" },
{ "label": "Priority support", "highlighted": true },
{ "label": "SSO & SCIM" },
{ "label": "Audit logs (1 year)" },
{ "label": "Custom integrations" }
],
"cta": { "primary": "Get Started", "secondary": "Schedule Demo" }
}
},
{
"type": "bento_card",
"props": {
"variant": "dark",
"title": "Enterprise",
"subtitle": "Dedicated infrastructure",
"icon": "shield",
"heroSection": { "value": "Custom", "period": "per agreement", "description": "volume pricing available" },
"features": [
{ "label": "Unlimited everything" },
{ "label": "Dedicated cloud region" },
{ "label": "24/7 SLA support", "highlighted": true },
{ "label": "MSA & DPA included" },
{ "label": "On-premise option" },
{ "label": "Dedicated CSM" }
],
"cta": { "primary": "Contact Sales" }
}
}
]
}Payload-driven Cards (Repeat Context)
This is the recommended pattern when plan data lives in the payload. The template node is defined once; the renderer expands it for each item in the data array.
Template node:
{
"type": "layout_group",
"props": {
"columns": [{"width": "star"}, {"width": "star"}, {"width": "star"}],
"columnGap": 12
},
"_repeat": "plans",
"children": [
{
"type": "bento_card",
"props": {
"title": "{{name}}",
"subtitle": "{{tagline}}",
"icon": "{{iconKey}}",
"badge": "{{badge}}",
"heroSection": {
"value": "{{price}}",
"period": "{{billingPeriod}}",
"description": "{{pricingNote}}"
},
"features": "{{features}}",
"cta": { "primary": "{{ctaPrimary}}", "secondary": "{{ctaSecondary}}" }
}
}
]
}Example payload:
{
"plans": [
{
"name": "Starter",
"tagline": "For solo practitioners",
"iconKey": "zap",
"badge": null,
"price": "Free",
"billingPeriod": "forever",
"pricingNote": null,
"ctaPrimary": "Get Started",
"ctaSecondary": null,
"features": [
{ "label": "3 active matters" },
{ "label": "Document vault (500 MB)" },
{ "label": "Email delivery" }
]
},
{
"name": "Professional",
"tagline": "For boutique firms",
"iconKey": "shield",
"badge": "POPULAR",
"price": "$89",
"billingPeriod": "/ month",
"pricingNote": "billed annually",
"ctaPrimary": "Start Trial",
"ctaSecondary": "Talk to Sales",
"features": [
{ "label": "Unlimited matters" },
{ "label": "Document vault (10 GB)" },
{ "label": "Priority support", "highlighted": true },
{ "label": "E-signature included" },
{ "label": "Client portal access" }
]
},
{
"name": "Enterprise",
"tagline": "For large law firms",
"iconKey": "box",
"badge": null,
"price": "Custom",
"billingPeriod": "per agreement",
"pricingNote": "volume discounts available",
"ctaPrimary": "Contact Sales",
"ctaSecondary": null,
"features": [
{ "label": "Unlimited everything" },
{ "label": "Dedicated storage region", "highlighted": true },
{ "label": "On-premise deployment" },
{ "label": "MSA & DPA included" },
{ "label": "Dedicated account manager" },
{ "label": "Custom retention policies" }
]
}
]
}When driving the variant from the payload, add "variant": "{{tier}}" (or any field key) to the props. The renderer reads _repeatItem.variant first, falling back to the static variant prop. This lets different rows in the same repeat loop render with different visual treatments automatically.
Per-card Color Override
All four color properties can be set explicitly to override variant defaults — useful for branded one-off cards or when the theme colors do not match the intended hierarchy.
{
"type": "bento_card",
"props": {
"variant": "standard",
"title": "Regulated Markets Package",
"subtitle": "Financial services add-on",
"icon": "shield",
"badge": "COMPLIANCE READY",
"backgroundColor": "#FFF7ED",
"textColor": "#1C1917",
"accentColor": "#EA580C",
"iconBackgroundColor": "#EA580C33",
"heroSection": {
"value": "$1,200",
"period": "/ year per entity",
"description": "includes annual review"
},
"features": [
{ "label": "SOX-aligned reporting templates", "highlighted": true },
{ "label": "Immutable audit trail (7 years)" },
{ "label": "SEC filing export" },
{ "label": "Dedicated compliance officer" }
],
"cta": { "primary": "Request Proposal" }
}
}KPI Summary Grid
Bento Cards are not limited to pricing. Use the hero section to show any large metric (throughput, SLA scores, error rates, etc.) and the feature list to show supporting breakdowns.
{
"type": "layout_group",
"props": {
"columns": [{"width": "star"}, {"width": "star"}, {"width": "star"}],
"columnGap": 10
},
"children": [
{
"type": "bento_card",
"props": {
"variant": "light",
"title": "API Gateway",
"subtitle": "Last 30 days",
"icon": "zap",
"heroSection": { "value": "99.98%", "period": "uptime", "hasSeparator": true },
"features": [
{ "label": "Avg latency", "value": "42 ms" },
{ "label": "Requests", "value": "14.2 M" },
{ "label": "Error rate", "value": "0.02%", "highlighted": true }
]
}
},
{
"type": "bento_card",
"props": {
"variant": "standard",
"title": "Data Pipeline",
"subtitle": "Last 30 days",
"icon": "box",
"heroSection": { "value": "2.4 TB", "period": "processed", "hasSeparator": true },
"features": [
{ "label": "Jobs completed", "value": "8,410" },
{ "label": "Failed jobs", "value": "3" },
{ "label": "Avg processing time", "value": "1.8 s" }
]
}
},
{
"type": "bento_card",
"props": {
"variant": "dark",
"title": "Security Events",
"subtitle": "Last 30 days",
"icon": "shield",
"heroSection": { "value": "0", "period": "critical alerts", "hasSeparator": true },
"features": [
{ "label": "Auth attempts blocked", "value": "127" },
{ "label": "Policy violations", "value": "4", "highlighted": true },
{ "label": "Scans completed", "value": "360" }
]
}
}
]
}Color Contrast Guard
The renderer automatically checks whether the accent color is readable on the card background using a luminance-ratio formula. If the ratio falls below 1.5 (for example, a very light accent on a light background), the accent is automatically swapped for theme.textOnShade to preserve legibility. This affects the badge, hero value, feature icons, highlighted feature labels, and CTA text.
You can bypass the guard entirely by setting accentColor explicitly in the node props or payload — an explicit override is always used as-is.
Best Use Cases
| Use Case | Recommended Variant | Notes |
|---|---|---|
| Pricing or plan comparison | All four in a grid | Use premium for the featured plan, dark for enterprise |
| Product feature highlights | light or standard | Hero value for a key spec; features for capability list |
| Service tier proposals | premium and dark side by side | Badge on the recommended tier |
| KPI dashboards in reports | light / standard / dark mix | Hero value for the headline metric; features for breakdowns |
| Quote line summaries | standard | Hero for total price; features for line items |
| Compliance or certification blocks | Custom color override | Amber or orange accent for regulated or flagged status |
Bento Cards produce fixed-height PDF blocks. Very long feature lists (10 or more items) will make the card tall. Consider splitting into two cards side-by-side or limiting the feature list to the 6–8 most important items for clean visual balance.
Card
The Card node in VaultPDF. Renders a structured key-value block with configurable variants, border styles, label layouts, and field definitions. Ideal for contact details, order summaries, address blocks, and grouped metadata.
Layout Group
A flexible multi-column layout container. Layout Group places its direct children side by side in 2, 3, or more columns with configurable widths, column gap, and an optional box model.