Quick Start

Learn the basics of Wompo by creating real components with props, events, state, and dynamic rendering.


First component

A Wompo component is a function that returns the result of the template function html. After declaring the component's function, register it with defineWompo, so that it will be usable inside your HTML file.

import { defineWompo, html } from 'wompo';

function GreetingCard() {
  return html`<p>Hello, World!</p>`;
}

defineWompo(GreetingCard);

The function name becomes a kebab-case HTML tag.

<greeting-card></greeting-card>

You can also choose an explicit name.

defineWompo(GreetingCard, { name: 'app-greeting' });

Templates with `html`

html is a template tag. It lets you combine markup and JavaScript values without building strings manually.

function UserCard({ user }) {
  return html`
    <article>
      <strong>${user.name}</strong>
      <span>${user.role}</span>
    </article>
  `;
}

When you render one Wompo component inside another template, use the dynamic component syntax.

function App() {
  const user = { name: 'Ada', role: 'Admin' };

  return html`
    <main>
      <${UserCard} user=${user} />
    </main>
  `;
}

Props

Props arrive as the first function parameter. When a component is used from plain HTML, attributes are strings. When it is used inside a Wompo template, props can be objects, arrays, functions, or any other JavaScript value.

function ProductPrice({ amount, currency = 'EUR' }) {
  const price = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency,
  }).format(amount);

  return html`<strong>${price}</strong>`;
}
function ProductRow() {
  return html`<${ProductPrice} amount=${24.9} currency="EUR" />`;
}

Events

Attach events with the @ prefix. The value must be a function.

function SaveButton({ onSave }) {
  return html` <button type="button" @click=${onSave}>Save</button> `;
}

The same system works on native elements and custom elements because Wompo works with the real DOM.


State

useState makes a component reactive. When you call the setter, Wompo renders the component again and updates the UI.

import { defineWompo, html, useState } from 'wompo';

function Counter() {
  const [count, setCount] = useState(0);

  return html` <button @click=${() => setCount(count + 1)}>Count: ${count}</button> `;
}

defineWompo(Counter);


Lists

Render lists by mapping data to html templates. Keep the main markup shape stable.

function TodoList({ todos }) {
  const items = todos.map(
    (todo) => html`
      <li>
        <input type="checkbox" checked=${todo.done} />
        <span>${todo.title}</span>
      </li>
    `,
  );

  return html`
    <ul>
      ${items}
    </ul>
  `;
}

Conditions

Use normal JavaScript conditions, but avoid changing the whole component structure when a shared wrapper is enough.

function SessionStatus({ user }) {
  const label = user ? `Hello ${user.name}` : 'Sign in';

  return html` <p>${label}</p> `;
}

Avoid alternating unrelated roots when you can preserve a common structure.

// Less predictable.
function Status({ logged }) {
  if (logged) return html`<p>Logged in</p>`;
  return html`<section>Guest</section>`;
}

// More stable.
function Status({ logged }) {
  return html`<p>${logged ? 'Logged in' : 'Guest'}</p>`;
}

Next step

Once components, props, events, and state are clear, continue with:

  • Installation to choose your setup;
  • Styling to learn CSS modules and Shadow DOM;
  • Complex example for a small complete app.

Hooks must always be called in the same order. Do not put them inside if, loops, or nested callbacks.