Skip to content

Sizing custom widgets

You may have noticed that every custom widget chapter sets flex: templateData.size on the widget’s host element. That single line is what lets your widget participate in the Flex layout’s sizing system — without it, a custom widget inside a flex container won’t honour size: 1, size: 2, etc.

This page explains the why, and clarifies when you don’t need it.

GolemUI ships two layout widgets that arrange children differently:

  • Flex — children share space along a main axis using CSS flex. Each child’s size becomes its flex value.
  • Grid — children land in named grid cells using CSS Grid. Sizing is decided by the grid template, not by the child.

Built-in widgets read templateData.size automatically; the framework adapters apply it to the rendered element. Custom widgets opt in explicitly — the engine sets size on templateData, but only your render code can apply it to the DOM.

When the parent is gui.layouts.flex(...), the rendered <form-flex> element is a CSS flex container. Every direct child is a flex item, so any custom widget you drop in there needs a CSS flex value that matches what the form definition asked for. That’s exactly what templateData.size carries — the engine resolves the widget’s size prop (defaulting to 1) and exposes it through templateData.

So in every chapter you’ll see one of these:

<div className="my-widget" style={{ flex: templateData.size }}>
{/* widget body */}
</div>

That single line is what lets a consumer write:

gui.layouts.flex([
gui.inputs.custom('productRating', 'rating', { size: 1 }),
gui.actions.custom('productShare', { size: 2, onClick: 'shareEvent' }),
]);
{
"kind": "layout",
"type": "flex",
"children": [
{
"kind": "input",
"type": "productRating",
"path": "rating",
"props": { "size": 1 }
},
{
"kind": "action",
"type": "productShare",
"props": { "size": 2 },
"on": { "click": "shareEvent" }
}
]
}

…and have the rating widget take 1 part of the row while the share widget takes 2.

When the parent is gui.layouts.grid(...), sizing flips. The grid widget itself owns the column template — each child lands in a cell that’s been pre-sized by the grid, so the child shouldn’t try to grow into the row.

You can leave flex: templateData.size in your widget code; it just has no visual effect inside a grid because the parent isn’t a flex container. There’s no harm and no need for branching — write the line once and your widget works in both layouts.

The only widgets that genuinely don’t need to read size are ones that are never rendered as a flex item — for example, a widget that always lives at the form root and stretches to 100% width. In practice that’s rare, and reading templateData.size costs nothing. When in doubt, include it.