Skip to Content
React WidgetPlayground

Ahead of the release

npm install @evanion/react-widget gives you 0.3.0. These pages document main, which has changes that release does not.

Playground

A page the shop would ship

The counter’s view of Baize below is one Widgets region: a figures row and two boards, composed from the seven items printed under it. Every block is a component somebody wrote once, and the items decide which blocks the page has, what sits inside what and how wide each one is.

Move an item with the controls in the gutter and the page is composed again. Moving counter above week carries two boards and three figures as one block, which a nested item list expresses and a flat items.map cannot; moving tables past reprints swaps the wide side, because meta.span belongs to the item and travels with it.

BaizeWeek 38
38Games in+6
31Sold+2
2.4 dTurnaround−0.3

Tonight at the tables

TableGamePartyState
OneBrass: BirminghamHanna Lind, +3Playing
TwoSpirit IslandOtto Ruane, +2Playing
ThreeRootSigrid Vall, +3Teaching
FourCrokinoleEmil Norrby, +1Booked, 20:00

Reprints on order

TitleDue
Wingspan, OceaniaTuesday
Hive PocketThursday
Azul, Summer PavilionNext week

itemsMove one and the page is composed again

[  { "id": "week", "type": "columns", "props": {}, "children": [    { "id": "intake", "type": "metric", "props": { "figure": "38", "label": "Games in", "delta": "+6" } },    { "id": "sold", "type": "metric", "props": { "figure": "31", "label": "Sold", "delta": "+2" } },    { "id": "turnaround", "type": "metric", "props": { "figure": "2.4 d", "label": "Turnaround", "delta": "−0.3" } }  ] },  { "id": "counter", "type": "columns", "props": {}, "children": [    { "id": "tables", "type": "tables", "props": { "title": "Tonight at the tables" }, "meta": { "span": 2 } },    { "id": "reprints", "type": "reprints", "props": { "title": "Reprints on order" } }  ] }]

The same demonstration opens the front page. What is on screen is the published renderer over the items printed beside it — nothing here is a picture of a page.

Your own items

The editors below run the published @evanion/react-widget build.

Try these examples

What a snippet can use

Each snippet is evaluated by react-live in noInline mode against a fixed scope. There is no module resolution inside one, so an import line, or a name that is not in the scope, surfaces as a runtime error in the preview pane rather than as a build failure.

Available: createWidgets, React, useState, useEffect, useMemo, useCallback, and render — which every snippet has to end in.

const { Widgets } = createWidgets({ components: { text: Text } }); render(<Widgets items={[{ id: 't', type: 'text', props: { body: 'hi' } }]} />);

Things that behave differently here

Everything runs in the browser. The package is importable from a React Server Component, but nothing in a playground is one, so async widgets and the streaming behaviour described under Suspense cannot be demonstrated here — chrome.suspenseFallback still works, but only for a widget that suspends on the client.

Type errors do not show. The snippets are strings; nothing typechecks them, so an unknown type, mismatched props and children on a component that does not take them all run here without complaint. What the editor does show is the rendered output, the chrome composing around it, and the console warning when an item names a type the map does not have.

Try changing

  • A type to something not in the components map. The item disappears and the browser console carries one warning naming its id.
  • A props key. Nothing validates it at runtime — the widget just receives undefined — which is the gap the type checker closes outside this editor.
  • The chrome.wrapper, to see how the region container composes.
  • An item’s position in the array. id is the React key, so reordering moves the element rather than rebuilding it.
Last updated on