Contents

Widget chrome

This is this widget's live chrome. Composer and Preview read these draft color-scheme and selection fields. Publish to send them with the published (and dev.) embed. A new widget starts as a snapshot of the project catalog; edits here stay on this widget.

The host owns color-scheme. The widget still looks light

The published-key wrapper is display: contents. It does not generate a box. Host body or :root can set color-scheme: dark, a custom selection color, and scrollbar styles — and native inputs inside the widget still paint light. A utility class on one inner node does not cover the whole embed. Selection stays the browser default.

A class definition can nest &::selection if someone puts that class on every root box. Authors will not. Fonts already solved “apply to the widget” with one flag. Widget chrome is that same slot for color-scheme, selection, caret, and scrollbars.

Themes change token values under a dark host. Chrome tells the browser how native controls should look. They are separate settings.

When to use it / when not to

You wantWithout widget chromeWith this catalog
A dark widget on a light host (or the reverse) so form controls match the embedNative inputs stay the host scheme. Selection is the browser default.RuleCMS sets color-scheme on the widget root. Inputs paint dark (or light) with the widget.
A host that already sets color-scheme on a wrapper around the embedWorks today. Do not double-set it.Turn published inclusion off. Composer and Preview still use the catalog.
Color scheme is the important field. Selection, scrollbar, and caret are brand polish on the same page so you do not grow a fifth catalog later.
One chrome entry on this widget — not “only fields this widget uses.” Same choice as fonts and CSS variables.

This widget's catalog

Open the widget, then CSS Settings, then Widget chrome. This catalog belongs to this widget.

To change the template for the next widget you create, edit the project catalog.

  • Preview dumps the catalog as emitted CSS on .rulecms-render-surface > * — not a :root listing.
  • Edit is one card: color scheme, selection colors, caret, and scrollbar fields. Pick dark or type var(--brand-accent) — not a pasted stylesheet. Invalid values are refused. Catalog Save is explicit.

A typical emit looks like this:

[data-rulecms-published-key="env---w"] > * {
  color-scheme: dark;
  caret-color: var(--brand-accent);
  scrollbar-width: thin;
  scrollbar-color: var(--brand-accent) transparent;
}
[data-rulecms-published-key="env---w"] > * ::selection {
  background: var(--brand-accent);
  color: #fff;
}

Color values reuse the CSS variable sanitizer: no url(, @, braces, or ;. Color scheme is light, dark, or light dark. Scrollbar width is auto, thin, or none. An empty card is no entry.

What the renderer does with the catalog

Composer and Preview read this widget's draft catalog. The published embed and the Development (dev.) draft GET read the published widget's catalog. Publish is how a draft catalog goes live.

A new widget starts as a copy of the project catalog. After that, edits here do not write back to the project, and later project edits do not come back here.

SurfaceWhat happens
Composer canvas and PreviewAlways inject from this widget's draft catalog when it is non-empty. The published-inclusion flag is ignored here so authors still see the result while they work.
Published widget (React SDK and HTML custom element)The widget fetch includes this widget's catalog when inclusion is on. Nested collections inherit. You do not get a copy per collection.

When the widget catalog is applied, chrome lands on .rulecms-render-surface > * in composer and on [data-rulecms-published-key] > * on the embed, plus that subtree's ::selection. RuleCMS never styles :root, html, or body.

Published widgets

On this widget's Widget chrome page, the Published widgets accordion holds two radios. These radios control whether this widget's published and dev. embed carry the definitions. Composer and Preview still use this widget's catalog when inclusion is off. Changing a radio saves immediately. Catalog Save is separate.

  • Include this widget chrome when published widgets are rendered. A non-empty catalog is sent with the widget and the renderer applies it. This is the default.
  • My apps already set color-scheme and selection styles. Do not include them again when the widget is being rendered. Published widgets still carry token names that need those colors, but RuleCMS does not ship the chrome rules. Your host stylesheet must set them.
Composer and Preview still use this widget's catalog when inclusion is off. Only the published (and Development-draft) embed on your site stops carrying the extra rules.
If you turn inclusion off, the host must set color-scheme on a wrapper around the embed. A missing scheme on the live page leaves native inputs on the host default.

How a published widget receives the catalog

Hosts already fetch the widget once. RuleCMS hangs the catalog on that same response as a sibling of the widget, its collections, CSS variables, class definitions, fonts, keyframes, themes, and typed properties — not folded into itemList. The field is widgetChrome.

{
  "success": true,
  "data": {
    "widget": { "publishedKey": "…", "itemList": "…", "…": "…" },
    "childCollections": { },
    "widgetChrome": {
      "colorScheme": "dark",
      "selectionBackground": "var(--brand-accent)",
      "selectionColor": "#fff",
      "caretColor": "var(--brand-accent)",
      "scrollbarColor": "var(--brand-accent) transparent",
      "scrollbarWidth": "thin"
    }
  }
}

widgetChrome is omitted when the catalog is empty, when inclusion is off, or if the catalog cannot be read. When inclusion is off, the same response also sends includeWidgetChrome: false so renderers that still receive an object must not emit it. Missing on the payload means include (legacy clients). The widget still loads.

The React renderer (@rulecms/widget-react) and the HTML custom element turn a non-empty catalog into one <style> on the widget root, for example:

[data-rulecms-published-key="env---w"] > * {
  color-scheme: dark;
}
[data-rulecms-published-key="env---w"] > * ::selection {
  background: var(--brand-accent);
  color: #fff;
}

Good to know

  • This catalog belongs to this widget. Copy and promote copy these columns as-is. The project catalog is only the starting snapshot.
  • At most one chrome entry. This catalog is a single card, not a list.
  • Themes change tokens. Chrome changes native controls. A dark theme can set --background. Chrome is what makes a <select> paint dark without styling html.
  • React and the HTML embed this pass. Other framework SDKs do not emit this catalog yet.
  • Leave the catalog empty if the host already sets color-scheme around the embed. Nothing extra is sent to the published page.

Related docs