Files
sigpro/docs/api/jsx.md
natxocc bef6c20231
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 3s
Include Fragment for JSX
2026-04-30 11:19:37 +02:00

3.8 KiB
Raw Blame History

Hyperscript & Tag Helpers & JSX Style

SigPro provides two complementary ways to create DOM elements:

  1. The h function the lowlevel DOM builder.
  2. Global Tag Helpers (e.g., div(), button(), span()) a convenient DSL built on top of h.

Both are reactive, autocleanup, and support SVG, events, twoway binding, and dynamic children.


JSX with SigPro

SigPro works seamlessly with JSX. You can use JSX as a compiletime syntax sugar for h calls.

Configuration

TypeScript

// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment"
  }
}

Vite

// vite.config.js
import { defineConfig } from 'vite'

export default defineConfig({
  esbuild: {
    jsxFactory: 'h',
    jsxFragmentFactory: 'Fragment'
  }
})

Babel

// babel.config.js
export default {
  plugins: [
    ['@babel/plugin-transform-react-jsx', {
      pragma: 'h',
      pragmaFrag: 'Fragment'
    }]
  ]
}

Note: You need to import h and Fragment from SigPro in every JSX file, or make them global.

JSX Example

// App.jsx
import { $, h, Fragment, mount } from 'sigpro';

const Button = ({ onClick, children }) => (
  <button class="btn btn-primary" onclick={onClick}>
    {children}
  </button>
);

const App = () => {
  const count = $(0);

  return (
    <div class="container p-8">
      <h1 class="text-2xl font-bold">SigPro with JSX</h1>
      
      <Button onClick={() => count(count() + 1)}>
        Clicks: {() => count()}
      </Button>

      <Fragment>
        <p>Multiple elements</p>
        <p>Without extra wrapper</p>
      </Fragment>
    </div>
  );
};

mount(App, '#app');

What Gets Compiled

Your JSX:

<div class="container">
  <Button>Click</Button>
</div>

Compiles to:

h('div', { class: "container" },
  h(Button, {}, "Click")
)

Without a Build Step (CDN + Tag Helpers)

If you dont want to configure a JSX compiler, you can use the global tag helpers directly. They are available after loading SigPro via CDN.

<!DOCTYPE html>
<html>
<head>
  <script type="module">
    import 'https://cdn.jsdelivr.net/npm/sigpro@1.2.18/+esm';
    // Now $, $$, watch, h, mount, div, button, etc. are global

    const count = $(0);
    const App = () =>
      div({ class: 'container' }, [
        h1(() => `Count: ${count()}`),
        button({ onClick: () => count(count() + 1) }, 'Increment')
      ]);

    mount(App, '#app');
  </script>
</head>
<body>
  <div id="app"></div>
</body>
</html>

Template Literals Alternative (htm)

For a JSXlike syntax without a build step, you can combine SigPro with htm.

import { $, h, mount } from 'https://cdn.jsdelivr.net/npm/sigpro@1.2.18/+esm';
import htm from 'https://esm.sh/htm';

const html = htm.bind(h); // bind to SigPro's h function

const App = () => {
  const count = $(0);
  
  return html`
    <div class="container">
      <h1>SigPro Demo</h1>
      <button onclick=${() => count(count() + 1)}>
        Clicks: ${() => count()}
      </button>
    </div>
  `;
};

mount(App, '#app');

Summary Comparison

Method Build Step Syntax Recommended for
h function Optional h('div', ...) Dynamic tag names, lowlevel control
Tag Helpers Optional div(...) Most cases clean, simple, no build step
JSX Required <div>...</div> Large projects, teams familiar with React syntax
htm Optional html`<div>...</div>` Buildless but HTMLlike syntax

Tip: All approaches are fully reactive, support twoway binding, events, SVG, and automatic cleanup. Choose the one that fits your workflow.