AkurAI Build
Menu

Public repository / fee5b6c2cde89fa6bf8dc51068af7336b56a88b8

AkurAI-Framework / site/frontend/reactivity.html

Latest change 7003a93dcc0adf28fa6dc8af98472bbcf4f2091e - feat(frontend): signals + directives reactivity runtime by Ólafur Búi Ólafsson

{% include "header" %}
    <main class="container">
      <header class="page-head">
        <span class="eyebrow">Live demo</span>
        <h1>Reactivity</h1>
        <p class="lede">Every widget below is wired by <code>signals.js</code> — a few-KB,
        no-build, zero-dependency reactivity runtime that enhances this server-rendered
        HTML in place. Signals track what they read; directives re-render when those
        signals change. <a href="/docs/reactivity">Read how it works →</a></p>
      </header>

      <section class="split rt-grid">
        <!-- Counter: data-text + data-on:click -->
        <article class="card" data-scope data-state='{"count":0}'>
          <header class="rt-head">
            <h3>Counter</h3>
            <span class="status ok">data-text · data-on</span>
          </header>
          <p class="muted small">A signal behind <code>count</code>. The buttons mutate it;
          <code>data-text</code> re-renders the number reactively.</p>
          <div class="rt-num" id="counter-value" data-text="count">0</div>
          <div class="btn-row">
            <button class="btn btn-secondary" id="counter-dec" data-on:click="count--">−1</button>
            <button class="btn btn-primary" id="counter-inc" data-on:click="count++">+1</button>
            <button class="btn btn-ghost" id="counter-reset" data-on:click="count = 0">Reset</button>
          </div>
        </article>

        <!-- Two-way binding: data-model + data-text -->
        <article class="card" data-scope data-state='{"name":"world"}'>
          <header class="rt-head">
            <h3>Two-way binding</h3>
            <span class="status ok">data-model</span>
          </header>
          <p class="muted small">Type below. <code>data-model</code> binds the input to a
          signal, and <code>data-text</code> echoes it live — no event wiring by hand.</p>
          <form class="rt-form" autocomplete="off" data-on:submit="$event.preventDefault()">
            <input id="echo-input" type="text" placeholder="Type a name…"
                   aria-label="Your name" data-model="name" />
          </form>
          <p class="rt-echo">Hello, <strong id="echo-output" data-text="name">world</strong>!</p>
        </article>
      </section>

      <section class="split rt-grid">
        <!-- Conditional: data-show -->
        <article class="card" data-scope data-state='{"open":true}'>
          <header class="rt-head">
            <h3>Conditional</h3>
            <span class="status ok">data-show</span>
          </header>
          <p class="muted small">The checkbox is a boolean signal; <code>data-show</code>
          toggles the panel's visibility from it.</p>
          <label class="switch">
            <input type="checkbox" class="switch-input" role="switch"
                   id="toggle-input" data-model="open" checked />
            <span class="switch-text">Reveal the panel</span>
          </label>
          <div class="alert alert-info" id="secret-panel" data-show="open" style="margin-top:1rem">
            <strong>Visible.</strong> <span>This panel is shown only while the signal is true.</span>
          </div>
        </article>

        <!-- List: data-for -->
        <article class="card" data-scope data-state='{"items":["Signals","Effects","Directives"],"draft":""}'>
          <header class="rt-head">
            <h3>List rendering</h3>
            <span class="status ok">data-for</span>
          </header>
          <p class="muted small">A <code>&lt;template data-for&gt;</code> renders one row per
          array item. Adding an item replaces the array, and the list re-renders.</p>
          <form class="rt-form" autocomplete="off"
                data-on:submit="$event.preventDefault(); if (draft.trim()) { items = items.concat(draft.trim()); draft = '' }">
            <input id="list-input" type="text" placeholder="Add an item…"
                   aria-label="New item" data-model="draft" />
            <button class="btn btn-primary" type="submit" id="list-add">Add</button>
          </form>
          <ul class="rt-log" id="list-output" aria-live="polite">
            <template data-for="(item, index) in items">
              <li><span data-text="index + 1"></span>. <span data-text="item"></span></li>
            </template>
          </ul>
        </article>
      </section>

      <section class="container cta">
        <h2>Reactive UI, with zero runtime dependencies.</h2>
        <div class="btn-row center">
          <a class="btn btn-secondary" href="/docs/reactivity">Reactivity docs</a>
          <a class="btn btn-secondary" href="https://github.com/olibuijr/AkurAI-Framework">Source on GitHub</a>
        </div>
      </section>
    </main>
    <script type="module" src="/signals.js"></script>
{% include "footer" %}