Skip to content

UI hint vocabulary

JSON Schema is fine for validation but says nothing about presentation. mobrule defines a small vocabulary of x-mobrule-* keys that let Pack authors steer the auto-generated UI without writing UI code. The validator ignores the whole x-mobrule-* namespace, so hints never affect whether a value is accepted — only how it is asked for.

KeyTypeEffect
x-mobrule-viewer-overridebooleanSurface this property as a viewer-controlled input.
x-mobrule-widgetstringForce a specific widget (see Available widgets below).
x-mobrule-optionsarrayChoice list: [{ "value": …, "label": "…", "color": "…"? }, …].
x-mobrule-unitstringUnit suffix rendered inside number, text, and slider widgets (e.g. "s").
x-mobrule-toggle-labelstringFirst line of a toggle widget’s label.
x-mobrule-toggle-substringSecond, smaller line under a toggle widget’s label.
x-mobrule-visible-whenobject{ "field": "...", "equals": … } — show this field only while another field equals a value. A hidden field is also excluded from required-validation.

Standard JSON Schema keywords are honoured alongside the hints: description renders as help text, minimum / maximum bound and clamp numeric widgets, and maxLength gives text widgets a live character counter plus validation.

The UI must degrade gracefully when an unknown hint appears — Pack authors are free to ship forward-compatible hints.

x-mobrule-widget accepts one of the following values. Each demo below is interactive and renders exactly as the platform UI does.

WidgetValue typeRequires
chipsany option valuex-mobrule-options
segmentedany option valuex-mobrule-options
dropdownany option valuex-mobrule-options
comboboxany option valuex-mobrule-options
multiselectarray of valuesx-mobrule-options
checkboxboolean
toggleboolean
numbernumber / integer
steppernumber / integer
slidernumber / integerminimum and maximum
textstring

One pill button per option; single-select, click again to deselect. An option color shows as a swatch on the chip.

pack.toml
[events.example.params_schema.properties.mood]
type = "string"
"x-mobrule-widget" = "chips"
"x-mobrule-options" = [
{ value = "chaos", label = "Chaos", color = "#e8748a" },
{ value = "calm", label = "Calm", color = "#74d2e0" },
{ value = "gold", label = "Gold", color = "#e8b76a" },
{ value = "plain", label = "Plain" },
]

A joined segmented-button row; single-select, click again to deselect. Best for short ordered scales.

pack.toml
[events.example.params_schema.properties.intensity]
type = "string"
"x-mobrule-widget" = "segmented"
"x-mobrule-options" = [
{ value = "low", label = "Low" },
{ value = "medium", label = "Medium" },
{ value = "high", label = "High" },
]

A picker popover; click the field to open, pick one option.

Select…
pack.toml
[events.example.params_schema.properties.starter]
type = "string"
"x-mobrule-widget" = "dropdown"
"x-mobrule-options" = [
{ value = "bulbasaur", label = "Bulbasaur" },
{ value = "charmander", label = "Charmander" },
{ value = "squirtle", label = "Squirtle" },
{ value = "pikachu", label = "Pikachu" },
{ value = "eevee", label = "Eevee" },
{ value = "snorlax", label = "Snorlax" },
{ value = "gengar", label = "Gengar" },
{ value = "dragonite", label = "Dragonite" },
]

The same picker, searchable — opens on focus and filters as you type. Use for long option lists.

pack.toml
[events.example.params_schema.properties.starter]
type = "string"
"x-mobrule-widget" = "combobox"
"x-mobrule-options" = [
{ value = "bulbasaur", label = "Bulbasaur" },
{ value = "charmander", label = "Charmander" },
{ value = "squirtle", label = "Squirtle" },
{ value = "pikachu", label = "Pikachu" },
{ value = "eevee", label = "Eevee" },
{ value = "snorlax", label = "Snorlax" },
{ value = "gengar", label = "Gengar" },
{ value = "dragonite", label = "Dragonite" },
]

Chips that accumulate into an array; toggling every chip off yields unset.

pack.toml
[events.example.params_schema.properties.modifiers]
"x-mobrule-widget" = "multiselect"
"x-mobrule-options" = [
{ value = "chaos", label = "Chaos", color = "#e8748a" },
{ value = "calm", label = "Calm", color = "#74d2e0" },
{ value = "gold", label = "Gold", color = "#e8b76a" },
{ value = "plain", label = "Plain" },
]

A plain checkbox for booleans.

pack.toml
[events.example.params_schema.properties.announce]
type = "boolean"
"x-mobrule-widget" = "checkbox"

A switch with a two-line label from x-mobrule-toggle-label / x-mobrule-toggle-sub; without a label it reads “Enabled” / “Disabled”.

Friendly fire
Effects can hit the streamer's allies too.
pack.toml
[events.example.params_schema.properties.friendly_fire]
type = "boolean"
"x-mobrule-widget" = "toggle"
"x-mobrule-toggle-label" = "Friendly fire"
"x-mobrule-toggle-sub" = "Effects can hit the streamer's allies too."

A numeric input; clamped to minimum / maximum, with an optional x-mobrule-unit suffix.

ms
pack.toml
[events.example.params_schema.properties.delay]
type = "integer"
minimum = 0
maximum = 500
"x-mobrule-widget" = "number"
"x-mobrule-unit" = "ms"

A −/+ stepper around a numeric input; steps by 1, clamps to minimum / maximum, and disables the button at the bound.

pack.toml
[events.example.params_schema.properties.count]
type = "integer"
minimum = 1
maximum = 10
"x-mobrule-widget" = "stepper"

A range slider with a live readout (plus x-mobrule-unit) and min/max tick labels. Requires both minimum and maximum.

30s
5 120
pack.toml
[events.example.params_schema.properties.duration]
type = "integer"
minimum = 5
maximum = 120
"x-mobrule-widget" = "slider"
"x-mobrule-unit" = "s"

A text input; maxLength adds a live counter, x-mobrule-unit a suffix. This is also the fallback for unknown schemas.

7/40
pack.toml
[events.example.params_schema.properties.message]
type = "string"
maxLength = 40
"x-mobrule-widget" = "text"
"x-mobrule-viewer-override" = true

A property without x-mobrule-widget (or with an unrecognised value) is inferred from its schema:

  • "type": "boolean"checkbox
  • has x-mobrule-optionschips for up to 6 options, dropdown beyond
  • "type": "number" or "integer"number
  • everything else (including nested / $ref / anyOf schemas) → text

A duration slider and a mode picker that reveals a dependent field:

{
"type": "object",
"required": ["mode"],
"properties": {
"duration": {
"type": "integer",
"minimum": 5,
"maximum": 120,
"x-mobrule-widget": "slider",
"x-mobrule-unit": "s"
},
"mode": {
"type": "string",
"x-mobrule-widget": "segmented",
"x-mobrule-options": [
{ "value": "chaos", "label": "Chaos", "color": "#e0564b" },
{ "value": "calm", "label": "Calm" }
]
},
"chaos_level": {
"type": "integer",
"x-mobrule-widget": "stepper",
"minimum": 1,
"maximum": 10,
"x-mobrule-visible-when": { "field": "mode", "equals": "chaos" }
}
}
}
  • Manifest reference — where hints live in the schema tree.
  • Events — most viewer-facing hints attach to Event params.