Choice packs
A choice pack is a JSON file under themes/ that skins choice buttons or supplies group/item chrome for compose (source). The pack name is the file stem: "style": "choice_button" → themes/choice_button.json.
// themes/choice_button.json — button element pack
{
"min_width": 220,
"corner_radius": 0,
"padding_left": 18,
"padding_right": 18,
"padding_top": 4,
"padding_bottom": 6,
"normal_texture": "sprites/button-normal.png",
"hover_texture": "sprites/button-hover.png",
"pressed_texture": "sprites/button-down.png",
"focus_texture": "sprites/button-hover.png",
"texture_9slice": [6, 6, 6, 6],
"font_color": "#3a2a1a",
"font_hover_color": "#6b4420",
"font_pressed_color": "#8a5a28",
"font_focus_color": "#6b4420"
}
Usually you need
| Approach | When | What you put in the file |
|---|---|---|
| Button element pack | Stacked text buttons | Textures / flat colours / fonts (table below) |
| Group compose pack | Free / sprite / overlay menus | container + item (+ optional shuffle / show_numbers) — same shapes as story choices |
| Name only | Most stories | "style": "choice_plain" in layout.choices or on the node |
How style / source resolve: Styling model. Node fields: Choices.
Two pack roles
| Role | Referenced by | Typical contents |
|---|---|---|
| Button element | layout.choices.style, node choices.style, choice_style | Flat button chrome keys (this page) |
| Group / compose | choices.source, container.source, item.source | container, item, toggles — story Choices shapes; usually omit items |
Nested source is allowed (depth capped). Locale overlays: themes/<name>_<locale>.json.
Button element pack keys
| Key | Type | Effect |
|---|---|---|
min_width | number | Minimum button width |
corner_radius | number | Rounded corners on flat faces |
border_width | number | Flat border width |
padding_left / padding_right / padding_top / padding_bottom | number | Content margins |
normal_texture / hover_texture / pressed_texture / focus_texture | texture spec or "" | Nine-slice / image faces; empty string = flat fill |
texture_9slice | [L, T, R, B] | Slice margins for textures |
normal_bg / hover_bg / pressed_bg / focus_bg | color string | Flat fills |
normal_border / hover_border / pressed_border / focus_border | color string | Flat borders |
font_color / font_hover_color / font_pressed_color / font_focus_color | color string | Caption colours |
states.<state>.padding | sides object | Per-draw-state padding override (pressed, …) |
interaction.hooks | object | Default item hooks merged under items |
icon / hover_icon / pressed_icon / focus_icon | path string | Optional glyphs (same as item style) |
icon_max_width | number | Icon width cap |
click_sfx / hover_sfx | string or null | Per-channel UI SFX for button (non-sprite) choices. Omit = sounds.button_*; "" / null = silent |
Texture specs: string path, or richer texture objects — Texture specs. Empty texture strings keep flat colour chrome (see choice_plain.json).
Same click_sfx / hover_sfx keys are allowed on item style overlays (merged with the pack). If on_hover_enter / on_confirm already includes ui_sfx, that channel’s inherited theme SFX is skipped. Sprite render_mode does not inherit button SFX — add ui_sfx hooks when you want sound.
Does not restyle screen/menu buttons (those use theme root buttons) or the dialogue panel.
Group compose pack example
// themes/choice_yes_no.json — free + sprite + overlay
{
"show_numbers": false,
"shuffle": false,
"container": {
"layout": {
"mode": "free",
"host": "overlay",
"render_mode": "sprite",
"anchor_h": "center",
"anchor_v": "center",
"width": 750,
"height": 288
},
"style": { "bg_texture": "sprites/choice_bg.png" },
"transition": { "on_show": "slide_down", "on_hide": "fade", "duration": 0.3 }
},
"item": {
"style": { "text_color": "#00000000" },
"state_visual": {
"hover": { "animation": { "property": "position_y", "to": 73, "duration": 0.08 } }
}
}
}
Node then: "choices": { "source": "choice_yes_no", "items": [ … ] } with per-item layout.x / y and style.sprite faces. Full key lists: Choices (story node).
Related
layout.choiceschoice_style- Choices · Styling model
- Examples:
examples/example-05-ui-and-polish/themes/