Changelog

Revisions to the UI Schema language specification.

The specification is pre-release: revisions are listed by date, and breaking changes are called out. Once dialects pin language revisions by URI, entries here will carry those identifiers.

2026-09-20

  • Added inline messages: $message formats an ICU MessageFormat pattern carried by the document itself, with $params interpolating expressions into its arguments. Translation keys stay static strings; $message composes strings from data that no catalog owns, such as URLs.
  • Maps are valid on any prop that accepts an array, bindable fields and composition branches included. Where no single item schema is structurally identifiable, the meta-schema accepts any template and the resolved array is held to the prop's schema by the engine.
  • Action $args entries are documented as full expressions: translation references and inline messages are valid arguments.
  • The meta-schema's root strictness is encoded with unevaluatedProperties instead of an enumerated key set, and the control-flow wrapper shapes (ifThenElse, switchCase, map) live once in the definitions with small per-position branch overlays. Both are encoding changes: the accepted documents are unchanged.
  • Specified previously implicit engine behavior: the value model of tagged translations, reactivity of resolved values, the switch subject's string forms, lexical scope nesting, the inline-message fallback, and the structural probe deciding which positions take maps.
  • A dialect with no elements compiles its elements definition to true instead of an empty allOf, which draft 2020-12 forbids; every element is still rejected through unevaluatedProperties.

2026-09-19

  • The meta-schema recurses through static $anchor/$ref pairs instead of $dynamicAnchor/$dynamicRef. The two are equivalent while the meta-schema is self-contained, and static references keep it compatible with validators whose dynamic-reference support is incomplete.
  • Added the Patterns page and this changelog.

2026-09-18

  • Breaking: split the if/then/else condition into two keywords. $if now carries only the subject expression; the JSON Schema it must match moved to the new companion keyword $matches, which is optional and defaults to { "const": true }. The former tuple form ("$if": [value, schema]) is no longer part of the language. A tuple still validates structurally, as any literal subject does, but changes meaning; migrate by rewriting the tuple into the two keywords.
  • Breaking: element definitions are plain JSON Schema. A bindable field is declared as an anyOf of the field core definition and its value schema, replacing the $value keyword; callback props reference the new actions core definition, which accepts one dispatch or a sequence.
  • Added the Dialect section: Defining a Dialect and the Meta-Schema's core definitions, element definitions, and prop position composition.
  • Specified engine behavior for the unresolved and unmatched cases: missing data and translation references, conditionals without a selected branch, non-array map sources, out-of-scope arguments, unknown action handlers, and dispatch-time argument resolution. Behavior for nonconforming documents is undefined.
  • Removed the renderer mapping from the dialect's definition: a dialect declares element types and props only, and the engine maps types to renderer components.
  • Nested-element slots are dialect-declared props with no reserved name; type and props are documented as reserved structural keys.

On this page