This page collects small, composable patterns built from Atomica primitives and Companion helpers.
A component can be a self-contained widget that owns its HTML, CSS, and JS and mounts into a single DOM node.
import { bindInput, h, mount, signal } from 'atomica';
const MyWidget = () => {
const count = signal(0);
return h(
'button',
{
onClick: () => count.set((c) => c + 1),
style: () => ({
font: '600 14px/1.2 system-ui',
padding: '0.5rem 0.75rem',
opacity: count.get() > 3 ? 0.6 : 1
})
},
() => `Clicks: ${count.get()}`
);
};
const target = document.getElementById('my-widget');
if (target) mount(h(MyWidget, {}), target);
bindInput reduces boilerplate for text inputs by returning value and onInput props:
import { bindInput, h, signal } from 'atomica';
const name = signal('');
const View = () =>
h('input', {
placeholder: 'Name',
...bindInput(name)
});
bindProp is the generic helper for wiring signals to DOM properties:
import { bindProp, h, signal } from 'atomica';
const name = signal('');
const done = signal(false);
h('input', { type: 'text', ...bindProp(name, 'value') });
h('input', { type: 'checkbox', ...bindProp(done, 'checked') });
When you have multiple inputs bound to a single model, build the payload at click time and send it through the service. The response can update a shared signal:
import { createService, h, signal } from 'atomica';
type User = { name: string; email: string };
const name = signal('');
const email = signal('');
const user = signal<User | null>(null);
const api = createService({ baseUrl: '/api' });
const createUser = () => {
const payload: User = { name: name.get(), email: email.get() };
const { resource, channel } = api.post<User>('/users', payload, false);
channel.subscribe((created) => {
user.set(created);
});
resource.refresh();
};
const View = () =>
h('div', null,
h('input', {
placeholder: 'Name',
value: () => name.get(),
onInput: (e: Event) => name.set((e.target as HTMLInputElement).value)
}),
h('input', {
placeholder: 'Email',
value: () => email.get(),
onInput: (e: Event) => email.set((e.target as HTMLInputElement).value)
}),
h('button', { onClick: createUser }, 'Create User'),
() => (user.get() ? `Created: ${user.get()!.name}` : 'No user yet')
);