Skip to main content
orb-ui has three customization levels:
  1. Choose a built-in preset.
  2. Customize a built-in theme through typed tokens, CSS variables, and stable slots.
  3. Supply a custom renderer while Orb continues to own provider signals and session lifecycle.
A theme name is shorthand for its balanced preset:
Use a theme object when you want a preset or low-level control:
orb-ui resolves customization in this order:
  1. Load balanced, calm, or expressive for the selected theme.
  2. Apply appearance, geometry, and motion overrides.
  3. Render the resulting complete theme configuration.
You can therefore start with a preset and override one field without copying every internal value. All properties are optional except name. Cloud preserves its current animation when you change presets, appearance, or responsive size during an active session. These updates do not replay the connection entrance; a new session still uses the normal entrance animation. Use defineOrbTheme to keep literal types when a reusable theme lives outside JSX:

Presets

  • balanced preserves the existing theme’s intended visual behavior and is the default.
  • calm uses less visual range, slower response, and more restrained autonomous motion.
  • expressive uses more visual range, faster response, and stronger autonomous motion.
Presets are theme-specific. calm does not force every theme into one universal set of numbers; it chooses values appropriate for that theme’s geometry.

Visual response versus volume normalization

Provider calibration and theme motion solve different problems:
  • Adapter riseTimeMs and fallTimeMs produce a stable provider-independent speech envelope.
  • Theme activityRiseMs and activityFallMs control how quickly artwork follows that envelope.
  • stateTransitionMs controls blending between conversation states.
  • Autonomous speed or tempo fields control motion that continues even when volume is unchanged.
Theme timing values are the milliseconds required to move 90% toward a visual target. This makes them stable across display refresh rates. responseExponent maps the normalized envelope before animation: values below 1 lift quiet activity, 1 is linear, and values above 1 reserve more motion for loud activity. Do not change provider calibration to make one theme more dramatic. Choose a theme preset or adjust its motion and geometry instead. See volume calibration for the signal layer.

Circle parameters

appearance:
  • colors: partial state-to-hex-color map
  • listeningGlow, speakingGlow: maximum glow radius in pixels
geometry:
  • diameterRatio: artwork diameter relative to the size prop
  • listeningMinScale, listeningMaxScale: scale at silence and peak input activity
  • speakingMinScale, speakingMaxScale: scale at silence and peak output activity
motion:
  • responseExponent, activityRiseMs, activityFallMs, stateTransitionMs
  • idlePulseMs, processingPulseMs: CSS pulse durations

Bars parameters

appearance.colors is a partial state-to-hex-color map. geometry controls barWidthRatio, gapRatio, minHeightRatio, maxHeightRatio, and borderRadiusRatio, all relative to size. motion controls the shared response fields plus waveFrequency, listeningTempo, speakingTempo, and loadingTempo.

Cloud parameters

appearance exposes deepColor, upperColor, lowerColor, highlightColor, launchColor, and spinnerColor. Use six-digit hex colors; shader colors are compiled from these values. geometry controls diameterRatio, listeningMinScale, speakingMaxScale, and idleDotScale. motion provides the shared response fields plus idleSpeed, listeningBaseSpeed, listeningSpeedRange, speakingBaseSpeed, speakingSpeedRange, entranceHoldMs, entranceGrowMs, and entranceSettleMs.

Radial parameters

appearance exposes the shader palette (deepColor, cobaltColor, aquaColor, paleColor, membraneColor, and seamColor) and the three phone-control colors (idleControlColor, activeControlColor, and connectingControlColor). Use six-digit hex colors. geometry controls diameterRatio and controlRatio. motion provides the shared response fields plus idleSpeed, listeningBaseSpeed, listeningSpeedRange, speakingBaseSpeed, speakingSpeedRange, and rotationAmount. The radial control cutout still uses the typed --orb-ui-radial-control-surround root style variable because that value belongs to the surrounding page surface rather than the theme palette.

Debug parameters

The debug theme supports state colors, backgroundColor, textColor, and borderColor under appearance; borderRadius and padding under geometry; and responseExponent under motion.

Application-wide defaults

OrbThemeProvider supplies reusable theme, size, style, slots, component replacements, or a custom renderer. A local theme object for the same built-in theme deep-merges over the provider default; choosing another theme name replaces it.
The provider only supplies visual defaults. Each Orb still owns its own adapter, signal, accessibility label, disabled state, and lifecycle handlers.

Responsive sizing and CSS variables

Use --orb-ui-size when layout should respond to its container or viewport. Orb measures the rendered root and keeps canvas resolution and numeric theme geometry aligned with its actual width.
Every typed built-in token has a matching stable CSS variable:
For example:
The variable section is appearance, geometry, or motion; property names are the documented camel-case token names converted to kebab case. Nested state colors use colors-{state}. Numeric variables may be unitless or include a descriptive unit such as ms; orb-ui reads their numeric value. Built-in and shader palette colors should use six-digit hex values. orbThemeCssVariable(theme, section, property, nestedProperty?) is exported when a library or design-system integration needs to generate a variable name safely.

Stable slots

className and style apply to the rendered theme root. Every root also includes data-orb-ui-theme, data-orb-ui-preset, data-orb-ui-state, and data-orb-ui-slot="root". Internal semantic pieces use stable orb-ui__* classes and data-orb-ui-slot attributes. slotProps is the typed way to attach a class, inline style, ARIA attribute, title, role, or data attribute to those pieces:
Available built-in slots: Repeated bars include data-orb-ui-index. Unsupported slots are ignored, so one provider-level slot object can be shared across themes. Stable selectors also work for contextual CSS:
Animation loops own some surface properties such as transform and color. Use the typed theme object or matching CSS variables for those semantic values; use slots for surrounding layout, filters, opacity, shadows, and other presentational details. For unrestricted artwork, use a custom renderer.

Replacing built-in control chrome

The radial theme’s phone icon and connecting indicator can be replaced without rebuilding its WebGL artwork:
Component callbacks receive state, active, connecting, disabled, and the control size. They can also be supplied once through OrbThemeProvider.

Completely custom renderers

Use renderTheme when the built-in artwork and semantic tokens are not the right abstraction. The renderer receives both directional volumes, the direction-selected activity, actual pixel size, state, and lifecycle actions.
Spread rootProps on the outer element so responsive sizing, root classes, state diagnostics, and CSS variables continue to work. Spread controlProps on the lifecycle button so generated labels, disabled behavior, keyboard activation, and adapter start/stop behavior remain intact. The full renderer contract also includes signal, inputVolume, outputVolume, isActive, interactive, disabled, start, stop, and toggle. A custom renderer controls its own DOM and artwork; Orb continues to own adapter subscription, normalized signal selection, and lifecycle semantics.
Last modified on September 7, 2026