Skip to content

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.

RecipeLibraryHow
ChartsChart.js, EChartsWidget
Rich textTiptapWidget, toolbar as element commands
Code editorCodeMirror 6Widget, focus command
CarouselEmbla CarouselWidget, previous/next as element commands
Data tableTanStack Table v9A pure function of state in the view
Data gridAG Grid CommunityWidget, immutable row data
IconsLucideA helper that returns Sygnal SVG vnodes
Translations (i18n)i18nextt() 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/ui parts 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 form behavior.

Recipes for sygnal/ai: models through the chat driver and decision requests, no library beyond a schema validator.

RecipeModelHow
Support inboxA decision model, a chat model for the unsure ticketsA decide() resource per Collection item, escalation with structured output
Structured output into a formA chat modeloutput schema, form.CHANGE per extracted field
On-device summariesChrome’s built-in modelchromePrompt(), an excerpt where it is unavailable
  • 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 through update, events flow out through dispatch and the intent, and the model calls the library’s methods through the widget’s commands.
  • 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).

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.