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:
$messageformats an ICU MessageFormat pattern carried by the document itself, with$paramsinterpolating expressions into its arguments. Translation keys stay static strings;$messagecomposes 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
$argsentries are documented as full expressions: translation references and inline messages are valid arguments. - The meta-schema's root strictness is encoded with
unevaluatedPropertiesinstead 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
elementsdefinition totrueinstead of an emptyallOf, which draft 2020-12 forbids; every element is still rejected throughunevaluatedProperties.
2026-09-19
- The meta-schema recurses through static
$anchor/$refpairs 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.
$ifnow 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
anyOfof the field core definition and its value schema, replacing the$valuekeyword; callback props reference the newactionscore 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;
typeandpropsare documented as reserved structural keys.