Adding View
You have signals and behaviors. Now render them.
Rimitive View provides el() — a renderer-agnostic function for creating reactive elements. It works with any adapter (DOM, native, canvas, etc.). In this guide, we’ll use the DOM adapter.
Extending the Service
Section titled “Extending the Service”Building on the service from Creating a Behavior, add the el view module with a DOM adapter, and the Mount module to mount the view:
import { compose } from '@rimitive/core';import { SignalModule, ComputedModule, EffectModule, BatchModule } from '@rimitive/signals/extend';import { createDOMAdapter } from '@rimitive/view/adapters/dom';import { createElModule } from '@rimitive/view/el';import { MountModule } from '@rimitive/view/deps/mount';
// Create adapter-bound `el`const ElModule = createElModule(createDOMAdapter());
export const svc = compose( SignalModule, ComputedModule, EffectModule, BatchModule,
// Add the view modules ElModule, MountModule);
export const { signal, computed, effect, batch, el, mount } = svc;export type Service = typeof svc;The only additions are the view imports and modules — everything else stays the same.
Creating Elements
Section titled “Creating Elements”el() is curried: el(tag)(children).
import { el } from './service';
// Just a tagconst div = el('div')();
// With text contentconst heading = el('h1')('Hello, World');
// With childrenconst container = el('div')( el('h1')('Title'), el('p')('Some text'));Adding Props
Section titled “Adding Props”Use .props() to set attributes and event handlers:
const button = el('button').props({ className: 'primary', disabled: false, onclick: () => console.log('clicked'),})('Click me');Props are fully typed based on the adapter. With the DOM adapter, el('button') knows about disabled, onclick, type, etc. — you get autocomplete and type checking for the specific element.
Reactive Content
Section titled “Reactive Content”Pass a computed for reactive text:
import { signal, computed, el } from './service';
const count = signal(0);
const display = el('div')( computed(() => `Count: ${count()}`));
count(5); // display updates to "Count: 5"Reactive Props
Section titled “Reactive Props”Props can be reactive too:
const isDisabled = signal(false);
const button = el('button').props({ disabled: isDisabled, // reactive prop onclick: () => console.log('clicked'),})('Submit');
isDisabled(true); // button becomes disabledOr use a computed for derived props:
const count = signal(0);
const display = el('div').props({ className: computed(() => count() > 10 ? 'warning' : 'normal'),})( computed(() => `Count: ${count()}`));Components
Section titled “Components”Components are just functions that return elements:
import { el, computed } from './service';
const Greeting = (name: string) => { return el('div')( el('h2')(`Hello, ${name}!`), el('p')('Welcome to Rimitive.') );};
// Use itconst app = el('div')( Greeting('Ada'), Greeting('Grace'));Important: These functions run once. They are not reactive closures — there’s no re-rendering or reconciliation at the function level. All reactivity is encapsulated in the primitives (signal, computed, effect). The function builds the element tree once; signals and computeds handle updates from there.
With Behaviors
Section titled “With Behaviors”Combine behaviors with view for reactive components:
import { svc, el, computed } from './service';import { counter } from './behaviors/counter';
const useCounter = svc(counter);
const Counter = (initial: number) => { const { count, doubled, increment, decrement, reset } = useCounter(initial);
return el('div')( el('div')( computed(() => `Count: ${count()} (doubled: ${doubled()})`) ), el('div')( el('button').props({ onclick: decrement })('-'), el('button').props({ onclick: increment })('+'), el('button').props({ onclick: reset })('Reset') ) );};
// Use itconst app = el('div')( Counter(0), Counter(100));The behavior can handle state. The component can handle UI. You can also easily make components portable as well, just like behaviors:
import Service from './service';import { counter } from './behaviors/counter';
const Counter = (svc: Service) => { const { el, computed } = svc; const useCounter = svc(counter);
return (initial: number) => { // same as before };}It’s all just patterns of composition with functions—there’s no magic.
Mounting
Section titled “Mounting”Use mount() to attach a view to the DOM:
import { el, mount } from './service';
const App = () => el('div')( el('h1')('My App'));
const app = mount(App());document.querySelector('#app')?.appendChild(app.element!);