Joy DOM

API reference

Props, types, and error behavior for @joy-dom/react.

<JoyDom> (component)

The primary entry point. Renders a Joy DOM document as React elements.

<JoyDom spec={spec} components={{ "contact-button": ContactButton }} />

Props (JoyDomProps)

PropTypeRequiredDescription
specSpecYesThe Joy DOM document.
componentsRecord<string, JoyDomComponent>NoCustom node registry, keyed by kebab-case type name.
actionsRecord<string, ActionHandler>NoHandlers for the document's event action bindings, keyed by action name.
missingAction"throw" | "ignore"NoWhat to do when a binding names an absent action. Defaults to "throw".
responsive"media" | "container"NoHow breakpoints resolve: viewport @media (default) or @container against its own box.
refRef<HTMLDivElement>NoRef to the host div that holds the shadow root — useful for measuring or screenshotting.

<JoyDom> renders into its own shadow root, so the document's global ids and classes stay isolated from the host page.

Types

JoyDomProps

type JoyDomProps = JoyDomRenderOptions & {
  spec: Spec;
  /** Ref to the host element that holds the shadow root. */
  ref?: Ref<HTMLDivElement>;
};

JoyDomRenderOptions

The options <JoyDom> accepts alongside spec:

type JoyDomRenderOptions = {
  components?: Record<string, JoyDomComponent>;
  actions?: Record<string, ActionHandler>;
  missingAction?: "ignore" | "throw";
  responsive?: "media" | "container";
};

JoyDomComponent<N>

A custom component:

type JoyDomComponent<N extends Node = Node> = ComponentType<JoyDomComponentProps<N>>;

JoyDomComponentProps<N>

What custom components receive — RenderedNodeProps plus the rendered children and the original node:

type JoyDomComponentProps<N extends Node = Node> = RenderedNodeProps & {
  children?: ReactNode;
  node: N;
};
PropWhat's in it
childrenRendered child nodes and primitive values.
nodeThe raw Joy DOM node. Read it for anything the renderer doesn't surface directly.
idResolved node id (from props.id).
classNameThe document's class list for the node, joined into a string.
styleResolved inline style. Built-in nodes only — undefined for custom types.
altimg-only. The resolved alt attribute.
srcimg-only. The resolved src attribute.

For a custom node, only children, id, className, and node carry values; style, alt, src, and the on* handlers stay unset. Style a custom node from the cascade via className instead.

RenderedNodeProps

The bag of props the renderer passes to every node (text, image, block, or custom):

type RenderedNodeProps = {
  alt?: string;
  id?: string;
  className?: string;
  src?: string;
  style?: CSSProperties;
  onClick?: (event: SyntheticEvent) => void;
  onFocus?: (event: SyntheticEvent) => void;
  onBlur?: (event: SyntheticEvent) => void;
  onChange?: (event: SyntheticEvent) => void;
};

The on* handlers are wired only on built-in nodes whose props carry a matching action binding.

ActionHandler and ActionPayload

Registered in actions, keyed by the binding's action name:

type ActionHandler = (payload: ActionPayload) => void;

type ActionPayload = {
  event: SyntheticEvent;
  params?: Record<string, unknown>;
};

params is the binding's params object, verbatim.

Error behavior

  • A document fails SpecSchema validation at the boundary you control. @joy-dom/react does not call SpecSchema.parse itself, so validate before passing.
  • A document references a custom node with no entry in components. The renderer throws. This is intentional. Silent fallback hides the real bug.
  • A built-in event binding names an action absent from actions. The renderer throws unless you pass missingAction="ignore".
  • A malformed padding, margin, or borderRadius shape is dropped silently. Validate upstream with SpecSchema to catch it.

Why doesn't the renderer validate?

The renderer trusts its input. Validation is a step you choose to run at the boundary (network, file load). Running it on every render would be wasteful. See Tutorial › Publishing for the recommended pattern.

Where next

  • Tutorial, build a document from scratch, one chapter at a time.
  • Specification, the document format this renderer consumes.

On this page