Skip to content

GenUI

Safety, accessibility, and styling

What a model's output can and cannot reach, how accessible names are enforced, and the hooks that style the headless output.

Model output is untrusted

Nothing a model writes reaches the DOM without passing through a schema and a component that renders it on purpose.

  • The validator drops every prop a schema does not declare, so dangerouslySetInnerHTML, on* handlers, style, srcDoc, className, id, and ref cannot reach the DOM. Component names are looked up in the catalog only, never through prototypes.
  • Links accept http(s):, mailto:, tel:, relative, and #fragment URLs; images accept http(s) and relative URLs. javascript:, data:, blob:, file:, protocol-relative URLs, and URLs hiding a scheme behind whitespace are not linked or loaded.
  • Absolute links get rel="noopener noreferrer", and images load lazily without a referrer.
  • Text is text: Markdown and HTML are shown literally, including text computed from what the person typed.
  • Expressions run in a whitelisted evaluator with size limits and cannot reach globals, prototypes, or functions outside the list.
  • Buttons and submits are disabled while a response streams, so nothing acts on a half-written interface.

Limits

A response cannot lock the page: past these limits the rest is left out.

Response limits
LimitValue
Components per response1000
Component nesting40 levels
Items in a list or data prop500
Table size24 columns and 800 cells
Response text2 MB, nested at most 100 levels deep
Expression500 characters and 200 nodes
Reported errors50

Accessible by schema

A model is a poor judge of accessibility, so the schemas require the accessible name of everything that needs one. A component without it is not drawn, and the error tells the model what to add.

  • Inputs require a label, buttons and links visible text, charts and cards a title, tables a caption, and images alt text. There are no icon-only components.
  • Charts include a data table, and fields support help text through aria-describedby.
  • Heading levels follow card nesting.
  • Warnings and errors are announced at once; other messages are polite.
  • The conformance suite runs axe over every answer at every stage of its stream, including open selects and calendars.

Style the output

comp0 ships no CSS. Every part carries a data-slot, and layout components carry token attributes that are absent when the model did not choose a value. The comp0 parts inside keep their own state attributes, such as data-checked, data-selected, data-open, and data-focus-visible, so one stylesheet themes everything a model can compose.

genui.csscss
[data-slot="stack"] {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

[data-slot="stack"][data-direction="row"] {
  flex-direction: row;
}

[data-slot="grid"][data-columns="3"] {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

[data-slot="card"][data-tone="accent"] {
  border-color: teal;
}
Token attributes
AttributeOnValues
data-directionStackcolumn, row
data-gapStack, Gridxs, sm, md, lg, xl
data-alignStackstart, center, end, stretch
data-wrapStackPresent when children wrap.
data-columnsGrid1 to 6
data-toneCarddefault, muted, accent
data-toneTextdefault, muted, success, warning, danger
data-sizeTextsm, md, lg
data-variantButtonprimary, secondary, danger
data-toneAlertinfo, success, warning, danger
data-numericTable cellsPresent on cells that hold numbers.