Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Content blocks

Blocks inside a content layer (or nested scroll).

"blocks": [
  { "type": "heading", "text": "Audio" },
  { "bind": "bgm", "label": "Music", "label_key": "screen.settings.bgm_volume", "min": 0, "max": 1, "step": 0.05 },
  { "bind": "locale", "label": "Language", "label_key": "screen.settings.language", "style": "locale_button", "active_style": "locale_button_active" },
  { "type": "separator" },
  {
    "type": "table",
    "columns": [30, 70],
    "rows": [
      [
        { "type": "text", "text": "Go" },
        { "type": "button_row", "buttons": [{ "label": "A", "interaction": { "hooks": { "on_click": "close" } } }] }
      ]
    ]
  }
]

Usually you need

Type / shapeRole
heading / textCopy
bindPreference row — Widget bindings
slider / toggleFree controls with hooks (not prefs)
button / button_rowActions
tableMulti-row percent columns
historyBacklog log
save_slotsManual save/load slot grid
separatorRule — separator

Common fields

KeyTypeEffect
typestringBlock kind (required unless bind is set)
bindstringPreference id — no type when set
idstringLocale merge / identity
stylestring packElement pack sugar
sourcestringPack compose
show_ifexpressionVisibility
interactionobjectHooks
state_visualobjectPer-state look

Types

bind (preference)

KeyTypeEffect
bindstringKnown preference id (master, locale, …)
label / label_keystringWhen set → settings row (label | control); omit → full-width control. Labels accept BBCode ([b], [color=…], …)
format / min / max / step / suffix—Slider display (when kind is slider)
style / active_stylepack idsLocale chips

Do not set type on bind blocks; only listed keys are allowed.

KeyTypeEffect
text / text_keystringCopy. text blocks accept BBCode; heading is plain

separator / spacer

Theme separator supplies colour/height for separator. spacer is empty space (optional size fields via style/layout).

image

KeyTypeEffect
image path / texture fields—Displayed image
alignstringleft | center | right

button

KeyTypeEffect
label / label_keystringCaption
icon fieldspathGlyphs
interaction.hooksobjectTypically on_click

button_row

KeyTypeEffect
buttonsarrayExplicit row buttons (required)
stylepack idDefault button pack
align_hstringleft | center | right (default center)

slider / toggle (free UI)

KeyTypeEffect
label / label_keystringWhen set → settings-style row; omit → full width. Labels accept BBCode
interaction.hooksobjectRequire on_change and/or on_commit
min / max / step / format fields—Slider only

Only listed keys are allowed — use bind for preferences.

table

KeyTypeDefaultEffect
columnsnumber[2..6]—Percent weights; must sum to 100
rowsarray of cell arrays—Each row length = columns.length
align_hstring or arrayleftCell default; array = per column
align_vstringcentertop | center | bottom
spacing / row_gapint—Gaps

Cells are normal blocks (text, bind unlabeled, free controls, …). No nested table or scroll. Bind/slider/toggle inside cells must omit label/label_key (put copy in an adjacent cell). Empty {} or null = spacer. Cell blocks may override align_h / align_v.

history

KeyTypeEffect
max_itemsintCap
show_speaker / speaker_on_own_line / reverse_orderboolLayout
empty_text / empty_text_keystringEmpty state
colours / sizes / item_separator—Look

No interaction.hooks / state_visual on history.

save_slots

Early — not final UX. The slot grid works; layout, labels, and comfort (filters, previews, per-story views) are not polished yet.

Slot grid for opt-in save / load screens. Clicks emit save_slot:N or load_slot:N.

KeyTypeDefaultEffect
mode"save" | "load""save"Save writes a slot; load opens occupied compatible slots
columnsint3Buttons per row (1–6)
stylestring"menu_button"Button theme prefix
empty_label / empty_label_keystringSlot {n} — EmptyEmpty cell; {n} = slot number (literal token, not a story flag)
occupied_label / occupied_label_keystringSlot {n} — {node}Occupied; {n}, {node}, and (multi-story) {story} / {story_title}
spacing / row_gapint10Gaps

Slot count comes from session.save_slots (see Save and session). Empty load cells are disabled. No built-in save / load screens ship — build them yourself with this block, then point menus at screen:save / screen:load (immediate "save" / "load" stay slot 1).

scroll

KeyTypeEffect
blocksarrayNested blocks (no nested scroll)
height or height_percentnumberWindow height
min_height / max_height / separationnumberClamps / gap

Widget bindings · Actions and hooks · Named button packs · Theme: card · settings_layout.