Skip to content

Creating a layout widget

A layout widget is a container. It receives a children array from the form definition and is responsible for rendering them. The example we’ll walk through is productCard — a card container with a title header that wraps its children inside a styled card.

import { gui } from '@golemui/gui-shared';
gui.layouts.custom(
'productCard',
[
// child widgets go here
],
{ title: 'Product Card Name' },
);
{
"kind": "layout",
"type": "productCard",
"props": { "title": "Product Card Name" },
"children": [
/* child widgets go here */
]
}

Pick your framework — each tab walks through the key concepts and the full implementation side by side.

Key concepts (React)

  • useLayoutWidget returns the widget’s resolved children, already filtered by include/exclude, plus a merged templateData (your custom props + engine-managed values like size, lang, deps).
  • Render each child by handing it to <WidgetRenderer /> — that’s the React entry point that resolves a widget instance to its registered component.
  • The style={{ flex: templateData.size }} line lets the layout participate in flex parents — see Sizing custom widgets for the rationale.
ProductCard.tsx
import type { LayoutWidget, NonFunctionWidget, WithWidget } from '@golemui/core';
import { useLayoutWidget, WidgetRenderer } from '@golemui/react';
interface ProductCardProps {
title: string;
}
export function ProductCard(widgetInstance: WithWidget) {
const widget = widgetInstance.widget as LayoutWidget;
const { uid, children, templateData } =
useLayoutWidget<ProductCardProps>(widget);
return (
<div className="product-card" style={{ flex: templateData.size }}>
<div className="product-card__widget" id={uid}>
<h2 className="product-card__title">{templateData.title}</h2>
<div className="product-card__content">
{children.map((child) => {
const w = child as NonFunctionWidget<string>;
return <WidgetRenderer key={w.uid} widget={w} />;
})}
</div>
</div>
</div>
);
}

Here’s the Product Card layout rendering its child widgets: