Renderer adapters and coexistence
A product rarely replaces its entire interface at once. It may use Components for Arc-aware forms and data surfaces, retain a vendor grid for one specialized screen, and adopt a different visual language for ordinary controls. Components supports that coexistence without claiming that every surface becomes interchangeable.
The ownership boundary
Section titled “The ownership boundary”The default path is built in. Install @cratis/components, mount CratisComponentsProvider, and
omit library. Components then renders its Components-owned React and HTML contracts. Semantic
native HTML handles simple controls, while the installed React Aria foundation supplies selected
focus, collection, date, and overlay behavior internally.
An optional adapter changes only the renderer slots that it declares:
| Package | Current upstream boundary | Declared coverage |
|---|---|---|
@cratis/components.mui | MUI 9 and Emotion 11 | Nine stable presentation slots |
@cratis/components.primereact | PrimeReact 11 and PrimeUX themes 3 | Nine stable presentation slots |
@cratis/components.primereact10 | PrimeReact >=10.9.9 <11 | Nine stable presentation slots |
All three adapters publish stable CratisPresentationUiLibrary manifests for renderer ABI version 1. They do not replace DataPage, DataTables, CommandDialog, CommandForm, Toolbar, Canvas, or another Components-owned composition. The primitive adaptation reference lists the exact nine-slot profile. Stable profile selection means nine-slot primitive adaptation, never full-catalog replacement.
The application-owned vendor surface is a sibling, not a hidden replacement for the Components composite.
Direct vendor coexistence
Section titled “Direct vendor coexistence”Keep direct vendor usage explicit. The application owns that vendor’s package, provider, theme,
server-rendering setup, portal configuration, and license. Mount the vendor provider at the smallest
host boundary that needs it, and keep CratisComponentsProvider responsible only for Components
configuration and any selected adapter.
A direct vendor island does not need to register itself as a renderer. Register an adapter only when it implements the public renderer ABI and accepts the exact slot props. Use custom composition when an entire workflow needs vendor-native capabilities that a Components composite does not claim.
Providers and setup values
Section titled “Providers and setup values”A renderer library may mount its own provider around the selected Components scope. Application
resources that the renderer ABI cannot safely transport stay outside that scope. The stable
CratisRendererSetup shape accepts only adapter-declared boolean attestations. Never place a
credential, license key, cache, provider instance, or mutable configuration object in it.
PrimeReact 11 demonstrates the boundary: the application passes its key directly to its own outer PrimeReact provider, then gives Components only a non-secret boolean assertion that setup occurred. The adapter fails closed when the provider or assertion is absent. The licensing policy explains this boundary without making a licensing conclusion for an application.
Portals and z-index
Section titled “Portals and z-index”The built-in overlay environment resolves document.body only when an overlay needs a container.
A host may supply overlayEnvironment to return another container. Returning null defers the
overlay; it does not silently retarget it.
Direct vendor overlays keep their vendor configuration. Components does not merge a vendor portal registry or z-index service with its built-in overlay environment. When both systems can open simultaneously, the application must:
- choose containers that are not clipped by local overflow;
- assign an explicit layer order for Components and vendor overlays;
- verify nested menus, listboxes, dialogs, and toasts in the real application shell; and
- keep theme CSS and portal CSS available in every chosen container.
The nine-slot adapters do not include dialog, dropdown, date-picker, tooltip, or paginator atomic slots. Those controls therefore use the built-in implementation unless another adapter explicitly and honestly declares them.
Focus ownership
Section titled “Focus ownership”One interactive surface owns one focus lifecycle. Do not place one modal implementation inside another modal merely to borrow vendor appearance, and do not combine two focus traps, dismissal listeners, or keyboard-selection owners for the same interaction. A presentation adapter must preserve the Components contract without adding a second semantic control. An atomic adapter, if one is selected, owns the complete interaction instead of wrapping the built-in owner.
This rule is structural, not a universal accessibility certification. Verify keyboard order, initial focus, focus restoration, escape handling, background inertness, and screen-reader output in the application’s supported browsers and assistive technologies.
Adapter package metadata schema
Section titled “Adapter package metadata schema”Adapter authors can validate the static cratis object in their package manifest against the public JSON Schema exported by Components:
import uiAdapterSchema from '@cratis/components/schemas/ui-adapter.schema.json' with { type: 'json' };The export path is @cratis/components/schemas/ui-adapter.schema.json; its canonical $id is https://cratis.io/schemas/ui-adapter.schema.json, and it uses JSON Schema draft 2020-12. It validates the metadata object itself, not the entire package.json.
An adapter package places that object under the cratis key. The schema requires the adapter identity and display name, renderer ABI range, adaptation level and profile, category, package entry/export names, slot and mode declarations, capabilities, SSR behavior, accessibility claims, license information, and upstream dependency metadata. Unknown properties are rejected so misspelled or unsupported claims do not silently pass.
Use the schema for editor/build-time manifest validation, then run @cratis/components.conformance against the loaded adapter library for runtime contract checks. Schema validity proves only that the static declaration has the supported shape; it does not prove rendering fidelity, behavior, accessibility, SSR safety, or license compatibility. Changes to this exported schema follow the @cratis/components package’s semantic versioning.
Continue
Section titled “Continue”- Use primitive adaptation when the nine stable controls need vendor presentation.
- Use custom composition when the workflow itself must be vendor-native.
- Check unsupported renderer claims before promising replacement behavior.