Stack

Stack several components one under the other as one piece, with one child able to follow another's result.

Primitive

≈ 839 tokens per use (tool 347 · guidance 250 · typical payload 242)How token costs are estimated

Example: Stack

How did Q3 go?

Q3 in numbers

Revenue
$4.6MIncrease of 11%
Best region
EuropeIncrease of 21%
New customers
312
Net retention
108%

Revenue by region

Revenue by region
RegionQ2Q3
North America$1,840,000$1,925,000
Europe$1,210,000$1,462,000
Asia Pacific$865,000$918,000
Latin America$312,000$298,000

Europe grew most, up 21%. Latin America dipped.

When to use

  • One answer needs 2–6 components that belong together and should arrive as one piece: a summary over a table, a picker over a confirmation, a chart over its KPIs.
  • A component below should follow what the user does in a component above. That's a bind.

When not to use

  • The parts are independent answers. Call each tool on its own; the host stacks them anyway.
  • The parts are parallel views the user switches between. Use Tabs.
  • The parts are a procedure with an order. Use Steps.

How it works

items lists 2–6 components by catalog name. Each may carry a short label above it, and an id that siblings can bind to:

{
  "items": [
    { "id": "slot", "component": "pick_slot", "props": { "title": "Table for 4 at Casa Lume", "days": ["…"] } },
    { "component": "show_summary", "props": {
      "title": "Your reservation",
      "facts": [{ "label": "When", "value": { "$bind": "slot.label", "default": "Pick a time above" } }]
    } }
  ]
}

In the second scenario above, picking a time fills the reservation card at once ({ action: "select", start: "19:30" } flows into the When fact), with no call to the model. Binds only copy values; use them for pick → confirm, not to duplicate a control a component already has.

  • Renders through the Renderer. Children come from the same catalog.
  • One more layout inside is fine. A stack may hold columns, a grid or a split, and no deeper.
  • Results. Each interactive child's result comes back as { child, result }, and the Renderer keeps the latest per child for binds.

How the agent should use it

  • Put the main answer first.
  • Give an id only to children others bind to.
  • Use gap: "tight" for parts of one thing (a KPI and its chart), the default for separate parts.

Installation

npx shadcn@latest add https://your-site.com/r/layout-stack.json

Usage

lib/genui-catalog.ts
import { LayoutStack } from "@/components/genui/layout-stack"

export const catalog = {
  show_stack: LayoutStack,
  show_kpis: KpiCard,
  show_chart: Chart,
} satisfies GenUICatalog

Schema

PropTypeNotes
items{ component, props, id?, label? }[]2–6 components
gap"tight" | "normal"Default "normal"

Host props: status and className. renderChild is injected by the Renderer.

Source

On this page