Skip to content

Properties per state

Per-state property overrides let you change a widget’s appearance or behavior when one or more states are active, without duplicating the widget definition. The two paths express overrides differently:

  • Programmatic — a states: {} block on the widget itself, mapping state name to the props that change while that state is active.
  • JSON — a suffix on the prop name, "<prop>.<stateName>": <value>. The base prop holds the default; each suffix supplies the override.

A repeater accepts up to five users. Once the array reaches that limit a limitReached state activates, swapping the add button label.

The state lives in formConfig.states; the override sits in the repeater’s states block.

import { gui } from '@golemui/gui-shared';
import { GuiForm } from '@golemui/gui-react';
const config = {
formDef: [
gui.inputs.repeater('users', {
addLabel: 'Add user',
states: {
limitReached: { addLabel: "Limit reached, you can't add more" },
},
children: [
gui.inputs.textInput('name', { label: 'Name' }),
],
}),
],
formConfig: {
states: { limitReached: '$form.users?.length === 5' },
},
};
export function MyForm() {
return <GuiForm config={config} />;
}

The state lives at the form root; the override is a "addLabel.limitReached" suffix on the repeater.

{
"states": {
"limitReached": "$form.users?.length === 5"
},
"form": [
{
"kind": "input",
"type": "repeater",
"path": "users",
"addLabel": "Add user",
"addLabel.limitReached": "Limit reached, you can't add more",
"children": [
{
"kind": "input",
"type": "textinput",
"path": "name",
"label": "Name"
}
]
}
]
}

Wire the parsed JSON into your form component the same way as any other JSON formDef:

import { GuiForm } from '@golemui/gui-react';
import formDef from './my-form.json';
export function MyForm() {
return <GuiForm config={{ formDef }} />;
}

When limitReached is active the add button label switches; when it’s inactive the default addLabel applies. You can override any prop the widget supports — labels, icons, disabled flags, even nested arrays.

Stack as many per-state overrides as you need.

gui.actions.button('save', {
label: 'Save',
disabled: false,
states: {
busy: { label: 'Saving…', disabled: true },
success: { label: 'Saved!', disabled: true },
},
});
{
"kind": "action",
"type": "button",
"uid": "save",
"label": "Save",
"disabled": false,
"label.busy": "Saving…",
"disabled.busy": true,
"label.success": "Saved!",
"disabled.success": true
}
  • Inline when — for one-off prop conditions without naming a state.
  • Composing states — combining multiple states with AND / OR semantics, including the colon-chain convention.