Skip to content

Sprig and Web Components ​

Sprig supports native custom elements in JavaScript render functions and .sprig templates, and can register a Sprig component as a browser custom element. This is focused interoperability, not a complete Web Components compiler or a Vue-style custom-element mode.

The demo includes an external Iconify web component on its Web Components page. It imports iconify-icon once from the app entry, then uses <iconify-icon :icon="..."> in a .sprig route. This is an example of consuming a third-party custom element; the page controls it with Sprig signals and native buttons.

Use a native custom element ​

Custom tags can be written directly in a .sprig template. Use a reactive : binding for a property, and explicit event syntax for dashed custom event names:

html
<template>
  <data-panel :record="record()" @selection-change="handleSelection($event)"></data-panel>
</template>

Dynamic values on custom tags are assigned as DOM properties, so objects are not stringified. Static values remain HTML attributes. Use the .prop suffix to force even a static value through a property (:mode.prop="'compact'"). Event listeners, including dashed names, are removed with their Sprig owner.

Expose a Sprig component ​

Register a component once, before creating its tag:

js
import { defineCustomElement, h, onCleanup } from 'sprig-framework';

defineCustomElement('sprig-greeting', ({ props }) => {
  onCleanup(() => console.log('greeting disconnected'));
  return h('button', { onClick: () => props.onGreet(props.name) }, `Hello, ${props.name}!`);
}, {
  props: ['name', 'record'],
  events: ['greet'],
  shadow: 'open',
});

props lists component properties and their reflected kebab-case attributes. Attribute values are strings; setting a property preserves its original value, including objects, and takes precedence over the reflected attribute. Boolean true reflects as an empty attribute; false and null remove it. events lists callback props to expose as bubbling, composed CustomEvents whose detail is the callback's first argument. The default shadow: 'open' renders into an open shadow root; use false to render directly into the host (or 'closed' for a closed root). Sprig's reactive root is disposed when the element disconnects.

The helper is also available as Sprig.defineCustomElement(...). Registration follows the browser's one-definition-per-name rule. Native light-DOM slot projection, attribute type conversion, and SSR/hydration are not provided by this helper; map and validate string attributes in your component when needed.