openpencil/packages/pen-ai-skills/skills/phases/generation/elements.md
Kayshen-X c55807e432 ci: remove TS/Electron workflows (build-electron / ci / docker / publish-cli)
Rust-ification 阶段,CI 只保留 Rust 相关:
- rust-check.yml: cargo fmt + build + test (with STEP1A_REQUIRE_GPU=1 on Linux) + clippy + cargo-deny
- wasm-bundle-check.yml: wasm32 target check

删除:
- build-electron.yml: Electron desktop build (Rust 化后用 openpencil-shell-native)
- ci.yml: TS type-check + Vitest + web build (Rust 化后已废)
- docker.yml: TS Docker image (Rust 化后重做)
- publish-cli.yml: npm packages (Rust 化后改 cargo publish)
2026-05-05 22:09:00 +08:00

59 KiB
Raw Blame History

name description phase trigger priority budget category
elements N-tool element family reference — rows, containers, atoms, text/button primitives, composition, forms, controls (switch/checkbox/radio/tabs/segmented), state/feedback (empty_state/alert/toast/progress_bar), floating/nav (fab/breadcrumb/stepper), ratings & pagination (rating_stars/carousel_dots), inline primitives (link/kbd/price), content blocks (quote_block/code_block), design system (color_swatch). Each tool replaces a documented batch_design failure mode
generation
flags
hasMcpTools
14 2400 base

ELEMENT TOOLS (schema-constrained alternatives to batch_design):

These narrow MCP tools emit well-known structures that batch_design frequently gets wrong on non-Claude models (overflow, wrong role, anti-pattern layout). Each is shape-locked — you pick the tool by matching intent, then supply only content.

MULTI-TOOL OUTPUT IS THE NORM, NOT THE EXCEPTION. A brief that names more than one component (a settings panel with 4 toggle rows, a team list with 5 members, a feed with 6 log entries, an onboarding screen with 4 step cards) MUST emit ONE <op_tool> block per component. The harness reads every <op_tool> tag in your output, so chain as many as the brief implies. Fall back to batch_design only when at least one component in the brief truly needs a custom shape no element tool covers — and then use a SINGLE batch_design for the WHOLE response, never as a per-component fallback mixed with element-tool calls (the harness drops the batch_design half whenever element calls share the response).

Multi-tool example — a "Notifications" settings section with a header + 4 toggle rows is 5 tool calls (1× add_section_header_v1 + 4× add_setting_row_v1), NOT 1 batch_design.

parent_id is REAL or OMITTED — never invented. Every add_*_v1 tool's parent_id arg must either (1) be omitted entirely so the new node lands at the page root (the safe default for full-page composite briefs), or (2) name a real existing node id you already received from a prior tool call. The cookbook recipes below use placeholders like <page> / <panel> / <sidebar> as DOCUMENTATION shorthand only — when YOU emit the call in your output, OMIT the parent_id field entirely.

WRONG — these all crash with parent_id "X" not found in document because every id was made up by the model, not handed to you by a prior tool call:

  • add_activity_log_v1({ parent_id: "entry-1", actor: "Sarah", ... }) — "entry-1" was never created
  • add_setting_row_v1({ parent_id: "root", title: "Email" }) — page root has no id
  • add_member_row_v1({ parent_id: "members-section", name: "Sarah" }) — section-* placeholders are docs, not real ids
  • Same trap for any sequential name you might invent: card-1 / item-1 / row-N / <page> / panel / canvas

RIGHT — omit parent_id entirely; each call lands at the page root, which is what every full-page composite brief wants:

  • add_activity_log_v1({ actor: "Sarah", action: "approved deploy", timestamp: "2h ago", theme: "system" })
  • add_setting_row_v1({ title: "Email notifications", trailing: { kind: "switch", on: true }, theme: "system" })
  • add_member_row_v1({ name: "Sarah Lee", subtitle: "Designer", theme: "system" })

Theme handling — when to pass theme: 'system'

Default to theme: 'system' for every v1 tool call. This makes the output respect the user's design system (doc.variables / doc.themes):

  • If user has seeded applySemanticPalette(doc) or set custom token values, v1 'system' mode emits $color-* / $type-* / $spacing-* / $radius-* refs that resolve to user's design system at paint time.
  • If user has NOT seeded a design system, v1 'system' falls back to default palette values (byte-equivalent to v0 hex output via DEFAULT_PALETTE_FALLBACK).

Pass theme: 'light' ONLY if:

  • User explicitly asks for "light theme" output (rare — system mode handles light by default)
  • Brief mentions a specific palette (e.g. "use Tailwind slate")

Pass theme: 'dark' ONLY if:

  • User explicitly asks for "dark mode" / "dark theme"
  • Brief is for a dark UI (e.g. video player overlay, terminal interface)

Use v0 tools (without _v1 suffix) ONLY when:

  • The user explicitly requires byte-frozen output (rare — usually for downstream tooling that depends on stable bytes)
  • A specific test fixture requires v0 byte-parity

For 99% of design generation, add_X_v1({ ..., theme: 'system' }) is correct.

Decision tree (per component — pick first match)

Rows (horizontal, in-card or scrolling):

  1. Row of items with title + subtitle + optional icon → add_card_row_v1 (scroll; theme: 'system' default — see "Theme handling" section) 1b. Byte-frozen escape hatch (rare — downstream tooling requiring stable bytes) → add_card_row_v0
  2. Row of items with small label + big numeric value → add_metric_row_v1 (scroll; no hardcoded colors; accepts theme for API consistency) 2b. Byte-frozen escape hatch → add_metric_row_v0
  3. Row of filter chips / category tabs (label + optional icon, active state) → add_nav_chip_row_v1 (scroll; no hardcoded colors; accepts theme for API consistency) 3b. Byte-frozen escape hatch → add_nav_chip_row_v0
  4. Non-scrolling 2-5 stats inline (auto-share width) → add_stat_grid_v1 (no explicit fills; accepts theme for API consistency) 4b. Byte-frozen escape hatch → add_stat_grid_v0

Containers and single elements:

  1. Section header (big title + optional "See all" action) → add_section_header_v1 (no hardcoded colors; accepts theme for API consistency) 5b. Byte-frozen escape hatch → add_section_header_v0
  2. Bottom tab bar (inline flow, 3-5 nav items) → add_bottom_nav_v1 (accepts theme for API consistency; output identical across themes) 6b. Byte-frozen escape hatch → add_bottom_nav_v0
  3. Mobile top bar (leading icon + centered title + trailing icon) → add_top_nav_bar_v1 (accepts theme; output identical — no hardcoded surface colors) 7b. Byte-frozen escape hatch → add_top_nav_bar_v0
  4. Icon-only button (44×44, hit-target safe) → add_icon_button_v1 (accepts theme for API consistency; output identical across themes) 8b. Byte-frozen escape hatch → add_icon_button_v0
  5. Apple-style progress ring with centered text → add_activity_ring_v1 (accepts theme for API consistency; output identical across themes) 9b. Byte-frozen escape hatch → add_activity_ring_v0

Atoms (1-2 node building blocks):

  1. Hairline separator between list rows / sections → add_divider_v1 (accepts theme for API consistency; output identical across themes) 10b. Byte-frozen escape hatch → add_divider_v0
  2. Short inline pill / tag / "NEW" / "BETA" / count badge → add_badge_v1 (accepts theme for API consistency; output identical across themes) 11b. Byte-frozen escape hatch → add_badge_v0
  3. Circular avatar (with optional initial / empty for later image fill) → add_avatar_v1 (accepts theme for API consistency; output identical across themes) 12b. Byte-frozen escape hatch → add_avatar_v0

Text + button primitives:

  1. Padding-based button with text (optional leading icon) → add_text_button_v1 (accepts theme; output identical — no hardcoded surface colors) 13b. Byte-frozen escape hatch → add_text_button_v0
  2. Heading with enforced fontSize/lineHeight per level + AUTO CJK script detection (SC/JP/KR) → add_heading_v1 (supports theme: 'light' | 'dark' | 'system') 14b. Byte-frozen escape hatch → add_heading_v0
  3. Body text (Inter everywhere — CJK gets lineHeight 1.6 + letterSpacing 0, Latin 1.5) → add_body_text_v1 (accepts theme for API consistency; output identical across themes) 15b. Byte-frozen escape hatch → add_body_text_v0

Composition:

  1. Icon + text inline pair (menu items, breadcrumbs, status indicators) → add_icon_label_v1 (accepts theme for API consistency; output identical across themes) 16b. Byte-frozen escape hatch → add_icon_label_v0
  2. iOS/Material list row (leading icon + title/subtitle stack + trailing icon) → add_list_row_v1 (accepts theme for API consistency; output identical across themes) 17b. Byte-frozen escape hatch → add_list_row_v0

Forms:

  1. Search bar (height=44, cornerRadius=22, leading search icon) → add_search_bar_v1 (dark/system adds surface2 fill so bar is visible on dark bg) 18b. Byte-frozen escape hatch → add_search_bar_v0
  2. Form field (label + 48px input with optional affordance icons) → add_form_field_v1 (accepts theme for API consistency; output identical across themes) 19b. Byte-frozen escape hatch → add_form_field_v0 19c. Multi-line textarea (label + N-row input for notes / bio / feedback) → add_textarea_v1 (accepts theme; output identical — no hardcoded surface colors) 19c-v0. Byte-frozen escape hatch → add_textarea_v0 19d. Dropdown select closed-state (label + 48px input w/ value text + chevron-down) → add_select_v1 (placeholder → textSubtle in dark/system) 19d-v0. Byte-frozen escape hatch → add_select_v0

Controls (toggle / choice / tabs):

  1. iOS/Material toggle switch (51×31, thumb floats) → add_switch_v1 (iOS HIG values #34C759/#E5E5EA are builder-private per §3.4; all modes identical) 20b. Byte-frozen escape hatch → add_switch_v0
  2. Checkbox + inline label (20×20 box, check icon inside when checked) → add_checkbox_v1 (accent fill checked, border token unchecked) 21b. Byte-frozen escape hatch → add_checkbox_v0
  3. Radio button + inline label (20×20 ring, dot inside when selected) → add_radio_v1 (accent brand-invariant; unselected ring → border in dark/system) 22b. Byte-frozen escape hatch → add_radio_v0
  4. Horizontal top tabs with underline on active (fontWeight 600 + 2px sibling rectangle underline) → add_tabs_v1 (#2563EB underline is brand accent per §3.4; all modes identical) 23b. Byte-frozen escape hatch → add_tabs_v0
  5. iOS pill-style segmented control (equal-width segments, active floats white) → add_segmented_control_v1 (track → surface2, active seg → surface, labels → textPrimary/textMuted) 24b. Byte-frozen escape hatch → add_segmented_control_v0

State / feedback:

  1. Empty state (icon + title + optional subtitle + optional CTA button, centered) → add_empty_state_v1 (accepts theme for API consistency; output identical across themes) 25b. Byte-frozen escape hatch → add_empty_state_v0
  2. Inline banner / callout (icon + message + optional close x, fill_container) → add_alert_v1 (accepts theme for API consistency; output identical across themes) 26b. Byte-frozen escape hatch → add_alert_v0
  3. Floating pill notification (dark fit_content pill) → add_toast_v1 (theme: 'system' default — see "Theme handling" section) 27b. Byte-frozen escape hatch → add_toast_v0
  4. Linear progress bar (fixed bar_width + value 0-100) → add_progress_bar_v1 (track → surface2 in dark/system; accent fill brand-invariant) 28b. Byte-frozen escape hatch → add_progress_bar_v0

Floating / nav / wizard:

  1. Floating action button (circular 56×56, icon centered) → add_fab_v1 (bg → accent in dark/system; icon always white) 29b. Byte-frozen escape hatch → add_fab_v0
  2. Breadcrumb trail with chevron separators (last crumb auto-active) → add_breadcrumb_v1 (accepts theme for API consistency; output identical across themes) 30b. Byte-frozen escape hatch → add_breadcrumb_v0
  3. Horizontal numbered stepper (circles + fill_container connectors) → add_stepper_v1 (pending fill → border; pending number → textMuted; accent + done-white stay hardcoded) 31b. Byte-frozen escape hatch → add_stepper_v0

Ratings & pagination:

  1. N-of-M star rating (filled + empty stars using lucide star) → add_rating_stars_v1 (no explicit colors; all modes identical — accepts theme for API consistency) 32b. Byte-frozen escape hatch → add_rating_stars_v0
  2. Carousel / slide dots (active becomes elongated pill, inactive circles) → add_carousel_dots_v1 (active=text-primary, inactive=border in dark/system modes) 33b. Byte-frozen escape hatch → add_carousel_dots_v0

Inline text primitives:

  1. Text link with optional trailing icon ("Learn more →") → add_link_v1 (accepts theme for API consistency; output identical across themes) 34b. Byte-frozen escape hatch → add_link_v0
  2. Keyboard shortcut glyph ("⌘ K" / "Ctrl + Shift + P") → add_kbd_v1 (key bg → surface2, stroke → border in dark/system) 35b. Byte-frozen escape hatch → add_kbd_v0
  3. Pricing typography ("$29/month": currency 20/500 + amount 40/700 + period 14/500) → add_price_v1 (no hardcoded colors; all modes identical — accepts theme for API consistency) 36b. Byte-frozen escape hatch → add_price_v0

Content blocks:

  1. Quoted passage with optional author attribution → add_quote_block_v1 (container bg → surface in dark/system) 37b. Byte-frozen escape hatch → add_quote_block_v0
  2. Preformatted code block (fill_container, wraps, gray-50 bg) → add_code_block_v1 (bg → surface2 in dark/system) 38b. Byte-frozen escape hatch → add_code_block_v0

Design-system:

  1. Color swatch (colored square + optional token label) → add_color_swatch_v1 (same tree; theme param for API consistency) 39b. Byte-frozen escape hatch → add_color_swatch_v0

Charts / data visualization:

  1. Bar-chart skeleton (one rectangle per value, bottom-aligned) → add_chart_bars_v1 (chart-1 token in dark/system) 40b. Line-chart skeleton (polyline + optional dots) → add_chart_line_v1 (chart-1 token in dark/system) 40c. Pie-chart skeleton (colored ellipse slices via arc angles) → add_chart_pie_v1 (chart-1..6 tokens in dark/system) 40d. Byte-frozen bar chart escape hatch → add_chart_bars_v0 40e. Byte-frozen line chart escape hatch → add_chart_line_v0 40f. Byte-frozen pie chart escape hatch → add_chart_pie_v0

Media / placeholder:

  1. Image placeholder (gray box + centered icon + optional caption — future image slot) → add_image_placeholder_v1 (bg → bgDeep, icon/label → textMuted in dark/system). Pass image_search_query (2-3 English keywords like "burger fries", "modern office") so the auto-search pass replaces the gray box with a relevant photo; without it the pipeline searches the label or a generic placeholder and lands a random stock image. 44b. Video placeholder (dark box + play icon + optional caption — future video embed) → add_video_placeholder_v1 (dark bg/icon/caption are builder-private per §3.4; all modes identical) 44c. Byte-frozen image placeholder escape hatch → add_image_placeholder_v0 (also accepts image_search_query) 44d. Byte-frozen video placeholder escape hatch → add_video_placeholder_v0

Social / UGC:

  1. Comment row (circular avatar + author/timestamp header + body) → add_comment_v1 (avatar bg → surface2, timestamp → textMuted in dark/system) 45b. Byte-frozen escape hatch → add_comment_v0

Chrome / modals:

  1. Modal dialog shell (dimmed backdrop + centered card + title — body composed separately) → add_modal_shell_v1 (supports theme: 'light' | 'dark' | 'system') 46b. Byte-frozen escape hatch → add_modal_shell_v0

Status / presence:

  1. Status badge (small colored dot + short label, "● Online" pattern, tone-enum'd) → add_status_badge_v1 (tone colors are status semantics kept hardcoded; all modes identical) 47b. Byte-frozen escape hatch → add_status_badge_v0

Feedback / loading:

  1. Loading spinner (static ring + 3/4 arc) → add_spinner_v1 (track_color/active_color are caller params; accepts theme for API consistency; all modes identical) 48b. Byte-frozen escape hatch → add_spinner_v0
  2. Tooltip pill (dark pill + white text, hover-hint appearance) → add_tooltip_v1 (dark body #111827 is intentional inverted-contrast per §3.4; all modes identical) 49b. Byte-frozen escape hatch → add_tooltip_v0

Analytics / KPIs:

  1. KPI cell with trend arrow + change ("$12k ↑ 8%") → add_metric_comparison_v1 (label → textMuted; trend up → success, down → destructive, flat → textMuted) 50b. Byte-frozen escape hatch → add_metric_comparison_v0

Notifications:

  1. Notification list row (icon + title/timestamp header + optional body preview + optional unread dot) → add_notification_row_v1 (timestamp → textSubtle, body → textBody, unread dot → destructive) 51b. Byte-frozen escape hatch → add_notification_row_v0

Activity / history:

  1. Vertical timeline (dots + fixed 24px connectors + content; no padding/gap) → add_timeline_v1 (#2563EB active dot hardcoded per §3.4; inactive dot/connector → border, subtitle → textMuted) 41b. Byte-frozen escape hatch → add_timeline_v0

Calendars:

  1. Month calendar grid (weekday header + 7-col day rows, today/selected tint) → add_calendar_grid_v1 (header text, day numbers, selected/today fills respond to theme) 42b. Byte-frozen escape hatch → add_calendar_grid_v0

Loading / placeholder:

  1. Loading skeleton (N gray rectangles, last row ~60% width) → add_skeleton_v1 (row fill → surface2 in dark/system so bars are visible on dark bg) 43b. Byte-frozen escape hatch → add_skeleton_v0

Pagination:

  1. Pagination bar (numbered pills + prev/next arrows, Google-style ellipses for big ranges) → add_pagination_v1 (arrow/inactive → textBody, ellipsis → textMuted; active pill bg invariant, active text stays white) 52b. Byte-frozen escape hatch → add_pagination_v0

Collapsible content:

  1. FAQ / accordion item (question + chevron; expanded variant shows answer paragraph) → add_faq_item_v1 (chevron/answer → textMuted, divider → border in dark/system) 53b. Byte-frozen escape hatch → add_faq_item_v0

Tag / multi-value inputs:

  1. Chip input / tag input (pills + removable × + inline caret, wrap layout) → add_chip_input_v1 (chip bg → surface2, field bg → surface, placeholder → textSubtle) 54b. Byte-frozen escape hatch → add_chip_input_v0

Chart empty state:

  1. Empty chart placeholder (dashed tile in chart footprint; "No data yet" message) → add_empty_chart_v1 (theme: 'system' default — see "Theme handling" section) 55b. Byte-frozen escape hatch → add_empty_chart_v0

Menus / floating panels:

  1. Action / context menu panel (dropdown list of icon+label rows, destructive variant supported) → add_action_menu_v1 (surface, border, icon, label colors respond to theme) 56b. Byte-frozen escape hatch → add_action_menu_v0

Dates:

  1. Date picker CLOSED state (labeled input + "Jan 15, 2026" + trailing calendar icon) → add_date_picker_v1 (input bg → surface, stroke → border in dark/system) 57b. Byte-frozen escape hatch → add_date_picker_v0

Upload / file intake:

  1. File upload dropzone (dashed tile + cloud icon + "Drop files / click to browse") → add_upload_dropzone_v1 (bg → bgDeep, dashed border → border, icon → textMuted, title → textBody, subtitle → textMuted) 58b. Byte-frozen escape hatch → add_upload_dropzone_v0

Auth / verification:

  1. OTP / PIN code input (row of N square slots, 4..8 digits; blank / partial / full states) → add_otp_input_v1 (slot bg → surface, borders → border/borderStrong, digit → textPrimary; focused border = accent_color invariant) 59b. Byte-frozen escape hatch → add_otp_input_v0

Attachments:

  1. File attachment row (type-icon + filename + optional size + remove ×) → add_attachment_row_v1 (surface, text hierarchy, icon colors respond to theme) 60b. Byte-frozen escape hatch → add_attachment_row_v0

Messaging:

  1. Chat message bubble (left=from-others slate bg / right=from-self accent bg; optional author + timestamp) → add_chat_bubble_v1 (surface2 bg for left, accent bg for right, textMuted for author/timestamp) 61b. Byte-frozen escape hatch → add_chat_bubble_v0

Dashboard KPIs:

  1. Big-number stat card (standalone metric tile — label + huge value + optional delta/icon) → add_stat_card_v1 (bg → surface; border → border; label → textMuted; icon → textSubtle; value → textPrimary; delta tones stay hardcoded) 62b. Byte-frozen escape hatch → add_stat_card_v0

Auth / login:

  1. Social auth provider buttons ("Continue with Google / Apple / Microsoft", OAuth/SSO row, third-party sign-in) → add_social_login_row_v1 (button bg → surface; border → border; icon → textMuted; label → textPrimary in dark/system) 63b. Byte-frozen escape hatch → add_social_login_row_v0

Pricing / monetization:

  1. Pricing plan tier card (SaaS pricing table column: tier name + big price + feature list + CTA; emphasize the recommended tier with emphasis="featured") → add_pricing_card_v1 (card bg → surface, border → border; featured accent/CTA stay brand-invariant; text → textPrimary/textMuted/textBody) 64b. Byte-frozen escape hatch → add_pricing_card_v0

Input / forms:

  1. Range slider (single-thumb horizontal slider showing current value: volume, opacity, brightness, price range) → add_range_slider_v1 (accent brand-invariant; thumb bg → surface; remaining → border; label → textPrimary; value → textMuted) 65b. Byte-frozen escape hatch → add_range_slider_v0

  2. International phone number input with country-code prefix selector → add_phone_input_v1 (field bg → surface, stroke/divider → border, label → textBody, code → textPrimary, chevron → textMuted) 66b. Byte-frozen escape hatch → add_phone_input_v0

  3. Input field with inline action button (newsletter signup, apply discount code, send chat message) → add_input_with_action_v1 (input bg → surface, stroke → border, text → textPrimary; button bg → accent (brand-invariant), button text → white in all modes) 67b. Byte-frozen escape hatch → add_input_with_action_v0

Compliance / disclosure:

  1. Cookie consent / GDPR / privacy banner (sticky bottom-of-page disclosure card with accept / decline / settings) → add_cookie_banner_v1 (card bg → surface, title → textPrimary, accept → accent in dark/system) 68b. Byte-frozen escape hatch → add_cookie_banner_v0

Desktop / dashboard rails:

  1. Persistent vertical sidebar (left rail with icon+label rows, optional brand title, active item gets pill bg) → add_sidebar_nav_v1 (bg → surface; title + active label → textPrimary; inactive → textMuted; active item bg → surface2) 69b. Byte-frozen escape hatch → add_sidebar_nav_v0

Presence / collaboration:

  1. Stacked avatar group (team / online users / "+N more" tile, white-ringed circles in a tight horizontal row) → add_avatar_group_v1 (ring, overflow bg/text respond to theme; brand avatar palette stays hardcoded) 70b. Byte-frozen escape hatch → add_avatar_group_v0

Tabular data:

  1. Desktop data-table row (N column-aligned cells in a single horizontal row, header / body / selected variants) → add_data_table_row_v1 (header text → textMuted, body → textPrimary, selected → bgDeep in dark/system) 71b. Byte-frozen escape hatch → add_data_table_row_v0

Filter / selection chips:

  1. Single closable tag chip (filter / applied criterion / category, optional × close icon, tone enum) → add_tag_v1 (tone bg/fg are status semantic colors per §3.4; all modes identical) 72b. Byte-frozen escape hatch → add_tag_v0

People / profile:

  1. Compact user card (avatar + name + optional role line, horizontal row) → add_user_card_v1 (name → textPrimary, role → textMuted; avatar bg #3B82F6 + initial white stay brand-invariant per §3.4) 73b. Byte-frozen escape hatch → add_user_card_v0
  2. Large profile header (centered avatar + name + optional handle/bio) → add_profile_header_v1 (name → textPrimary, handle → textMuted, bio → textBody; avatar bg #3B82F6 + initial white stay brand-invariant) 74b. Byte-frozen escape hatch → add_profile_header_v0

Side panels & docking:

  1. Slide-in drawer shell (full-height side panel with header) → add_drawer_shell_v1 (bg → surface, border → border token, title/icon → semantic tokens in dark/system) 75b. Byte-frozen escape hatch → add_drawer_shell_v0

Forms (open state) & toolbars:

  1. Open-state combobox / autocomplete (input + visible dropdown rows) → add_combobox_v1 (surface/border/surface2 tokens in dark/system) 76b. Byte-frozen escape hatch → add_combobox_v0
  2. Desktop toolbar (icon button row with optional dividers) → add_toolbar_v1 (surface → surface, border → border, active-bg → surface2, icon fills → textPrimary/textMuted) 77b. Byte-frozen escape hatch → add_toolbar_v0

Doc / inline feedback:

  1. Inline doc callout (tinted block with title + body, tone enum) → add_callout_v1 (tone-keyed bg/fg → semantic alert palette in dark/system modes) 78b. Byte-frozen escape hatch → add_callout_v0
  2. Inline status + action ("Comment deleted • Undo") → add_inline_action_v1 (icon/message → textBody, CTA → accent in dark/system) 79b. Byte-frozen escape hatch → add_inline_action_v0

Sharing / chart annotations:

  1. Social share button row (circular icon buttons + labels) → add_share_row_v1 (icon btn bg → surface2; icon/label → textMuted in dark/system) 80b. Byte-frozen escape hatch → add_share_row_v0
  2. Chart legend entry (color marker + label + optional value) → add_legend_item_v1 (label → textBody, value → textPrimary; marker color kept as-is) 81b. Byte-frozen escape hatch → add_legend_item_v0

Mail / inbox:

  1. Inbox / email list row (sender + subject + preview + unread dot) → add_inbox_message_v1 (primary → textPrimary, timestamp → textSubtle, preview → textMuted, unread dot → accent in dark/system) 82b. Byte-frozen escape hatch → add_inbox_message_v0

Settings / preferences:

  1. Settings menu row (icon + title + subtitle + trailing chevron / value / switch / badge) → add_setting_row_v1 (supports theme: 'light' | 'dark' | 'system') 83b. Byte-frozen escape hatch → add_setting_row_v0

People / lists:

  1. Members / team list row (avatar + name + subtitle + role badge / kebab menu / status dot) → add_member_row_v1 (supports theme: 'light' | 'dark' | 'system') 84b. Byte-frozen escape hatch → add_member_row_v0
  2. Pending invite list row (initial avatar + email/role + status pill + Resend action) → add_invite_row_v1 (avatar bg → surface2, text → textPrimary/textMuted, action → accent; status pills use alertColors in dark/system) 85b. Byte-frozen escape hatch → add_invite_row_v0

Faceted search / filter sidebar:

  1. Sidebar filter group (heading + checkbox-style option list with counts) → add_filter_group_v1 (title → textPrimary, label → textBody, box bg/stroke → surface/border in dark/system) 86b. Byte-frozen escape hatch → add_filter_group_v0

Audit / activity feed:

  1. Activity log entry (actor in bold + action + timestamp + tinted icon dot) → add_activity_log_v1 (supports theme: 'light' | 'dark' | 'system') 87b. Byte-frozen escape hatch → add_activity_log_v0

Calendar:

  1. Single event card (month/day column + title + time + location) → add_event_card_v1 (card bg/stroke/date column → semantic tokens; accent strip + white text stay brand-invariant) 88b. Byte-frozen escape hatch → add_event_card_v0

Onboarding:

  1. Numbered step card (circle/check + title + description) → add_step_card_v1 (title → textPrimary; desc → textMuted; incomplete ring bg → surface; accent stays hardcoded) 89b. Byte-frozen escape hatch → add_step_card_v0

  2. None match → fall through to batch_design

Disambiguation: if you need a ROW of 3 metrics that should NOT scroll (e.g. a stats strip inside a card), use add_stat_grid_v1, NOT add_metric_row_v1. The grid uses fill_container per cell so it never overflows; the metric row uses fixed-px cells + scroll wrapper.

When to use vs batch_design

PREFER an element tool when the spec says any of:

  • "horizontal scrolling cards", "swipeable row", "chip row", "pills" → add_card_row_v1 (theme: 'system' default)
  • "metric tiles", "KPI cards", "dashboard stats" (SCROLLING row) → add_metric_row_v1 (theme: 'system' default)
  • "stats row", "3 metrics side by side", "summary bar" (NON-scrolling grid) → add_stat_grid_v1 (theme: 'system' default)
  • "category filter chips", "quick-access shortcuts" → add_nav_chip_row_v1 (theme: 'system' default)
  • "section title with See all / View more" → add_section_header_v1 (theme: 'system' default)
  • "bottom nav", "tab bar", "tabbar", "底部导航" → add_bottom_nav_v1 (theme: 'system' default)
  • "top bar", "app bar", "header with back button", "页面标题栏" → add_top_nav_bar_v1 (theme: 'system' default)
  • "icon-only button", "close button", "menu button" (toolbar-style) → add_icon_button_v1 (theme: 'system' default)
  • "activity ring", "progress ring", "circular progress", "Apple health ring" → add_activity_ring_v1 (theme: 'system' default)
  • "hairline divider", "separator", "row divider", "section separator" → add_divider_v1 (theme: 'system' default)
  • "badge", "pill", "tag", "NEW label", "count bubble" (≤16 Latin / ≤8 CJK chars) → add_badge_v1 (theme: 'system' default)
  • "avatar", "profile picture", "user circle", "initial bubble" → add_avatar_v1 (theme: 'system' default)
  • "primary button", "secondary button", "CTA", "submit button" (short label) → add_text_button_v1 (theme: 'system' default)
  • "hero headline", "section title", "card title" / 特定字号标题 → add_heading_v1 (theme: 'system' default; use "system" when applySemanticPalette(doc) is seeded)
  • "body paragraph", "description text", "intro copy" (包含 CJK 时尤其推荐) → add_body_text_v1 (theme: 'system' default)
  • "icon with label", "menu item (inline)", "breadcrumb segment", "status indicator text" → add_icon_label_v1 (theme: 'system' default)
  • "list item", "iOS list cell", "table row with chevron" → add_list_row_v1 (theme: 'system' default; settings rows specifically — add_setting_row_v1, which has switch / value / badge trailing variants)
  • "search bar", "search input", "filter search", "搜索栏" → add_search_bar_v1 (theme: 'system' default; adds surface2 fill in dark/system so bar is visible on dark bg)
  • "form field", "email input", "password field", "labeled input", "required field" → add_form_field_v1 (theme: 'system' default)
  • "textarea", "multi-line input", "notes field", "description box", "bio input", "feedback box", "多行输入", "备注" → add_textarea_v1 (theme: 'system' default)
  • "dropdown", "select", "picker", "combo box", "下拉选择", "选择器" → add_select_v1 (theme: 'system' default; placeholder → textSubtle in dark/system)
  • "skeleton", "loading placeholder", "shimmer", "loading state", "placeholder lines", "骨架屏", "加载中占位" → add_skeleton_v1 (theme: 'system' default; row fill → surface2 so bars are visible on dark bg)
  • "line chart", "trend chart", "折线图" → add_chart_line_v1 (theme: 'system' default)
  • "pie chart", "donut chart", "饼图" → add_chart_pie_v1 (theme: 'system' default)
  • "image placeholder", "photo slot", "upload zone", "hero image area", "cover placeholder", "图片占位" → add_image_placeholder_v1 (theme: 'system' default)
  • "video placeholder", "video slot", "play placeholder", "upcoming video", "视频占位" → add_video_placeholder_v1 (theme: 'system' default)
  • "comment", "reply", "feedback row", "review row", "评论" → add_comment_v1 (theme: 'system' default)
  • "modal", "dialog", "popup", "confirm dialog", "模态框", "弹窗" → add_modal_shell_v1 (theme: 'system' default; use "system" when the document has applySemanticPalette(doc) seeded)
  • "toast", "snackbar", "popup notification", "轻提示" → add_toast_v1 (theme: 'system' default; toasts use INVERTED contrast — "dark" gives a light pill with dark fg)
  • "empty chart", "no data chart", "chart placeholder", "empty analytics tile", "暂无数据", "空图表" → add_empty_chart_v1 (theme: 'system' default; use inside dark-theme dashboards so the empty slot doesn't punch a light rectangle into dark surfaces)
  • "status", "online indicator", "presence dot", "health status", "busy indicator", "状态", "在线" → add_status_badge_v1 (theme: 'system' default; tone colors are status semantics kept hardcoded)
  • "spinner", "loading spinner", "progress circle", "loader", "加载圈" → add_spinner_v1 (theme: 'system' default)
  • "tooltip", "hover hint", "help tip", "提示浮层" → add_tooltip_v1 (theme: 'system' default; dark body #111827 is intentional inverted-contrast)
  • "toggle", "switch", "on/off", "开关" → add_switch_v1 (theme: 'system' default; iOS HIG values kept hardcoded)
  • "checkbox", "agreement", "select option", "复选框" → add_checkbox_v1 (theme: 'system' default; accent fill checked, border token unchecked)
  • "radio", "single choice", "单选" → add_radio_v1 (theme: 'system' default; stack multiple in a vertical parent; accent stays brand-invariant)
  • "top tabs", "underline tabs", "secondary nav", "下划线 tab" → add_tabs_v1 (theme: 'system' default; #2563EB underline is brand accent per §3.4)
  • "segmented control", "iOS pill tabs", "filter toggle group", "iOS 分段控制" → add_segmented_control_v1 (theme: 'system' default; track → surface2; active seg → surface)
  • "empty state", "no results", "nothing here yet", "first-run state", "空状态" → add_empty_state_v1 (theme: 'system' default)
  • "alert", "callout", "banner", "notification bar", "告知条", "warning banner" → add_alert_v1 (theme: 'system' default)
  • "progress bar", "loading bar", "线性进度条", "linear progress" → add_progress_bar_v1 (theme: 'system' default; track → surface2; accent brand-invariant)
  • "FAB", "floating action button", "compose button", "新建按钮" → add_fab_v1 (theme: 'system' default; bg → accent; icon always white)
  • "breadcrumb", "nav path", "面包屑" → add_breadcrumb_v1 (theme: 'system' default)
  • "stepper", "progress steps", "wizard nav", "步骤条" → add_stepper_v1 (theme: 'system' default; pending fill → border; pending number → textMuted)
  • "rating", "review stars", "评分" → add_rating_stars_v1 (theme: 'system' default)
  • "carousel dots", "slide indicator", "轮播指示" → add_carousel_dots_v1 (theme: 'system' default)
  • "text link", "learn more", "inline link" → add_link_v1 (theme: 'system' default)
  • "keyboard shortcut", "hotkey", "⌘K", "快捷键" → add_kbd_v1 (theme: 'system' default; key bg → surface2, stroke → border in dark/system)
  • "price", "plan cost", "$29/month", "定价" → add_price_v1 (theme: 'system' default)
  • "quote", "testimonial quote", "引言" → add_quote_block_v1 (theme: 'system' default; container bg → surface in dark/system)
  • "code snippet", "code block", "代码块" → add_code_block_v1 (theme: 'system' default; bg → surface2 in dark/system)
  • "color swatch", "palette", "token", "色板" → add_color_swatch_v1 (theme: 'system' default)
  • "bar chart", "histogram skeleton", "weekly steps", "柱状图" → add_chart_bars_v1 (theme: 'system' default)
  • "timeline", "activity history", "vertical stepper", "时间线", "动态" → add_timeline_v1 (theme: 'system' default; #2563EB active dot hardcoded per §3.4)
  • "calendar", "date picker grid", "month view", "日历" → add_calendar_grid_v1 (theme: 'system' default)
  • "pagination", "page nav", "page numbers", "prev/next pages", "分页", "分页条" → add_pagination_v1 (theme: 'system' default)
  • "FAQ", "accordion", "collapsible item", "Q&A", "expandable row", "常见问题", "折叠面板" → add_faq_item_v1 (theme: 'system' default)
  • "chip input", "tag input", "multi-select field", "recipient list", "email chips", "标签输入", "多选标签" → add_chip_input_v1 (theme: 'system' default)
  • "action menu", "context menu", "dropdown menu", "more menu", "kebab menu", "action sheet", "下拉菜单", "操作菜单" → add_action_menu_v1 (theme: 'system' default)
  • "date picker", "date input", "date field", "due date", "picker closed", "日期选择器", "日期输入" → add_date_picker_v1 (theme: 'system' default; for the calendar grid shown after clicking, use add_calendar_grid_v1)
  • "upload", "drop files here", "drag and drop", "file picker", "dropzone", "upload area", "上传区", "文件拖放" → add_upload_dropzone_v1 (theme: 'system' default; visually similar to empty-chart but semantically different — pick by intent)
  • "OTP", "PIN code", "verification code", "2FA code", "6-digit code", "enter code", "验证码", "PIN 码" → add_otp_input_v1 (theme: 'system' default)
  • "attachment", "attached file", "uploaded file", "file item", "file list row", "附件", "已上传文件" → add_attachment_row_v1 (theme: 'system' default; for upload-in-progress state, compose add_progress_bar_v1 below)
  • "chat message", "message bubble", "conversation row", "iMessage bubble", "chat UI", "聊天气泡", "消息气泡" → add_chat_bubble_v1 (theme: 'system' default; side="left" for from-others, side="right" for from-self)
  • "KPI card", "big number card", "metric tile", "stat widget", "featured metric", "关键指标卡", "数据大屏卡片" → add_stat_card_v1 (theme: 'system' default; distinct from add_stat_grid_v1 which is multi-cell side-by-side)
  • "Continue with Google", "Sign in with Apple", "social login", "OAuth buttons", "SSO providers", "third-party login", "第三方登录", "社交登录", "OAuth 登录" → add_social_login_row_v1 (theme: 'system' default; orientation="vertical" for stacked full-width on mobile; orientation="horizontal" for the compact icon-only row)
  • "pricing card", "plan card", "SaaS tier", "subscription plan", "pricing tier", "billing card", "价格卡", "套餐卡", "定价卡片" → add_pricing_card_v1 (theme: 'system' default; set one tile's emphasis: "featured" to visually recommend it). For a 3-tier pricing section, call this 3× under the same parent section.
  • "slider", "range input", "volume control", "opacity slider", "brightness slider", "filter slider", "滑块", "滑动条", "音量条" → add_range_slider_v1 (theme: 'system' default; set show_value=true + value_suffix="%" to render the readout). For a dual-handle range (min+max), still fall through to batch_design.
  • "phone input", "phone field", "international phone", "country code input", "+1 (555) ...", "电话号码", "手机号输入", "国际电话" → add_phone_input_v1 (theme: 'system' default; pass country_flag for emoji prefix). For a plain single-line text input without the country prefix, use add_form_field_v1.
  • "newsletter signup", "subscribe form", "subscribe to newsletter", "promo code input", "apply discount", "send message input", "chat composer", "search with submit", "订阅", "应用优惠码", "发送消息" → add_input_with_action_v1 (theme: 'system' default; action_kind="text" for "Subscribe" pill button, action_kind="icon" for chat send arrow).
  • "cookie banner", "cookie consent", "GDPR banner", "CCPA banner", "privacy notice", "cookie disclosure", "cookie 提示", "隐私同意条" → add_cookie_banner_v1 (theme: 'system' default; set show_settings_link: true for fine-grained GDPR consent UX). Caller positions sticky-bottom; the tool emits the banner card itself.
  • "sidebar", "side nav", "sidebar nav", "left rail", "dashboard nav rail", "admin sidebar", "settings sidebar", "docs sidebar", "vertical nav", "侧边栏", "侧边导航", "左侧导航" → add_sidebar_nav_v1 (theme: 'system' default; pass title for a brand row above the items, mark current page with active: true on the item).
  • "stacked avatars", "avatar group", "avatar stack", "team avatars", "5 contributors", "online users", "+N more", "viewers row", "presence indicator", "成员头像", "团队头像", "在线用户", "头像组" → add_avatar_group_v1 (theme: 'system' default; renders up to max_visible ringed avatar circles + a "+N" overflow tile).
  • "data table row", "table row", "table header row", "customer row", "order row", "report row", "transaction row", "users table", "数据表行", "表格行", "表头行" → add_data_table_row_v1 (theme: 'system' default; pass header: true for the column-header row, selected: true to tint a hover/selected body row). For row separators stack add_divider_v1 between rows.
  • "filter chip", "filter tag", "applied filter", "selected criterion", "category pill", "removable tag", "Status: Active ×", "可移除标签", "筛选标签" → add_tag_v1 (theme: 'system' default; single chip with optional × close icon, default removable=true; pass tone for accent / success / warning / error palettes).
  • "user card", "contact card", "people picker row", "user mini card", "用户卡片", "联系人卡片" → add_user_card_v1 (theme: 'system' default; compact fit_content tile, no trailing slot — used in lobbies / chip-style lists).
  • "members list", "team page row", "people row", "sharing dialog row", "user list with role", "team member row", "团队成员", "成员列表行" → add_member_row_v1 (theme: 'system' default; avatar + name + optional subtitle + trailing role badge / kebab menu / status dot).
  • "profile header", "profile hero", "about me block", "account header", "user profile page", "个人主页头部" → add_profile_header_v1 (theme: 'system' default; large centered avatar + display name + optional handle / bio).
  • "notification row", "notification item", "notification list cell", "通知行", "通知条目" → add_notification_row_v1 (theme: 'system' default)
  • "KPI cell", "trend metric", "metric comparison", "delta metric", "KPI 趋势", "趋势指标" → add_metric_comparison_v1 (theme: 'system' default)
  • "drawer", "side panel", "slide-in panel", "edit drawer", "detail panel", "抽屉", "侧滑面板" → add_drawer_shell_v1 (theme: 'system' default; full-height drawer with title + close ×; body composed via subsequent calls under its id).
  • "combobox", "autocomplete", "open dropdown", "command palette", "open select", "search with results", "自动补全", "下拉补全" → add_combobox_v1 (theme: 'system' default; OPEN-state input + dropdown with N suggestion rows; one row optionally highlighted: true).
  • "toolbar", "editor toolbar", "formatting toolbar", "kanban actions", "icon button row", "工具栏" → add_toolbar_v1 (theme: 'system' default; horizontal 36×36 icon buttons + optional vertical dividers).
  • "callout", "tip block", "doc note", "did you know", "info box", "提示框", "信息块" → add_callout_v1 (theme: 'system' default; tinted block with body + optional title + tone-driven leading icon: info / success / warning / danger / note).
  • "inline action", "Undo button inline", "Saved • Retry", "comment deleted undo", "inline feedback", "inline action row" → add_inline_action_v1 (theme: 'system' default; left message + right blue action label, NO floating).
  • "share row", "share to social", "share buttons", "post share", "send via", "分享按钮组" → add_share_row_v1 (theme: 'system' default; horizontal circular icon buttons each labeled below).
  • "chart legend", "legend item", "legend entry", "数据图例", "图例条目" → add_legend_item_v1 (theme: 'system' default)
  • "inbox row", "email row", "message list cell", "mail item", "email preview", "邮件条目", "收件箱条目" → add_inbox_message_v1 (theme: 'system' default)
  • "settings row", "preference row", "menu item with toggle", "settings list item", "设置项", "偏好项", "开关行" → add_setting_row_v1 (theme: 'system' default; icon + title/subtitle + trailing chevron/value/switch/badge).
  • "facet panel", "filter sidebar", "category checklist", "brand filter", "applied filters group", "搜索筛选侧栏", "分面筛选", "类目筛选" → add_filter_group_v1 (theme: 'system' default; heading + vertical checkbox-style option list with optional counts).
  • "pending invite", "invitation row", "team invite", "邀请列表行", "待接受邀请", "invitations table row" → add_invite_row_v1 (theme: 'system' default; initial avatar + email/role + status pill + trailing action).
  • "audit log row", "activity feed entry", "recent activity item", "audit entry", "审计日志条目", "活动记录", "操作日志行" → add_activity_log_v1 (theme: 'system' default; single line: optional tinted icon dot + " " + right-aligned timestamp).
  • "event card", "agenda item", "meeting tile", "upcoming event", "calendar event row", "日程卡片", "会议条目", "活动卡片" → add_event_card_v1 (theme: 'system' default; date column with month band + day number, then title + time + location).
  • "onboarding step", "how-it-works step", "tutorial step card", "setup checklist item", "操作步骤卡片", "教程步骤", "新手引导步骤" → add_step_card_v1 (theme: 'system' default; numbered circle / check + title + description, stacks vertically).

STILL use batch_design when (emit a SINGLE batch_design for the whole response — do NOT mix with element-tool calls):

  • The brief's items are structurally heterogeneous (can't be uniformly described by a single items[] shape)
  • The brief needs a custom container or layout that no element tool covers (e.g. a horizontal row of pricing cards with a specific gap, a scroll row + sibling content)
  • The brief asks for unusual styling (custom fills, typography, theme variables) on top of a known structure

Common compositions (cookbook)

When the user asks for a recognizable screen pattern (login, signup, settings, paywall, dashboard tile row, support chat), STACK existing element tools under one parent rather than reaching for batch_design. The recipes below are by-frequency-of-real-use; each one fits in 4-7 tool calls.

Login screen (phone + password + social)

add_heading_v1({ parent_id: "<page>", content: "Welcome back", theme: "system" })
add_body_text_v1({ parent_id: "<page>", content: "Sign in to continue", theme: "system" })
add_phone_input_v1({ parent_id: "<page>", label: "Phone number", country_code: "+1", country_flag: "🇺🇸", required: true, theme: "system" })
add_form_field_v1({ parent_id: "<page>", label: "Password", required: true, theme: "system" })
add_text_button_v1({ parent_id: "<page>", label: "Sign in", theme: "system" })
add_link_v1({ parent_id: "<page>", label: "Forgot password?", theme: "system" })
add_divider_v1({ parent_id: "<page>", theme: "system" })
add_social_login_row_v1({ parent_id: "<page>", providers: [{ name: "Google" }, { name: "Apple" }], theme: "system" })

Signup form (email + password + agreement)

add_heading_v1({ parent_id: "<form>", content: "Create your account", theme: "system" })
add_form_field_v1({ parent_id: "<form>", label: "Email", required: true, theme: "system" })
add_form_field_v1({ parent_id: "<form>", label: "Password", required: true, theme: "system" })
add_form_field_v1({ parent_id: "<form>", label: "Confirm password", required: true, theme: "system" })
add_checkbox_v1({ parent_id: "<form>", label: "I agree to the Terms of Service", checked: false, theme: "system" })
add_text_button_v1({ parent_id: "<form>", label: "Sign up", theme: "system" })

Settings page (groups of setting rows)

add_section_header_v1({ parent_id: "<page>", title: "Account", theme: "system" })
add_setting_row_v1({ parent_id: "<page>", title: "Profile", leading_icon: "user", theme: "system" })
add_setting_row_v1({ parent_id: "<page>", title: "Email", leading_icon: "mail", trailing: { kind: "value", value: "you@acme.com" }, theme: "system" })
add_divider_v1({ parent_id: "<page>", theme: "system" })
add_section_header_v1({ parent_id: "<page>", title: "Notifications", theme: "system" })
add_setting_row_v1({ parent_id: "<page>", title: "Push notifications", leading_icon: "bell", trailing: { kind: "switch", on: true }, theme: "system" })
add_setting_row_v1({ parent_id: "<page>", title: "Email digest", leading_icon: "mail", trailing: { kind: "switch", on: false }, theme: "system" })

Team / members list (avatars + pending invitations)

add_section_header_v1({ parent_id: "<page>", title: "Members", theme: "system" })
add_body_text_v1({ parent_id: "<page>", content: "5 people", theme: "system" })
add_member_row_v1({ parent_id: "<page>", name: "Sarah Lee", subtitle: "sarah@acme.com", initial: "S", trailing: { kind: "role_badge", value: "Owner" }, theme: "system" })
add_member_row_v1({ parent_id: "<page>", name: "Marcus Chen", subtitle: "marcus@acme.com", initial: "M", trailing: { kind: "role_badge", value: "Admin" }, theme: "system" })
add_member_row_v1({ parent_id: "<page>", name: "Aiko Tanaka", subtitle: "aiko@acme.com", initial: "A", trailing: { kind: "role_badge", value: "Editor" }, theme: "system" })
add_member_row_v1({ parent_id: "<page>", name: "Raj Patel", subtitle: "raj@acme.com", initial: "R", trailing: { kind: "role_badge", value: "Editor" }, theme: "system" })
add_member_row_v1({ parent_id: "<page>", name: "Jordan Kim", subtitle: "jordan@acme.com", initial: "J", trailing: { kind: "role_badge", value: "Viewer" }, theme: "system" })
add_divider_v1({ parent_id: "<page>", theme: "system" })
add_section_header_v1({ parent_id: "<page>", title: "Pending invitations", theme: "system" })
add_invite_row_v1({ parent_id: "<page>", email: "leon@acme.com", role: "Editor", status: "pending", action_label: "Resend", theme: "system" })

Audit / activity feed (N log entries under a header)

add_section_header_v1({ parent_id: "<panel>", title: "Recent activity", theme: "system" })
add_body_text_v1({ parent_id: "<panel>", content: "Last 24 hours", theme: "system" })
add_activity_log_v1({ parent_id: "<panel>", actor: "Sarah Lee", action: "approved the production deploy", timestamp: "2h ago", icon: "check", tone: "success", theme: "system" })
add_activity_log_v1({ parent_id: "<panel>", actor: "Marcus Chen", action: "uploaded final-mockups.zip", timestamp: "3h ago", icon: "upload", tone: "info", theme: "system" })
add_activity_log_v1({ parent_id: "<panel>", actor: "Aiko Tanaka", action: "invited jordan@acme.com to the workspace", timestamp: "5h ago", icon: "user-plus", tone: "info", theme: "system" })
add_activity_log_v1({ parent_id: "<panel>", actor: "System", action: "rate-limited an IP after 50 failed sign-ins", timestamp: "8h ago", icon: "alert-triangle", tone: "warning", theme: "system" })
add_activity_log_v1({ parent_id: "<panel>", actor: "Raj Patel", action: "updated billing details", timestamp: "yesterday", icon: "settings", tone: "neutral", theme: "system" })
add_activity_log_v1({ parent_id: "<panel>", actor: "Sarah Lee", action: "deleted archive-2024.zip", timestamp: "yesterday", icon: "trash", tone: "danger", theme: "system" })

Faceted search filter sidebar (N filter groups stacked)

add_filter_group_v1({ parent_id: "<sidebar>", title: "Category", options: [{ label: "Apparel", count: 124, selected: true }, { label: "Footwear", count: 86 }, { label: "Bags", count: 41 }, { label: "Accessories", count: 67 }], theme: "system" })
add_filter_group_v1({ parent_id: "<sidebar>", title: "Brand", options: [{ label: "Nike", count: 32 }, { label: "Adidas", count: 28 }, { label: "Patagonia", count: 15, selected: true }, { label: "Arc'teryx", count: 9 }], theme: "system" })

Onboarding "How it works" (N step cards)

add_heading_v1({ parent_id: "<page>", content: "Get started in minutes", theme: "system" })
add_body_text_v1({ parent_id: "<page>", content: "Three steps to a smarter wallet.", theme: "system" })
add_step_card_v1({ parent_id: "<page>", number: 1, title: "Create your account", description: "Use your email and a strong password to sign up. No credit card required.", theme: "system" })
add_step_card_v1({ parent_id: "<page>", number: 2, title: "Connect your bank", description: "Link your account in seconds. We use 256-bit encryption to keep your data safe.", theme: "system" })
add_step_card_v1({ parent_id: "<page>", number: 3, title: "Set your goals", description: "Tell us what you want to save for — we'll do the rest.", theme: "system" })
add_step_card_v1({ parent_id: "<page>", number: 4, title: "You're all set", description: "You're ready to use the app. Tap below to continue.", completed: true, theme: "system" })
add_pricing_card_v1({ parent_id: "<page>", tier: "Starter", price: "0", period: "/month", features: ["3 projects", "Community support"], theme: "system" })
add_pricing_card_v1({ parent_id: "<page>", tier: "Pro", price: "29", period: "/month", features: ["Unlimited projects", "Priority support", "Advanced analytics"], emphasis: "featured", theme: "system" })
add_pricing_card_v1({ parent_id: "<page>", tier: "Enterprise", price: "Custom", features: ["Dedicated support", "SSO", "SLA"], cta: "Contact sales", theme: "system" })

Dashboard KPI strip (4 stat cards)

add_stat_card_v1({ parent_id: "<page>", label: "Revenue", value: "$12.4k", icon: "trending-up", delta: "+8%", trend: "up", theme: "system" })
add_stat_card_v1({ parent_id: "<page>", label: "Active users", value: "1,284", icon: "users", delta: "+3%", trend: "up", theme: "system" })
add_stat_card_v1({ parent_id: "<page>", label: "Churn", value: "3.2%", icon: "user-minus", delta: "-0.4%", trend: "down", theme: "system" })
add_stat_card_v1({ parent_id: "<page>", label: "Sessions", value: "5,471", icon: "activity", theme: "system" })

OTP / 2FA verification screen

add_heading_v1({ parent_id: "<page>", content: "Enter verification code", theme: "system" })
add_body_text_v1({ parent_id: "<page>", content: "We sent a 6-digit code to +1 (555) 123-4567", theme: "system" })
add_otp_input_v1({ parent_id: "<page>", length: 6, digits: ["1", "2", "3"], focused_index: 3, theme: "system" })
add_text_button_v1({ parent_id: "<page>", label: "Verify", theme: "system" })
add_link_v1({ parent_id: "<page>", label: "Resend code", theme: "system" })

Support chat thread

add_chat_bubble_v1({ parent_id: "<thread>", message: "Hi! How can I help today?", side: "left", author: "Sarah", timestamp: "Just now", theme: "system" })
add_chat_bubble_v1({ parent_id: "<thread>", message: "My order hasn't arrived.", side: "right", timestamp: "2m", theme: "system" })
add_chat_bubble_v1({ parent_id: "<thread>", message: "Sorry to hear! Let me check on that.", side: "left", author: "Sarah", timestamp: "1m", theme: "system" })
add_attachment_row_v1({ parent_id: "<thread>", filename: "receipt.pdf", size: "240 KB", icon: "file-text", theme: "system" })

Empty inbox / first-run onboarding

add_empty_state_v1({ parent_id: "<page>", title: "No messages yet", subtitle: "When someone messages you, it'll show up here.", icon: "inbox", cta_label: "Find friends", theme: "system" })

Composition rules of thumb

  • One parent for one row of siblings. Don't pass parent_id of an unrelated container.
  • Order matters. Tools insert as the LAST child of parent_id, so call sequence is render order top-to-bottom (vertical) or left-to-right (horizontal).
  • Don't mix element tools and batch_design in the same output. Pick one strategy: chain add_*_v1 calls (preferred when every component fits an element tool) OR a single batch_design covering the whole brief (when at least one component needs a custom shape). The corpus harness drops batch_design tags whenever element-tool calls share the response, so a mixed output silently loses its scaffolding.

Invariants you don't need to think about

The tool guarantees — you cannot break them from the input side:

  • Wrapper structure (scroll-row-wrapper + scroll-row + fixed-width children) for row tools — overflow-safe
  • bottom-tab-bar is inline (no empty spacer sibling needed, do NOT add one)
  • Activity ring is frame+cornerRadius=size/2+stroke+centered text — NEVER emit ellipse+sibling text for rings
  • Every emitted node has a unique id (you can reference it later)
  • Roles are set (card / metric-tile / nav-chip / nav-chip-active / bottom-tab-bar / nav-item / nav-item-active / activity-ring / stat-grid / stat-cell / section-header / section-header-title / section-header-action / top-nav-bar / nav-spacer / icon-button / divider / badge / avatar / button / heading / body / label / icon-label / list-row / list-row-text / search-bar / form-field / form-input / switch / switch-thumb / checkbox / checkbox-checked / checkbox-row / radio / radio-selected / radio-row / radio-dot / tabs / tab / tab-active / tab-underline / segmented-control / segment / segment-active / empty-state / empty-state-icon / empty-state-title / empty-state-subtitle / alert / alert-message / alert-close / toast / toast-message / progress-bar / progress-bar-fill / fab / breadcrumb / breadcrumb-item / breadcrumb-item-active / breadcrumb-separator / stepper / step / step-active / step-connector / step-connector-active / rating-stars / star-filled / star-empty / link / link-label / link-icon / kbd / kbd-key / kbd-glyph / kbd-separator / carousel-dots / dot / dot-active / price / price-currency / price-amount / price-period / quote-block / quote-text / quote-author / code-block / code / color-swatch / color-swatch-square / color-swatch-label / chart-bars / chart-bar / timeline / timeline-item / timeline-icon-column / timeline-dot / timeline-dot-active / timeline-connector / timeline-content / timeline-title / timeline-subtitle / calendar-grid / calendar-header-row / calendar-header / calendar-week / calendar-day / calendar-day-today / calendar-day-selected / calendar-day-empty)

Failure mode

If the tool throws, do NOT retry with the same arguments — the tool has already verified the failure is real (pre-check rejected the parent_id, or post-check detected a silent DSL no-op). Re-throwing from your side wastes tokens. Inspect the error message and either:

  • Fix parent_id (ensure the referenced node exists and has no " or \ in its id)
  • Switch to batch_design with the structure taught in overflow.md / layout.md