--- title: "Counter" description: "A small counter used to compare JSX-owned and authored-light-DOM RadiantElement host patterns." group: Examples order: 1 --- import { RadiantJsxCounter, RadiantElementCounter } from '@/components/radiant-counter'; export const config = { dependencies: { components: [RadiantJsxCounter, RadiantElementCounter], }, }; # Radiant Counter The smallest example comparing the two main `RadiantElement` host modes. ## Live Comparison ### JSX-Owned Host ### RadiantElement Host ## Live Example: JSX-Owned RadiantElement The live demo renders the custom element directly, so the server HTML comes from the `RadiantElement` host itself rather than from a wrapper component. It demonstrates: - a public `@prop(...)` for the element API - host-owned JSX through `render()` - SSR coming from the custom element host via `renderComponent(...)` / the server pipeline - event handling with `on:click` - no imperative DOM syncing step for the counter text ```tsx import { RadiantElement, customElement, prop } from '@ecopages/radiant'; export type RadiantCounterProps = { value?: number; }; @customElement('radiant-counter') export class RadiantCounter extends RadiantElement { @prop({ type: Number, reflect: true }) value = 0; private readonly decrement = () => { if (this.value > 0) { this.value -= 1; } }; private readonly increment = () => { this.value += 1; }; override render() { return ( <> {this.$.value} ); } } ``` ## The Same Behavior With Authored Light DOM `RadiantElement` does not own the view — the HTML is authored or server-rendered, and the component enhances it with behavior. ```html 5 ``` The script attaches to existing markup. `@onEvent` handles clicks. `@bindTo` copies `value` onto the authored count node. ```ts import { RadiantElement, bindTo, customElement, onEvent, prop } from '@ecopages/radiant'; @customElement('counter-element') export class CounterElement extends RadiantElement { @prop({ type: Number, reflect: true, defaultValue: 0 }) @bindTo({ ref: 'count', text: true }) declare value: number; @onEvent({ ref: 'decrement', type: 'click' }) decrement() { if (this.value > 0) { this.value -= 1; } } @onEvent({ ref: 'increment', type: 'click' }) increment() { this.value += 1; } } ``` ## See Also - See [RadiantElement](/docs/components/radiant-element) for the lower-level base class. - See [Slots](/docs/components/slots) for projected authored markup. - See [JSX SSR](/docs/ssr/jsx-ssr) for SSR and hydration. - See [Radiant Todo App](/docs/examples/todo-app) for a mixed architecture example.