Skip to content

Compatibility

MacroDeck.Ui, MacroDeck.Ui.Model, and MacroDeck.Ui.Testing are public NuGet contracts. Existing keys, component meanings, patch semantics, and public API members must follow the normal compatibility policy.

The UI model’s Minimum is 3 and its Current is 4, and the gap between them is the difference between a rename and a widening.

The floor moved to 3 because the component vocabulary was renamed outright rather than extended: every widget.* node type became either ui.* or macrodeck.*, with no alias kept for the old spelling. A tree built against the old vocabulary is not representable under the new one, so a package that no longer understands a single widget.* type must not advertise the majors in which those were the only spelling.

The ceiling moved to 4 because an icon property may now carry a typed {"type":…,"reference":…} provider reference where it previously always carried a bare icon-pack reference string - the same shape as the move to 2, where a text property gained the option of carrying a localization reference. A producer built against 3 emits only the string form and one built against 4 may emit either, so the two are not interchangeable and the version has to say which a session speaks. The floor stayed where it was because nothing was renamed: a reader at 4 accepts both readings, so it still reads every tree a producer at 3 emits, and UiIconInput is unchanged.

Either way a client and a provider negotiate the model version as they always have - before a session is opened - and a mismatch produces the same graceful decline, never a tree the reader cannot parse.

New component types and new properties are additive and leave the model version alone; the component profile’s rule decides which of the two a new feature is. Modifiers add both:

Addition Shape An older reader
modifiers (background, radius, border, accessibility text, disabled) A property on any node Ignores it and draws the node plainer. A disabled subtree still offers none of its own events, because the DSL stopped it declaring them, but the reader does not know the region absorbs the tile’s press, so a deck tile’s own flows still run there.
drag, drag-end, swipe, pinch, pinch-end Event names Never sends a name it does not implement.
ui.modifier (padding, opacity, clip, mask, frame), component version 1 A type Draws the node’s explicit fallback; without one, none of the wrapped content (Macro Deck’s renderer shows a faint placeholder box). No fallback is invented for you.

See ADR 0064 for why the vocabulary is organized as a registry over the ui.*/macrodeck.* namespaces rather than one flat list, and The UI model for where negotiation sits in a session’s lifecycle.