3.4 KiB
<ReactUiProvider> — opinionated chassis composition
(no submodules)
Purpose
The opinionated 95%-case wrapper for the chassis. Composes the three
primitive providers in the canonical order <TranslationProvider> →
<ThemeProvider> → <PackRegistryProvider> and adds an effect-driven
loader that auto-registers the chassis bundled translations into the
active i18n catalog (with optional consumer overrides applied on top).
Emits the react_ui.provider.mount OTel span on every mount.
Features
- 15-line provider composition in the right order
- Auto-registration of the bundled chassis locale on mount
- Consumer overrides via
reactUiOverrideswin over the default bundle keys - Re-loads the bundle on
languageChangedso a runtime locale switch picks up the matching translations automatically - Records
react_ui.locale.bundle.load_total{locale, outcome}andreact_ui.locale.bundle.load_duration_ms{locale}per load - Records the
react_ui.provider.mountspan carryingtheme,pack.count, andlocaleattributes - Defers to
<TranslationProvider>for the i18n instance (the Provider is modecaller-managedbecause we always passi18n)
Usage: Basic example
import { ReactUiProvider } from "@suaveplan/react-ui/provider";
import { lightTheme } from "@suaveplan/react-ui/theme";
import { createI18n } from "@suaveplan/i18n/plugin";
const i18n = createI18n({ defaultLocale: "en-GB" });
<ReactUiProvider i18n={i18n} themes={[lightTheme]} defaultTheme="light">
<App />
</ReactUiProvider>;
Usage: Advanced example
import { ReactUiProvider } from "@suaveplan/react-ui/provider";
import {
darkTheme,
highContrastTheme,
lightTheme,
} from "@suaveplan/react-ui/theme";
import { authPack } from "@suaveplan/react-ui-pack-auth";
<ReactUiProvider
i18n={i18n}
themes={[lightTheme, darkTheme, highContrastTheme]}
defaultTheme="light"
packs={[authPack]}
components={{ auth: { LoginForm: AcmeLoginForm } }}
reactUiOverrides={{
"en-GB": {
"react-ui.themeToggle.label": "Appearance",
},
}}
scriptNonce={cspNonce}
>
<App />
</ReactUiProvider>;
API Reference
<ReactUiProvider>— props perReactUiProviderProps:i18n: I18nInstance— requiredthemes: ReadonlyArray<ThemePlugin>— requireddefaultTheme: string— requiredpacks?: ReadonlyArray<ComponentPack>components?: RuntimeComponentOverridereactUiOverrides?: ReactUiLocaleOverrideslogger?: PackLoggerLikescriptNonce?: stringstorageKey?: stringattribute?: stringchildren: ReactNode
type ReactUiLocaleOverrides = Partial<Record<SupportedLocale, Partial<Record<TranslationKey, string>>>>
Implementation notes
The bundle loader runs inside a useEffect and tracks an aborted-flag
ref so a fast unmount does not leak a stale registration into the
catalog. The languageChanged listener is registered on the i18n
event bus rather than on the React reactive state because the i18n
instance owns the locale truth — re-deriving from React state would
introduce a one-render lag on every locale switch. The span.end()
fires synchronously (before the lazy bundle resolves) so the trace
boundary matches the React commit boundary; the bundle-load duration
is captured separately via the histogram.