@unofficialbox/box-open-elements-react
v0.19.0
Published
Optional React wrappers for box-open-elements Web Components. Thin adapters — core stays framework-agnostic.
Maintainers
Readme
@unofficialbox/box-open-elements-react
Optional React wrappers for box-open-elements Web Components.
The core package stays framework-agnostic. This adapter is a thin layer that:
- imports the automatically registered custom element
- syncs React props onto element properties (not fragile attribute stringification)
- forwards refs, and binds event callbacks directly to the element
Callbacks an adapter declares receive the native DOM event, not a React
SyntheticEvent. They are registered with addEventListener on the custom
element so the listener travels with it: React delegates from its root
container, so a node relocated out of that container silently stops receiving
delegated handlers. Button declares its own onClick, typed as
(event: MouseEvent) => void, for exactly that reason.
Props an adapter does not declare — including React's onClick on Select,
TextField and Dialog — are forwarded as ordinary host props and stay
delegated. That is fine unless something moves the node out of the React root,
and it is React's delegation model rather than these components': a plain
<div onClick> in a relocated subtree behaves the same. (box-drawer used to
relocate its subtree and no longer does — it uses the top layer.)
See docs/integration/react.md for the React
boundary and the framework adapter tracker
for cross-framework milestones.
Install
npm install @unofficialbox/box-open-elements @unofficialbox/box-open-elements-react react react-domimport { Button, Dialog, Select, TextField } from "@unofficialbox/box-open-elements-react";
import {
applyDesignTokens,
registerBoxDefaultDesignSystem,
} from "@unofficialbox/box-open-elements/foundations/tokens";
registerBoxDefaultDesignSystem({ setActive: true });
applyDesignTokens(document.documentElement, "box-default");
export function SaveAction() {
return (
<>
<TextField label="Project" value="Apollo" />
<Select
label="Status"
value="draft"
options={[{ label: "Draft", value: "draft" }]}
/>
<Button label="Save" tone="primary" onClick={() => console.log("saved")} />
</>
);
}The supported surface also includes a controlled Dialog wrapper and
useExplorerSelectionController, which subscribes React to the existing
headless selection controller without duplicating its state.
Status
Supported as of 0.7.0 — Button, TextField, Select, and Dialog prove
native and composed events, value and structured property synchronization, latest
callback routing, forwarded refs, controlled overlay focus behavior, and
server-safe host rendering. useExplorerSelectionController proves headless
controller composition. The two conditions this section used to defer on are met:
the first public npm publication happened at 0.7.0, and a clean registry install
resolves the package and loads its exports. React releases in lockstep with the
Angular, Vue, and Svelte adapters under adapters-vX.Y.Z, at the core's version.
Supported versions
| Dependency | Contract |
| --- | --- |
| React / React DOM | ^19.0.0 |
| @unofficialbox/box-open-elements | ^0.10.0 |
| Node.js for SSR | >=20.9.0 |
| Next.js validation host | 16.2.12 |
The package ships ESM JavaScript and declarations from dist/. The Next.js
fixture in examples/frameworks/react-ssr proves server prerendering, browser
upgrade, hydration, events, controller subscriptions, and overlay focus.
