Property schema
A property is a control a streamer configures when they add your widget — a colour, a number, a font, a toggle. You define your widget's properties on the Properties surface, and Streamerly generates the configuration form from them automatically. There's nothing to wire up: define a property, and it appears in the panel beside the widget.
Each property you read in two places:
- In code as
props.<name>(or theuseProp('<name>')hook in a template). - In CSS as a variable,
var(--<name>).
Defining a property
On the Properties surface, click Add property and fill in:
| Field | Meaning |
|---|---|
| Key | The stable identifier (e.g. accent-colour). Everything else derives from it. Don't rename it after release — it's how saved configurations are matched. |
| Type | The kind of control (see below). |
| Label | What the streamer sees above the control. |
| Description | Optional helper text under the control. |
| Default value | The value used until the streamer changes it. |
| Group | Optional section heading to organise a long form. |
| Required | Mark the field as required. |
Field types
| Type | Control | Notable options |
|---|---|---|
text | Text box | multiline, placeholder, maxLength |
number | Number input | min, max, step, suffix (e.g. px), slider to render as a slider |
range | Slider | min, max, step (required), suffix |
boolean | Switch | display: 'checkbox' for a checkbox instead |
select | Dropdown | selectOptions (the choices); display: 'segmented' for inline buttons |
color | Colour picker | alpha for transparency; swatches for suggested colours |
swatch | Preset colour picker | swatches — the locked set the streamer picks from |
extended-color | Rich fill editor | A solid colour, gradient or image fill. Normally an object — read it off props, not CSS — but it arrives as a bare CSS string (#f00, linear-gradient(...)) when the streamer binds the field to live data, so handle both. |
image | Asset picker | Picks an image from the streamer's library. |
audio | Asset picker | Picks a sound from the streamer's library. |
font | Font picker | Picks one of the platform fonts. |
direction | Angle dial | Degrees 0–360. |
channel-point-redeem | Channel-point reward picker | The streamer picks one of their own Twitch rewards; the value is the reward's Twitch id. |
power-up | Power-up picker | The streamer picks one of their Twitch Power-Ups; the value is its id. |
twitch-category | Twitch category search | The value is a { id, name } object. |
The channel-point-redeem, power-up and twitch-category pickers pair naturally with bindings. Add a channel-point-redeem property and match its value against the rewardId on a Channel Points event to fire only for that reward.
Reading a property in code
A property's key becomes a camelCase name on the props object. So accent-colour → props.accentColour:
import { onLoad, props } from '@widget';
onLoad(() => {
console.log(props.accentColour); // the configured value, or the default
});
Inside a template, use the useProp hook so the template re-renders when the streamer changes the value:
import { useProp } from '@widget';
export default function Main() {
const colour = useProp('accentColour');
return <div style={{ color: colour }}>Hello</div>;
}
Reading a property in CSS
The same key becomes a kebab-case CSS variable. So accent-colour → var(--accent-colour):
.title {
color: var(--accent-colour);
}
This is the easiest way to wire a colour or size straight into your styles — no code needed.
The two names are derived from the key automatically (accent-colour → props.accentColour and var(--accent-colour)). If you need a different name, set an explicit JS name or CSS variable on the property to override the derived one.
Show a field only when it's relevant
A property can declare a visibility condition so its control only appears when another property has a certain value. Write a small boolean expression that references sibling properties by their JS name:
showLogo === true && logoOpacity > 50
The logo-opacity control then only shows when Show logo is on and opacity is above 50. If the expression can't be evaluated, the field is shown anyway — a bad condition never hides a control by mistake. Hidden fields still resolve to their value in code and CSS; this only affects the form.
Next
- Event bindings — make the widget react to the stream.
- The @widget runtime — the full code API.