Repository navigation
toggle
Standalone collapsible panels with animated slide in/out, expand mode for automatic window resizing, and persistence.
local wu = GetMod("WindowUtils")
local split = wu.Splitter
-- Left toolbar that collapses
local isOpen = split.toggle("tools", {
{ content = drawToolbar },
{ content = drawCanvas },
}, { side = "left", size = 180 })
-- Bottom status bar
split.toggle("status", {
{ content = drawStatusBar },
{ content = drawMainArea },
}, { side = "bottom", size = 30, defaultOpen = true })Standalone collapsible panel with animated slide in/out. panels[1] is the fixed/toggleable panel, panels[2] is the flex panel that fills remaining space.
| Parameter | Type | Default | Description | Read |
|---|---|---|---|---|
| id | string | - | Unique toggle ID | - |
| panels | table | - | Two-element array: [1] = fixed, [2] = flex. Both entries are required |
every frame |
| opts.side | string | "left" |
"left", "right", "top", or "bottom"
|
every frame |
| opts.size | number|string | 200 | Expanded size (pixels or percentage) | every frame |
| opts.edgeFlush | boolean | false | Bar sits flush against window edge when collapsed (right/bottom only) | every frame |
| opts.toggleOnClick | boolean | false | Expand mode only: single click toggles instead of double click | every frame |
| opts.elementId | string|nil | nil | Tutorial elementId for the toggle bar | every frame |
| opts.expand | boolean | false | Enable expand mode (auto window resize) | every frame |
| opts.sizeMode | string | "fixed" |
"fixed", "flex", or "auto" (expand only) |
every frame |
| opts.defaultOpen | boolean | true | Initial open state | first call |
| opts.speed | number | 6.0 | Animation speed multiplier | first call |
| opts.animate | boolean | true | Enable open/close animation | first call |
| opts.barWidth | number | ItemSpacing.x | Toggle bar thickness | first call |
| opts.barBg | table|nil | transparent | Idle bar background {r,g,b,a}
|
first call |
| opts.windowName | string|nil | nil | ImGui window name. Required when expand = true, and required by explicit persist
|
first call |
| opts.normalConstraintPct | number|nil | nil | Normal max-size constraint as display % (expand only) | first call |
| opts.persist | string|boolean|nil | nil | Explicit persistence mode: "auto" (restore on load), "manual" (save but don't auto-restore), true (same as "auto"), or nil/false (use automatic layout cache). Requires windowName. |
first call |
The Read column above is not cosmetic. Fields marked "first call" are copied into the toggle's state the first time that id is seen and are silently ignored on every later frame, even though you keep passing them. That covers defaultOpen, speed, animate, barWidth, barBg, windowName, persist, and normalConstraintPct.
Fields marked "every frame" are re-read on each call, so side, size, sizeMode, expand, edgeFlush, toggleOnClick, and elementId can all change at runtime.
Use setToggleAnimate(id, enabled) to change animation after creation, and splitter.destroy(id) if you need the first-call fields to be picked up again.
windowNameis required withexpand = true. Expand mode indexes its panels by window name; passingexpand = truewithoutwindowNamelogsexpand.init: '<id>' requires opts.windowNameand returns early, so the panel is never registered and expand mode silently does nothing. There is no fallback.
opts.expandDuration and opts.expandEasing used to configure a separate constraint animation. They are still forwarded internally but nothing reads them, so setting them does nothing. The smooth transition comes from getExpandSizePx following the toggle's own animation instead.
Automatic persistence: When no
persistoption is set and the consumer mod callsUpdate(windowName), toggle state automatically persists across sessions via the layout cache. No extra code needed. The explicitpersist/windowNamesystem takes priority when present. SettingpersistwithoutwindowNamedisables both paths, so nothing is stored or restored.
Returns: boolean - current open state
Alias: split.t(...)
| Field | Type | Description |
|---|---|---|
| content | function | Renders the panel. panels[1].content is skipped while the panel is narrower than the bar |
| minWidth | number|string|function|nil | On panels[2] only: minimum flex size used by getMinSize. Defaults to one icon button plus padding |
| minHeight | number|string|function|nil | Same, for "top"/"bottom" sides |
- Normal mode (no
expand): single click on the bar toggles. - Expand mode: double click toggles, drag resizes. Set
toggleOnClick = truefor single-click toggling with drag still available.
-- Left toolbar that collapses
local isOpen = split.toggle("tools", {
{ content = drawToolbar },
{ content = drawCanvas },
}, { side = "left", size = 180 })
-- Bottom status bar
split.toggle("status", {
{ content = drawStatusBar },
{ content = drawMainArea },
}, { side = "bottom", size = 30, defaultOpen = true })
-- Expand mode: window resizes when panel opens/closes
split.toggle("sidebar", {
{ content = drawSidebar },
{ content = drawMain },
}, {
side = "right",
size = 250,
expand = true,
windowName = "MyWindow",
sizeMode = "fixed",
normalConstraintPct = 25,
})Expand mode enables automatic window resizing. See expand for full documentation of the three size modes, constraint sizing, and position anchoring.
Programmatically set toggle open/closed state. Silently does nothing if the toggle has not rendered at least once, since there is no state to write to yet.
| Parameter | Type | Description |
|---|---|---|
| id | string | Toggle identifier |
| open | boolean | Desired open state |
Persistence differs from a user click. A click on the bar writes to both the explicit window cache (when
persist+windowNameare set) and the automatic layout cache.setToggleonly writes to the explicit window cache. If you rely on automatic persistence, a state set programmatically is not saved and the previous cached value is restored next session.
Query current toggle state. If the toggle has not rendered yet, falls back to the value stored in the automatic layout cache for that id, so it is safe to call before the first frame.
Returns: boolean|nil - open state, or nil if the id is unknown to both the live state and the cache
Enable or disable toggle animation at runtime. No-op if the toggle has not rendered yet.
Query whether animation is enabled.
Returns: boolean|nil - true or false for a known id, nil only when the toggle has not rendered yet.
Get the cached minimum size (in pixels) for a splitter's primary direction. Returns the minimum content-region size needed so all panels fit at their minimums. Use this value (plus window padding) for SetConstraints.
Works with both multi() and toggle() splitters.
Returns: number|nil - minimum pixels, or nil if splitter hasn't rendered yet
Query a panel's last saved open state from the window cache. Works with any persist mode ("auto" or "manual"). Returns the state that was saved when the game last closed, regardless of current state.
| Parameter | Type | Description |
|---|---|---|
| windowName | string | The window name |
| panelId | string | The panel/toggle identifier |
Returns: two values, boolean|nil saved open state and number|nil saved flex drag size. Both are nil when nothing is cached for that window and panel.
local wasOpen, dragSize = split.getSavedToggle("MyMod", "sidebar")Careful when passing this straight into another call: the second return value comes along for the ride, so wrap it in parentheses ((split.getSavedToggle(...))) if the callee takes more arguments.
Get the base max constraint percentage for an expand-mode toggle. Returns normalConstraintPct as configured. Use with getExpandSizePx to compute pixel constraints. Returns nil if the toggle hasn't rendered yet, isn't in expand mode, or was created without normalConstraintPct. Dragging does not affect it.
Returns: number|nil - base constraint percentage
Get the current panel size contribution in pixels for constraint adjustment. Returns the grid-aligned panel size when open and settled, the live panel size while animating or dragging, or 0 when closed. Use this to adjust both min and max constraints when an expand panel is present.
| Parameter | Type | Description |
|---|---|---|
| id | string | Toggle identifier (same id passed to splitter.toggle with expand = true) |
Returns: number - pixels to add to min/max constraints. Always a number, never nil.
Returns 0 when the toggle exists but is not in expand mode. Before the toggle has rendered even once there is no state to read, so the value comes from the window cache instead, and only if you called registerToggle(id, windowName) first. Without that registration it returns 0 on frame 1, which shows up as a one-frame constraint pop.
Map a toggle id to its window so getExpandSizePx can fall back to the cached window size on the first frame, before the toggle has rendered. Call it once during init or before Begin(). Idempotent, and it stores nothing else: it does not create toggle state or configure expand mode.
| Parameter | Type | Description |
|---|---|---|
| id | string | Toggle identifier |
| windowName | string | Window name the toggle lives on |
split.registerToggle("sidebar", "MyMod")Remove all internal state for a splitter ID. Call when dynamically created splitters are no longer needed to prevent unbounded state growth. Cleans up two-panel, multi-panel, and toggle state (including derived edge-toggle keys).
| Parameter | Type | Description |
|---|---|---|
| id | string | Splitter identifier to clean up |
split.toggle("toolbar", {
{ content = drawToolbar },
{ content = function()
-- Main content with bottom status bar
split.toggle("status", {
{ content = drawStatusBar },
{ content = drawMainContent },
}, { side = "bottom", size = 28 })
end },
}, { side = "left", size = 200 })local wu = GetMod("WindowUtils")
local split = wu.Splitter
local expand = wu.Expand
local basePct = split.getExpandConstraint("sidebar")
local panelPx = split.getExpandSizePx("sidebar")
if basePct then
local dw, dh = GetDisplayResolution()
local maxW = dw * basePct / 100 + panelPx
wu.SetConstraints(200, 200, maxW, dh * 0.8, "MyMod")
end
if ImGui.Begin("MyMod") then
split.toggle("sidebar", {
{ content = drawSidebar },
{ content = drawMain },
}, {
side = "right",
size = 280,
expand = true,
windowName = "MyMod",
sizeMode = "fixed",
normalConstraintPct = 25,
})
expand.applyWindowSize("MyMod")
end
ImGui.End()