Recipes
Most JavaScript UI libraries don’t need a Sygnal version. A library that builds its UI inside an element you give it becomes a JSX tag with defineWidget; a library that only computes (a table model, a translation) is called from the view or the context, as a pure function of state. Each recipe shows the code, how to test it, what it adds to the bundle, and the mistakes to avoid.
| Recipe | Library | How |
|---|---|---|
| Charts | Chart.js, ECharts | Widget |
| Rich text | Tiptap | Widget, toolbar as element commands |
| Code editor | CodeMirror 6 | Widget, focus command |
| Carousel | Embla Carousel | Widget, previous/next as element commands |
| Data table | TanStack Table v9 | A pure function of state in the view |
| Data grid | AG Grid Community | Widget, immutable row data |
| Icons | Lucide | A helper that returns Sygnal SVG vnodes |
| Translations (i18n) | i18next | t() in .context, the locale saved with persist() |
Elsewhere in the docs:
- Positioning (tooltips, popovers, menus) with Floating UI: Floating UI for older browsers. Current browsers position
sygnal/uiparts with CSS anchor positioning and need no library. - List animations with AutoAnimate and Motion: View Transitions.
- Date pickers (flatpickr): the Widgets guide’s example.
- Web components (Web Awesome, Shoelace): no wrapper needed, see Web components.
- Forms with validation (zod, valibot): the
formbehavior.
Recipes for sygnal/ai: models through the chat driver and decision requests, no library beyond a schema validator.
| Recipe | Model | How |
|---|---|---|
| Support inbox | A decision model, a chat model for the unsure tickets | A decide() resource per Collection item, escalation with structured output |
| Structured output into a form | A chat model | output schema, form.CHANGE per extracted field |
| On-device summaries | Chrome’s built-in model | chromePrompt(), an excerpt where it is unavailable |
Choosing a pattern
Section titled “Choosing a pattern”- The library owns some DOM (a canvas, an editor, a slider):
defineWidget. Sygnal renders the host element and never touches what the library builds inside it. Props flow in throughupdate, events flow out throughdispatchand the intent, and the model calls the library’s methods through the widget’scommands. - The library only computes (rows to show, a translated string, an icon’s shape): call it in the view or in
.context, and render the result with JSX. Sygnal keeps rendering the DOM, so the output is ordinary markup: it is server-rendered, tested in the mock DOM, and checked by sygnal-check. - The library is a framework component (React, Vue): see Adapters, and look for a framework-agnostic core first (most headless libraries have one).
Size numbers
Section titled “Size numbers”Each recipe gives what it adds to an app, measured with Vite (minified, gzipped), Sygnal itself not included. defineWidget adds about 1.1 KB the first time an app uses it.