AI Authoring Rules
Compact rules for models that generate ToonUI inside markdown.
This is the shortest correct mental model:
The AI writes normal markdown plus valid
toon-uiblocks, using ONLY the official catalog and canonical syntax.
If the model is uncertain, it must simplify. It must NOT improvise.
Quick path
- Write normal markdown when plain prose is enough.
- Add a fenced
toon-uiblock when the user needs structured UI. - Use only official components, official variants, and canonical syntax.
- If unsure, fall back to a smaller safe subset like
card,text,table,form,confirm, orlist.
Hard rules
- Output markdown + optional
toon-uifenced blocks only - Never output React
- Never output HTML
- Never output CSS
- Never output JavaScript
- Never output component JSON
- Never invent components
- Never invent props
- Never emit raw HTML or scripts inside
text - Never execute business actions directly
Official components only
Allowed today:
textheadingseparatorcardformfieldbuttonconfirmlistitembadgealerttableemptytabsaccordiondialogsheetpopovertooltipprogressloadingtoastbreadcrumbpaginationmenucommandchart
Structural child nodes are ALSO part of the canonical language, but only inside the correct parent:
crumbinsidebreadcrumbactioninsidemenuandcommandtabinsidetabssectioninsideaccordionseriesinsidechartpointinsideseries
Never invent pseudo-components like:
headerfootersubtitledescriptioninputmodalstackgriddivider
Canonical syntax
text "Visible text"
heading <1-6> "Visible text"
separator
separator horizontal
separator vertical
card "Title" [description="..."]:
form "Title" [description="..."]:
field <name> <fieldType> "Label" [placeholder="..."] [helper="..."] [required] [options="A|B"] [min=<number>] [max=<number>] [step=<number>] [value="..."]
button <variant> "Label" reply="Value"
button <variant> "Label" submit
confirm <variant> "Title" [trigger="..."] [description="..."]:
list "Title":
item "Title" [description="..."]:
badge "Label" <variant>
alert <variant> "Title" [description="..."]:
table "Title":
empty "Title" [description="..."]:
tabs "Title":
tab "Label":
accordion "Title":
section "Title":
dialog "Title" [trigger="..."] [description="..."]:
sheet "Title" [trigger="..."] side="left|right|top|bottom":
popover "Title" [trigger="..."]:
tooltip "Visible text" [trigger="..."]
progress "Label" value=<number> max=<number>
loading "Visible text"
toast <variant> "Visible text"
breadcrumb:
crumb "Label" [reply="Value"]
pagination page=<number> totalPages=<number>
menu "Title":
action "Label" reply="Value"
action "Label" submit
action "Label" reply="Value" variant="secondary"
command "Title" [trigger="..."]:
action "Label" reply="Value"
action "Label" submit
chart <type> "Title" [description="..."] [x="..."] [y="..."]:
series "Label":
point "Label" <number>Required rules by component
Quoted titles
These nodes always require a quoted title:
cardformconfirmlistitemalerttableemptytabsaccordiondialogsheetpopovermenucommandchart
Required structure
| Component | Required rule |
|---|---|
button | Must include variant, label, and either reply="..." or submit |
form | Must include title, one or more field nodes, and one submit button |
alert | Must include variant, title, optional description="...", :, and nested children |
empty | Must include title, :, and nested children |
progress | Must include label, value=<number>, and max=<number> |
pagination | Must include page=<number> and totalPages=<number> |
badge | Never has children and never takes a title prop |
breadcrumb | Must include one or more crumb children |
menu / command | Must include one or more action children, and each action must use reply="..." or submit |
tabs | Must include one or more tab children |
accordion | Must include one or more section children |
chart | Must include one or more series children, and each series must include one or more point rows |
field | select, radio, and multiselect need options; slider needs min and max; default values use quoted value="...", and React renders that value as the initial input value |
Fields are data-capture controls. They belong inside form.
Wrong:
dialog "Contact customer" description="Send a message to the customer.":
field message textarea "Message" required
button primary "Send" submitCorrect:
dialog "Contact customer" description="Send a message to the customer.":
form "Customer message" description="Write the message before sending.":
field message textarea "Message" required
button primary "Send" submitIf a submit is incomplete, do not rebuild the full original form. Ask only for the missing or invalid fields and preserve the valid submitted values in conversation state.
description rule
Use description="..." ONLY on:
cardformalertconfirmdialogitememptychart
Do NOT invent description for other nodes.
Variants and families
Button variants
primarysecondarydangerghostoutline
Badge variants
successwarningdangerneutralinfo
Alert variants
infosuccesswarningdanger
Confirm variants
neutralinfowarningdangersuccess
Chart types
barlineareapie
Field types
textemailnumberpassworddatetimetextareaselectcheckboxradioswitchcomboboxotpslidermultiselect
Table rules
Tables must use:
columns:row:
And every column and cell should be quoted. This matters MOST when values contain commas, currency, or large numbers.
Correct example:
table "Sales":
columns: "Date", "Sale number", "Total", "Status"
row: "May 14", "177877222574876", "$ 387.45", "Completed"UI decision rules
Prefer ToonUI instead of plain markdown when the user needs to:
- choose
- confirm
- complete structured data
- view structured results
- compare values
- navigate options
Decision defaults:
- if 2 or more structured inputs are needed, use
form - if there are multiple results, prefer
tableorlist - if one entity needs a next action, prefer
cardplus buttons - if the action is destructive, prefer
confirm danger - if the action is risky but not destructive, prefer
confirm warning
Never ask “do you want me to build a UI?” when it is already obvious that UI is the right response.
Composition rules
- Prioritize useful UI, not explanation about UI
- Prefer one focused ToonUI block per intent
- Keep actions close to the data they affect
- Prefer simple trees over unnecessary nesting
- Use
emptyfor empty states - Use
chartonly for trend/comparison analysis - If syntax confidence drops, fall back to simpler valid nodes
What NOT to do
These anti-patterns are important because AI systems often copy visible patterns literally.
Do NOT invent components
Wrong:
header "Customer"
grid:
text "Name"Why it is wrong:
headerandgridare not official ToonUI nodes
Do NOT omit explicit actions
Wrong:
button primary "Create product" "start-create-product"
action "Open reports" "open-reports"Correct:
button primary "Create product" reply="start-create-product"
action "Open reports" reply="open-reports"Why it is wrong:
buttonandactionrequirereply="..."orsubmit
Do NOT use structural child nodes outside their parent
Wrong:
tab "Summary":
text "Active"Correct:
tabs "Customer profile":
tab "Summary":
text "Active"Why it is wrong:
tab,section,crumb,action,series, andpointare structural child nodes- they only work inside their valid parent
Do NOT create incomplete containers
Wrong:
form "Create product":
field name text "Name"Why it is wrong:
formneeds at least onefieldformalso needs a submitbutton
Wrong:
alert "Low stock"Why it is wrong:
alertneeds a variant, a quoted title, optionaldescription="...",:, and nested children
Do NOT use unquoted field defaults
Wrong:
field active switch "Active" value=true
field score slider "Score" min=0 max=10 step=1 value=7Correct:
field active switch "Active" value="true"
field score slider "Score" min=0 max=10 step=1 value="7"Why it is wrong:
- the parser reads field defaults from quoted
value="...", and@toon-ui/reactuses that value as the initial rendered input value
Do NOT leave table cells ambiguous
Risky:
row: May 09, $ 8,155.35, CompletedCorrect:
row: "May 09", "$ 8,155.35", "Completed"Why it is wrong:
- commas inside values can break parsing intent
- quote every table column and cell
Do NOT ask prose questions when UI is obvious
Bad:
Do you want me to build a form for this?Better:
form "Create product":
field name text "Name" required
field price number "Price" required
button primary "Create product" submitWhy it is wrong:
- when structured input is already needed, ToonUI should reduce back-and-forth
Language rule
Prompt instructions may be in English, but visible UI copy should follow the user's language:
- labels
- titles
- button text
- field labels