Skip to content

Stable presentation renderer profile

Status: Accepted

Components V4 needs an honest extension point for adapting common primitives without implying that a vendor renderer replaces the full Components catalog. The experimental renderer system proved a larger fourteen-slot model, but five of those slots own interactions rather than presentation and have not earned the same compatibility promise.

The stable-presentation/v1 candidate was tested independently by four implementations: the private plain-DOM falsification fixture, MUI, PrimeReact 11, and PrimeReact 10. Each implementation passed every applicable conformance check with zero failures and zero skips. The generated report, rather than a hardcoded count in this decision, inventories the exercised checks. The proof covers the exact public props, refs, parts, state, behavior ownership, server rendering, hydration, and bounded accessibility assertions recorded by the conformance package. It does not turn the remaining experimental renderer system into a stable API.

Renderer ABI major 1 promotes one immutable profile through @cratis/components/renderer:

  • common.button
  • common.iconButton
  • common.textInput
  • common.textArea
  • common.checkbox
  • common.radio
  • common.switch
  • common.progress
  • common.surface

The stable API is identified by CRATIS_PRESENTATION_PROFILE, CRATIS_PRESENTATION_ABI_VERSION, and cratisPresentationSlotIds. Its CratisPresentationUiLibrary declaration requires all nine slots, presentation behavior ownership, native or emulated fidelity, and the slot.render, parts.passthrough, and ssr.staticRender capabilities. definePresentationUiLibrary() validates the same boundary for JavaScript callers, rejects duplicate capabilities, and defensively copies/freezes the manifest through the shared manifest machinery.

The profile also stabilizes the non-secret boolean setup contract used by certified providers: CratisRendererSetupExtensions, CratisRendererSetup, and CratisPresentationUiLibraryProviderProps. Adapter declaration merging may add boolean attestations only. Credentials, license keys, caches, provider instances, and mutable configuration objects remain impossible at this boundary.

CratisOverlayEnvironment is a separate stable V4 host contract. It resolves a portal container on demand and may return null when no container is available. Internal overlay hooks remain experimental.

The MUI, PrimeReact 11, and PrimeReact 10 package manifests are stable CratisPresentationUiLibrary values. Selecting one certifies nine-slot primitive adaptation only. It never promises full-catalog replacement.

Removing a stable-presentation/v1 slot, changing its identifier, changing its public component props or ref contract, changing presentation behavior ownership, or weakening its required fidelity is a breaking change.

Adding a slot is not a compatible expansion of stable-presentation/v1. Additions require a new named profile and version so existing adapters never acquire an unimplemented requirement. The conformance package and the three certified adapters share the Components repository release version. Renderer ABI major 1 remains separate from npm versioning, and every adapter retains the honest @cratis/components >=4 <5 peer range.

The following surfaces keep their unstable_ prefix and carry no promise from this decision:

  • the open fourteen-slot table and generic UiLibrary manifest;
  • atomic slots and BehaviorMode;
  • capabilities outside the bounded presentation subset;
  • adapter diagnostics and errors;
  • manifest composition;
  • RendererScope, islands, and only routing;
  • useCapability, useRendererId, and internal overlay hooks;
  • the built-in full manifest;
  • lazy loading, preload behavior, and adapter discovery tooling.

The unused unstable_RendererExtensions and unstable_RendererProps declarations are removed. No component or adapter consumed them, so retaining them would advertise renderer-specific prop bags that did not exist. Portable customization remains the typed pt contract.

Applications keep zero-configuration built-in behavior. The package root remains setup-only, the React/browser-DOM-free kernel boundary remains unchanged, and Core gains no PrimeReact dependency. Adapter authors can depend on a small stable façade while experimental work continues behind explicit unstable_ names.

Conformance evidence is bounded evidence, not a universal claim about every browser, theme, assistive technology, security posture, or application shell. Adapter packages continue to publish their exact peer, license, and conformance metadata.