Skip to Content
WidgetOrder and Nesting

Order and nesting

@evanion/widget 0.1.0 and its patch releases up to 0.1.3, the version on npm. Values on this page were produced by running the source at f9b1d93, a later commit than the 0.1.0 tag, and are not re-executed.

A renderer draws widget items in array order, and each item’s children appear inside it. This means that any edit made to the order of items in your content management system (CMS) is reflected immediately on the page—and everything nested within a widget moves with it.

The Problem: Complex, Nested Page Layouts

Modern pages aren’t just flat lists of components. They often feature nested structures: a “Featured Shelf” that contains “Game Listings,” or a “Dashboard Row” that contains “Metric Cards.”

Manually managing these relationships in code is fragile. If you want to move a whole section of the page, you have to carefully move the parent and all its children, ensuring you don’t break the nesting logic.

Solution: Hierarchical Widget Items

@evanion/widget models the page as a tree. By utilizing the children property on a widget item, you can create deeply nested layouts that are easy to move and reorganize.

Consider a staff dashboard:

import { } from '@evanion/widget'; import type { } from '@evanion/widget'; const : [] = [ { : 'week', : 'columns', : {}, : [ { : 'intake', : 'metric', : { : '38', : 'Games in', : '+6' }, }, { : 'sold', : 'metric', : { : '31', : 'Sold', : '+2' }, }, { : 'turnaround', : 'metric', : { : '2.4 d', : 'Turnaround', : '−0.3' }, }, ], }, { : 'counter', : 'columns', : {}, : [ { : 'tables', : 'tables', : { : 'Tonight at the tables' }, : { : 2 }, }, { : 'reprints', : 'reprints', : { : 'Reprints on order' }, }, ], }, ]; const = (, [ 'columns', 'metric', 'tables', 'reprints', ]); ; // -> []

In this structure:

  • The root contains two main sections: week and counter.
  • The week item acts as a container, wrapping three metric widgets.
  • The counter item wraps two board widgets: tables and reprints.

Because the children are nested inside the parent item, moving the week item to the bottom of the array moves all three metrics with it, preserving the group’s integrity.

Placement and the Item Chrome

While the widget’s props contain the data, the widget’s meta property contains placement data.

The item chrome (chrome.item) is the component that surrounds each widget. It uses the meta field to determine how the widget should be positioned (e.g., in a grid).

In the dashboard example, the tables widget has meta: { span: 2 }. The item chrome sees this and assigns the widget two grid columns. If you move the tables widget to a different position in the array, its span: 2 metadata moves with it, ensuring the layout remains consistent regardless of where the widget sits on the page.

Renderer Differences: React vs. Astro

While @evanion/react-widget and @evanion/astro-widget both use the same core widget items and follow the same order, they handle the rendering process differently:

1. Handling Children

  • @evanion/react-widget: Draws each child first and passes the resulting React elements as the children prop to the parent component.
  • @evanion/astro-widget: Passes the raw child items to the parent component. The parent is then responsible for rendering its own <Widgets /> component over those items.

2. The Item Chrome

  • React: Uses a default item chrome (a div) that ignores meta unless you provide a custom one.
  • Astro: Does not provide a default item chrome. If you pass one, it must render a <slot />, or the widget inside will not appear on the page.

Move a Widget Item and Watch the Page Follow

@evanion/react-widget draws the dashboard below from the seven items above, and draws it again after every move. The items are printed under the page, and each line that opens an item has two move controls beside it.

  • Move counter above week. The two rows swap, and each row keeps its own items, because an item’s children move with it.
  • Move the board tables past the board reprints. The wide board changes sides, because meta belongs to the item it sits on, so the width moves with tables.

The interactive example this release showed here runs against the current source, so it is on the same page under /next/ and not on this one.

Build a Custom Renderer for Layout

The dashboard on this page is powered by @evanion/react-widget. However, if you are using a framework without a published renderer, you can build your own. Your own renderer shows how to implement the logic to draw items in order and handle nesting.

Last updated on