Hudini Radio + RadioGroup
Single-selection form control. RadioGroup manages the 'only one selected' invariant via a factory; individual Radios are free to be positioned anywhere in the scene.
Radio + RadioGroup
Two components that work together. Radio is a single-selection form control â same contract as Checkbox (uncontrolled state, getValue(), disabled, readOnly, custom icon), but click always selects and never deselects (matches native <input type="radio">).
RadioGroup is a stateless controller â no visual, just a factory. Call group.createRadio() and place the returned Radios anywhere you want. The group enforces "only one selected" internally.
Recommended: use RadioGroup whenever you have 2+ related radios. Standalone Radio is supported but you own the "only one" logic manually.
Features
- đ¯ Layout-free grouping:
createRadio()returns a Radio you can drop anywhere â Stack, Card, scattered HUD positions - đ "Only one" invariant guaranteed by the group; no hidden global state, no scene-wide registry
- đ Custom icon per Radio (default
'circle', or use'heart','star','skull', ...) - đ¨ Group-level defaults (color, size, icon) inherited by every Radio, overridable per Radio
- ⨠Pop animation on the inner icon â scale + fade in with
Back.easeOut - đ Form-ready:
group.getValue()returns the selected string
RadioGroup props
scene- Phaser scene shared by all radios in the groupname- Form field name, passed toonChangevalue- Initially selected valuedisabled,readOnly- Apply to every radio in the groupcolor,icon,iconColor,size,borderRadius,labelColor- Defaults for every Radio created by this grouponChange-(value, name?) => void
RadioGroup methods
createRadio(params)- Factory. Same params as Radio, but the group managescheckedandonChangesetValue(v)/getValue()- Programmatic selectiondisable()/enable()/setDisabled(v)/isDisabled()setReadOnly(v)/isReadOnly()onChange(cb)- Replace the callbackdestroy()- Clear the group's registry (does not destroy the Radios themselves)
Live Example
Loading game...
Usage Example
import Phaser from 'phaser';
import {
createTheme,
HUDINI_KEY,
HudiniPlugin,
withHudini,
RadioGroup,
Stack,
} from 'hudini';
class DifficultyScene extends Phaser.Scene {
create(): void {
// 1. Create the group first â no visual.
const group = new RadioGroup({
scene: this,
name: 'difficulty',
value: 'normal',
color: 'blue-500',
onChange: (value) => {
console.log('selected:', value);
},
});
// 2. Create Radios via the factory. Place them anywhere.
const easy = group.createRadio({ x: 0, y: 0, value: 'easy', label: 'Easy' });
const normal = group.createRadio({ x: 0, y: 0, value: 'normal', label: 'Normal' });
const hard = group.createRadio({ x: 0, y: 0, value: 'hard', label: 'Hard' });
// 3. Lay them out â Stack (or wherever you want).
const layout = new Stack({
scene: this, x: 400, y: 300,
direction: 'column',
gap: 12,
children: [easy, normal, hard],
});
this.add.existing(layout);
// Read the current value later (form-style):
console.log(group.getValue()); // 'normal'
}
}