# Table of Contents - [Iris | Iris](#iris-iris) - [Combo | Iris](#combo-iris) - [Drag | Iris](#drag-iris) - [Basic | Iris](#basic-iris) - [Internal | Iris](#internal-iris) - [Iris | Iris](#iris-iris) - [Format | Iris](#format-iris) - [Iris | Iris](#iris-iris) - [Image | Iris](#image-iris) - [Input | Iris](#input-iris) - [Plot | Iris](#plot-iris) - [Menu | Iris](#menu-iris) - [Slider | Iris](#slider-iris) - [State | Iris](#state-iris) - [Understanding Widgets | Iris](#understanding-widgets-iris) - [Tab | Iris](#tab-iris) - [Tree | Iris](#tree-iris) - [Text | Iris](#text-iris) - [Table | Iris](#table-iris) - [Window | Iris](#window-iris) - [Common Issues | Iris](#common-issues-iris) - [Showcases | Iris](#showcases-iris) - [Iris | Iris](#iris-iris) - [Getting Started | Iris](#getting-started-iris) - [Understanding the Lifecycle | Iris](#understanding-the-lifecycle-iris) - [Understanding the Configuration | Iris](#understanding-the-configuration-iris) - [Understanding State | Iris](#understanding-state-iris) - [Understanding Events | Iris](#understanding-events-iris) --- # Iris | Iris [Skip to main content](https://sirmallard.github.io/Iris#__docusaurus_skipToContent_fallback) ### Fast, portable, self-contained Iris is a standalone module, with no dependencies, designed to be as lightweight and easy on resources whilst providing a rich experience. ### Favouring simplicity and functionality Iris favours writing as little code as possible. You describe what you want and Iris organises handles everything else. ### Wide range of widgets Iris offers a wide assortment of widgets, from handling user interaction to displaying complex information, all with rich customisability. Iris is an Immediate mode GUI Library for Roblox, Based on [Dear ImGui](https://github.com/ocornut/imgui) . It solves the same problems as Dear ImGui: providing a simple and bloat-free UI system, designed for visualisation and debugging. It is fast, portable, and self-contained (no external dependencies). ![](https://sirmallard.github.io/Iris/assets/docs/demoWindow.png) What is Dear ImGui, and why is it important? -------------------------------------------- Dear ImGui is best known for allowing developers to create content-creation and visualisation and debugging UI. Using the Dear ImGui paradigm (Immediate Mode), UI design is remarkably easy and simple. Because of this, Dear ImGui has been adopted in almost every major game engine from Unity and Unreal Engine to in-house engines from Rockstar and Ubisoft (and now Roblox!). Iris favors simplicity and productivity; It is designed to simplify UI, streamlining the process for creating visualisation, debug, and data input tools. To accomplish this, Iris offers a different approach to Roblox UI than existing libraries, at the cost of certain features commonly found in more intricate UI libraries. Iris opts to supercede the Roblox UI API, instead having a streamlined Immediate-Mode library and a set of widgets which developers can use to build the UI and tools they need. Demo Place: [https://rblx.games/7245022703](https://rblx.games/7245022703) Usage ----- Iris can be installed as a [package](https://wally.run/package/sirmallard/iris) using [Wally](https://wally.run/) , as an rbxm file from the [latest GitHub release](https://github.com/SirMallard/Iris/releases/latest) or building from [source](https://github.com/SirMallard/Iris/archive/refs/heads/main.zip) . You can import the rbxm into any roblox project, and begin creating UI in any client side script. No external dependences are needed. Iris can be used under any kind of Roblox UI, including PlayerGui, CoreGui, BillboardGui, SurfaceGui, and PluginGui. Credits ------- Created originally by [Michael\_48](https://github.com/Michael-48) and now maintained by [SirMallard](https://github.com/SirMallard) . Many thanks to [JakeyWasTaken](https://github.com/JakeyWasTaken) , [OverHash](https://github.com/OverHash) and everyone else who has contributed to Iris in any way. Inspriation and design: [Omar Cornut](https://www.miracleworld.net/) , [Evaera](https://github.com/evaera) . Thanks! --- # Combo | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Combo#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Combo#properties "Direct link to Properties") -------------------------------------------------------------------------------------------------- ### `Selectable`[​](https://sirmallard.github.io/Iris/api/Combo#Selectable "Direct link to Selectable") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1601) `Combo.Selectable:` `Iris.Selectable` An object which can be selected. hasChildren = false hasState = true Arguments = { Text: string, Index: any, -- index of selectable value. NoClick: boolean? = false -- prevents the selectable from being clicked by the user. } Events = { selected: () -> boolean, unselected: () -> boolean, active: () -> boolean, clicked: () -> boolean, rightClicked: () -> boolean, doubleClicked: () -> boolean, ctrlClicked: () -> boolean, hovered: () -> boolean, } States = { index: State -- a shared state between all selectables. } ### `Combo`[​](https://sirmallard.github.io/Iris/api/Combo#Combo "Direct link to Combo") WidgetHasChildrenHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1633) `Combo.Combo:` `Iris.Combo` A dropdown menu box to make a selection from a list of values. hasChildren = true hasState = true Arguments = { Text: string, NoButton: boolean? = false, -- hide the dropdown button. NoPreview: boolean? = false -- hide the preview field. } Events = { opened: () -> boolean, closed: () -> boolean, changed: () -> boolean, clicked: () -> boolean, hovered: () -> boolean } States = { index: State, isOpened: State? } ### `ComboArray`[​](https://sirmallard.github.io/Iris/api/Combo#ComboArray "Direct link to ComboArray") WidgetHasChildrenHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1667) `Combo.ComboArray:` `Iris.Combo` A selection box to choose a value from an array. hasChildren = true hasState = true Arguments = { Text: string, NoButton: boolean? = false, -- hide the dropdown button. NoPreview: boolean? = false -- hide the preview field. } Events = { opened: () -> boolean, closed: () -> boolean, clicked: () -> boolean, hovered: () -> boolean } States = { index: State, isOpened: State? } Extra = { selectionArray: { any } -- the array to generate a combo from. } ### `ComboEnum`[​](https://sirmallard.github.io/Iris/api/Combo#ComboEnum "Direct link to ComboEnum") WidgetHasChildrenHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1716) `Combo.ComboEnum:` `Iris.Combo` A selection box to choose a value from an Enum. hasChildren = true hasState = true Arguments = { Text: string, NoButton: boolean? = false, -- hide the dropdown button. NoPreview: boolean? = false -- hide the preview field. } Events = { opened: () -> boolean, closed: () -> boolean, clicked: () -> boolean, hovered: () -> boolean } States = { index: State, isOpened: State? } Extra = { enumType: Enum -- the enum to generate a combo from. } Show raw api { "functions": \[\], "properties": \[\ {\ "name": "Selectable",\ "desc": "An object which can be selected.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string,\\n Index: any, -- index of selectable value.\\n NoClick: boolean? = false -- prevents the selectable from being clicked by the user.\\n}\\nEvents = {\\n selected: () -> boolean,\\n unselected: () -> boolean,\\n active: () -> boolean,\\n clicked: () -> boolean,\\n rightClicked: () -> boolean,\\n doubleClicked: () -> boolean,\\n ctrlClicked: () -> boolean,\\n hovered: () -> boolean,\\n}\\nStates = {\\n index: State -- a shared state between all selectables.\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Selectable",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1601,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "Combo",\ "desc": "A dropdown menu box to make a selection from a list of values.\\n\\n\`\`\`lua\\nhasChildren = true\\nhasState = true\\nArguments = {\\n Text: string,\\n NoButton: boolean? = false, -- hide the dropdown button.\\n NoPreview: boolean? = false -- hide the preview field.\\n}\\nEvents = {\\n opened: () -> boolean,\\n closed: () -> boolean,\\n changed: () -> boolean,\\n clicked: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n index: State,\\n isOpened: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Combo",\ "tags": \[\ "Widget",\ "HasChildren",\ "HasState"\ \],\ "source": {\ "line": 1633,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "ComboArray",\ "desc": "A selection box to choose a value from an array.\\n\\n\`\`\`lua\\nhasChildren = true\\nhasState = true\\nArguments = {\\n Text: string,\\n NoButton: boolean? = false, -- hide the dropdown button.\\n NoPreview: boolean? = false -- hide the preview field.\\n}\\nEvents = {\\n opened: () -> boolean,\\n closed: () -> boolean,\\n clicked: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n index: State,\\n isOpened: State?\\n}\\nExtra = {\\n selectionArray: { any } -- the array to generate a combo from.\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Combo",\ "tags": \[\ "Widget",\ "HasChildren",\ "HasState"\ \],\ "source": {\ "line": 1667,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "ComboEnum",\ "desc": "A selection box to choose a value from an Enum.\\n\\n\`\`\`lua\\nhasChildren = true\\nhasState = true\\nArguments = {\\n Text: string,\\n NoButton: boolean? = false, -- hide the dropdown button.\\n NoPreview: boolean? = false -- hide the preview field.\\n}\\nEvents = {\\n opened: () -> boolean,\\n closed: () -> boolean,\\n clicked: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n index: State,\\n isOpened: State?\\n}\\nExtra = {\\n enumType: Enum -- the enum to generate a combo from.\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Combo",\ "tags": \[\ "Widget",\ "HasChildren",\ "HasState"\ \],\ "source": {\ "line": 1716,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Combo", "desc": "Combo Widget API\\n ", "source": { "line": 1569, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Combo#properties) * [Combo](https://sirmallard.github.io/Iris/api/Combo#Combo) * [ComboArray](https://sirmallard.github.io/Iris/api/Combo#ComboArray) * [ComboEnum](https://sirmallard.github.io/Iris/api/Combo#ComboEnum) * [Selectable](https://sirmallard.github.io/Iris/api/Combo#Selectable) --- # Drag | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Drag#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Drag#properties "Direct link to Properties") ------------------------------------------------------------------------------------------------- ### `DragNum`[​](https://sirmallard.github.io/Iris/api/Drag#DragNum "Direct link to DragNum") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1132) `Drag.DragNum:` `Iris.DragNum` A field which allows the user to click and drag their cursor to enter a number. You can ctrl + click to directly input a number, like InputNum. You can hold Shift to increase speed, and Alt to decrease speed when dragging. hasChildren = false hasState = true Arguments = { Text: string? = "DragNum", Increment: number? = nil, Min: number? = nil, Max: number? = nil, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `DragVector2`[​](https://sirmallard.github.io/Iris/api/Drag#DragVector2 "Direct link to DragVector2") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1164) `Drag.DragVector2:` `Iris.DragVector2` A field which allows the user to click and drag their cursor to enter a Vector2. You can ctrl + click to directly input a Vector2, like InputVector2. You can hold Shift to increase speed, and Alt to decrease speed when dragging. hasChildren = false hasState = true Arguments = { Text: string? = "DragVector2", Increment: Vector2? = nil, Min: Vector2? = nil, Max: Vector2? = nil, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `DragVector3`[​](https://sirmallard.github.io/Iris/api/Drag#DragVector3 "Direct link to DragVector3") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1196) `Drag.DragVector3:` `Iris.DragVector3` A field which allows the user to click and drag their cursor to enter a Vector3. You can ctrl + click to directly input a Vector3, like InputVector3. You can hold Shift to increase speed, and Alt to decrease speed when dragging. hasChildren = false hasState = true Arguments = { Text: string? = "DragVector3", Increment: Vector3? = nil, Min: Vector3? = nil, Max: Vector3? = nil, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `DragUDim`[​](https://sirmallard.github.io/Iris/api/Drag#DragUDim "Direct link to DragUDim") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1228) `Drag.DragUDim:` `Iris.DragUDim` A field which allows the user to click and drag their cursor to enter a UDim. You can ctrl + click to directly input a UDim, like InputUDim. You can hold Shift to increase speed, and Alt to decrease speed when dragging. hasChildren = false hasState = true Arguments = { Text: string? = "DragUDim", Increment: UDim? = nil, Min: UDim? = nil, Max: UDim? = nil, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `DragUDim2`[​](https://sirmallard.github.io/Iris/api/Drag#DragUDim2 "Direct link to DragUDim2") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1260) `Drag.DragUDim2:` `Iris.DragUDim2` A field which allows the user to click and drag their cursor to enter a UDim2. You can ctrl + click to directly input a UDim2, like InputUDim2. You can hold Shift to increase speed, and Alt to decrease speed when dragging. hasChildren = false hasState = true Arguments = { Text: string? = "DragUDim2", Increment: UDim2? = nil, Min: UDim2? = nil, Max: UDim2? = nil, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `DragRect`[​](https://sirmallard.github.io/Iris/api/Drag#DragRect "Direct link to DragRect") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1292) `Drag.DragRect:` `Iris.DragRect` A field which allows the user to click and drag their cursor to enter a Rect. You can ctrl + click to directly input a Rect, like InputRect. You can hold Shift to increase speed, and Alt to decrease speed when dragging. hasChildren = false hasState = true Arguments = { Text: string? = "DragRect", Increment: Rect? = nil, Min: Rect? = nil, Max: Rect? = nil, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } Show raw api { "functions": \[\], "properties": \[\ {\ "name": "DragNum",\ "desc": "A field which allows the user to click and drag their cursor to enter a number.\\nYou can ctrl + click to directly input a number, like InputNum.\\nYou can hold Shift to increase speed, and Alt to decrease speed when dragging.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"DragNum\\",\\n Increment: number? = nil,\\n Min: number? = nil,\\n Max: number? = nil,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.DragNum",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1132,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "DragVector2",\ "desc": "A field which allows the user to click and drag their cursor to enter a Vector2.\\nYou can ctrl + click to directly input a Vector2, like InputVector2.\\nYou can hold Shift to increase speed, and Alt to decrease speed when dragging.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"DragVector2\\",\\n Increment: Vector2? = nil,\\n Min: Vector2? = nil,\\n Max: Vector2? = nil,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.DragVector2",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1164,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "DragVector3",\ "desc": "A field which allows the user to click and drag their cursor to enter a Vector3.\\nYou can ctrl + click to directly input a Vector3, like InputVector3.\\nYou can hold Shift to increase speed, and Alt to decrease speed when dragging.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"DragVector3\\",\\n Increment: Vector3? = nil,\\n Min: Vector3? = nil,\\n Max: Vector3? = nil,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.DragVector3",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1196,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "DragUDim",\ "desc": "A field which allows the user to click and drag their cursor to enter a UDim.\\nYou can ctrl + click to directly input a UDim, like InputUDim.\\nYou can hold Shift to increase speed, and Alt to decrease speed when dragging.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"DragUDim\\",\\n Increment: UDim? = nil,\\n Min: UDim? = nil,\\n Max: UDim? = nil,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.DragUDim",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1228,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "DragUDim2",\ "desc": "A field which allows the user to click and drag their cursor to enter a UDim2.\\nYou can ctrl + click to directly input a UDim2, like InputUDim2.\\nYou can hold Shift to increase speed, and Alt to decrease speed when dragging.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"DragUDim2\\",\\n Increment: UDim2? = nil,\\n Min: UDim2? = nil,\\n Max: UDim2? = nil,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.DragUDim2",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1260,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "DragRect",\ "desc": "A field which allows the user to click and drag their cursor to enter a Rect.\\nYou can ctrl + click to directly input a Rect, like InputRect.\\nYou can hold Shift to increase speed, and Alt to decrease speed when dragging.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"DragRect\\",\\n Increment: Rect? = nil,\\n Min: Rect? = nil,\\n Max: Rect? = nil,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.DragRect",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1292,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Drag", "desc": "Drag Widget API\\n\\nA draggable widget for each datatype. Allows direct typing input but also dragging values by clicking and holding.\\n\\nSee \[Input\] for more details on the arguments.\\n ", "source": { "line": 1101, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Drag#properties) * [DragNum](https://sirmallard.github.io/Iris/api/Drag#DragNum) * [DragRect](https://sirmallard.github.io/Iris/api/Drag#DragRect) * [DragUDim](https://sirmallard.github.io/Iris/api/Drag#DragUDim) * [DragUDim2](https://sirmallard.github.io/Iris/api/Drag#DragUDim2) * [DragVector2](https://sirmallard.github.io/Iris/api/Drag#DragVector2) * [DragVector3](https://sirmallard.github.io/Iris/api/Drag#DragVector3) --- # Basic | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Basic#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Basic#properties "Direct link to Properties") -------------------------------------------------------------------------------------------------- ### `Button`[​](https://sirmallard.github.io/Iris/api/Basic#Button "Direct link to Button") Widget [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L573) `Basic.Button:` `Iris.Button` A clickable button the size of the text with padding. Can listen to the `clicked()` event to determine if it was pressed. hasChildren = false hasState = false Arguments = { Text: string, Size: UDim2? = UDim2.fromOffset(0, 0), } Events = { clicked: () -> boolean, rightClicked: () -> boolean, doubleClicked: () -> boolean, ctrlClicked: () -> boolean, -- when the control key is down and clicked. hovered: () -> boolean } ### `SmallButton`[​](https://sirmallard.github.io/Iris/api/Basic#SmallButton "Direct link to SmallButton") Widget [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L598) `Basic.SmallButton:` `Iris.SmallButton` A smaller clickable button, the same as a [Iris.Button](https://sirmallard.github.io/Iris/api/Basic#Button) but without padding. Can listen to the `clicked()` event to determine if it was pressed. hasChildren = false hasState = false Arguments = { Text: string, Size: UDim2? = 0, } Events = { clicked: () -> boolean, rightClicked: () -> boolean, doubleClicked: () -> boolean, ctrlClicked: () -> boolean, -- when the control key is down and clicked. hovered: () -> boolean } ### `Checkbox`[​](https://sirmallard.github.io/Iris/api/Basic#Checkbox "Direct link to Checkbox") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L624) `Basic.Checkbox:` `Iris.Checkbox` A checkable box with a visual tick to represent a boolean true or false state. hasChildren = false hasState = true Arguments = { Text: string } Events = { checked: () -> boolean, -- once when checked. unchecked: () -> boolean, -- once when unchecked. hovered: () -> boolean } State = { isChecked = State? -- whether the box is checked. } ### `RadioButton`[​](https://sirmallard.github.io/Iris/api/Basic#RadioButton "Direct link to RadioButton") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L652) `Basic.RadioButton:` `Iris.RadioButton` A circular selectable button, changing the state to its index argument. Used in conjunction with multiple other RadioButtons sharing the same state to represent one value from multiple options. hasChildren = false hasState = true Arguments = { Text: string, Index: any -- the state object is set to when clicked. } Events = { selected: () -> boolean, unselected: () -> boolean, active: () -> boolean, -- if the state index equals the RadioButton's index. hovered: () -> boolean } State = { index = State? -- the state set by the index of a RadioButton. } Show raw api { "functions": \[\], "properties": \[\ {\ "name": "Button",\ "desc": "A clickable button the size of the text with padding. Can listen to the \`clicked()\` event to determine if it was pressed.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = false\\nArguments = {\\n Text: string,\\n Size: UDim2? = UDim2.fromOffset(0, 0),\\n}\\nEvents = {\\n clicked: () -> boolean,\\n rightClicked: () -> boolean,\\n doubleClicked: () -> boolean,\\n ctrlClicked: () -> boolean, -- when the control key is down and clicked.\\n hovered: () -> boolean\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Button",\ "tags": \[\ "Widget"\ \],\ "source": {\ "line": 573,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "SmallButton",\ "desc": "A smaller clickable button, the same as a \[Iris.Button\](Basic#Button) but without padding. Can listen to the \`clicked()\` event to determine if it was pressed.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = false\\nArguments = {\\n Text: string,\\n Size: UDim2? = 0,\\n}\\nEvents = {\\n clicked: () -> boolean,\\n rightClicked: () -> boolean,\\n doubleClicked: () -> boolean,\\n ctrlClicked: () -> boolean, -- when the control key is down and clicked.\\n hovered: () -> boolean\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.SmallButton",\ "tags": \[\ "Widget"\ \],\ "source": {\ "line": 598,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "Checkbox",\ "desc": "A checkable box with a visual tick to represent a boolean true or false state.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string\\n}\\nEvents = {\\n checked: () -> boolean, -- once when checked.\\n unchecked: () -> boolean, -- once when unchecked.\\n hovered: () -> boolean\\n}\\nState = {\\n isChecked = State? -- whether the box is checked.\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Checkbox",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 624,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "RadioButton",\ "desc": "A circular selectable button, changing the state to its index argument. Used in conjunction with multiple other RadioButtons sharing the same state to represent one value from multiple options.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string,\\n Index: any -- the state object is set to when clicked.\\n}\\nEvents = {\\n selected: () -> boolean,\\n unselected: () -> boolean,\\n active: () -> boolean, -- if the state index equals the RadioButton's index.\\n hovered: () -> boolean\\n}\\nState = {\\n index = State? -- the state set by the index of a RadioButton.\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.RadioButton",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 652,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Basic", "desc": "Basic Widget API\\n ", "source": { "line": 549, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Basic#properties) * [Button](https://sirmallard.github.io/Iris/api/Basic#Button) * [Checkbox](https://sirmallard.github.io/Iris/api/Basic#Checkbox) * [RadioButton](https://sirmallard.github.io/Iris/api/Basic#RadioButton) * [SmallButton](https://sirmallard.github.io/Iris/api/Basic#SmallButton) --- # Internal | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Internal#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Internal#properties "Direct link to Properties") ----------------------------------------------------------------------------------------------------- ### `_cycleCoroutine`[​](https://sirmallard.github.io/Iris/api/Internal#_cycleCoroutine "Direct link to _cycleCoroutine") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L73) `Internal._cycleCoroutine:` `thread` The thread which handles all connected functions. Each connection is within a pcall statement which prevents Iris from crashing and instead stopping at the error. Functions[​](https://sirmallard.github.io/Iris/api/Internal#functions "Direct link to Functions") -------------------------------------------------------------------------------------------------- ### `_cycle`[​](https://sirmallard.github.io/Iris/api/Internal#_cycle "Direct link to _cycle") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L209) `Internal.``_cycle``(``) →` `(``)` Called every frame to handle all of the widget management. Any previous frame data is ammended and everything updates. ### `WidgetConstructor`[​](https://sirmallard.github.io/Iris/api/Internal#WidgetConstructor "Direct link to WidgetConstructor") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L336) `Internal.``WidgetConstructor``(` `type:` `string``,`\-- name used to denote the widget class. `widgetClass:` `Types.WidgetClass`\-- table of methods for the new widget. `) →` `(``)` For each widget, a widget class is created which handles all the operations of a widget. This removes the class nature of widgets, and simplifies the available functions which can be applied to any widget. The widgets themselves are dumb tables containing all the data but no methods to handle any of the data apart from events. ### `_Insert`[​](https://sirmallard.github.io/Iris/api/Internal#_Insert "Direct link to _Insert") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L445) `Internal.``_Insert``(` `widgetType::` `string``,`\-- name of widget class. `arguments:` `{``[``string``]``:` `number``}``,`\-- arguments of the widget. `states:` `{``[``string``]``:` `States``<``any``>``}``?`\-- states of the widget. `) →` `[Widget](https://sirmallard.github.io/Iris/api/Iris#Widget) `\-- the widget. Every widget is created through \_Insert. An ID is generated based on the line of the calling code and is used to find the previous frame widget if it exists. If no widget exists, a new one is created. ### `_GenNewWidget`[​](https://sirmallard.github.io/Iris/api/Internal#_GenNewWidget "Direct link to _GenNewWidget") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L546) `Internal.``_GenNewWidget``(` `widgetType:` `string``,` `arguments:` `{``[``string``]``:` `any``}``,`\-- arguments of the widget. `states:` `{``[``string``]``:` `[State](https://sirmallard.github.io/Iris/api/State) ``<``any``>``}``?``,`\-- states of the widget. `ID:` `[ID](https://sirmallard.github.io/Iris/api/Iris#ID) `\-- id of the new widget. Determined in `Internal._Insert` `) →` `[Widget](https://sirmallard.github.io/Iris/api/Iris#Widget) `\-- the newly created widget. All widgets are created as tables with properties. The widget class contains the functions to create the UI instances and update the widget or change state. ### `_ContinueWidget`[​](https://sirmallard.github.io/Iris/api/Internal#_ContinueWidget "Direct link to _ContinueWidget") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L631) `Internal.``_ContinueWidget``(` `ID:` `[ID](https://sirmallard.github.io/Iris/api/Iris#ID) ``,`\-- id of the widget. `widgetType:` `string` `) →` `[Widget](https://sirmallard.github.io/Iris/api/Iris#Widget) `\-- the widget. Since the widget has already been created this frame, we can just add it back to the stack. There is no checking of arguments or states. Basically equivalent to the end of `Internal._Insert`. ### `_DiscardWidget`[​](https://sirmallard.github.io/Iris/api/Internal#_DiscardWidget "Direct link to _DiscardWidget") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L654) `Internal.``_DiscardWidget``(``widgetToDiscard:` `[Widget](https://sirmallard.github.io/Iris/api/Iris#Widget) ``) →` `(``)` Destroys the widget instance and updates any parent. This happens if the widget was not called in the previous frame. There is no code which needs to update any widget tables since they are already reset at the start before discarding happens. ### `_widgetState`[​](https://sirmallard.github.io/Iris/api/Internal#_widgetState "Direct link to _widgetState") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L679) `Internal.``_widgetState``(` `thisWidget:` `[Widget](https://sirmallard.github.io/Iris/api/Iris#Widget) ``,`\-- widget the state belongs to. `stateName:` `string``,` `initialValue:` `any` `) →` `[State](https://sirmallard.github.io/Iris/api/State) ``<``any``>`\-- the state for the widget. Connects the state to the widget. If no state exists then a new one is created. Called for every state in every widget if the user does not provide a state. ### `_EventCall`[​](https://sirmallard.github.io/Iris/api/Internal#_EventCall "Direct link to _EventCall") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L709) `Internal.``_EventCall``(` `thisWidget:` `[Widget](https://sirmallard.github.io/Iris/api/Iris#Widget) ``,` `evetName:` `string` `) →` `boolean`\-- the value of the event. A wrapper for any event on any widget. Automatically, Iris does not initialize events unless they are explicitly called so in the first frame, the event connections are set up. Every event is a function which returns a boolean. ### `_GetParentWidget`[​](https://sirmallard.github.io/Iris/api/Internal#_GetParentWidget "Direct link to _GetParentWidget") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L728) `Internal.``_GetParentWidget``(``) →` `[Widget](https://sirmallard.github.io/Iris/api/Iris#Widget) `\-- the parent widget Returns the parent widget of the currently active widget, based on the stack depth. ### `_getID`[​](https://sirmallard.github.io/Iris/api/Internal#_getID "Direct link to _getID") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L799) `Internal.``_getID``(` `levelsToIgnore:` `number`\-- used to skip over internal calls to `_getID`. `) →` `[ID](https://sirmallard.github.io/Iris/api/Iris#ID) ` Generates a unique ID for each widget which is based on the line that the widget is created from. This ensures that the function is heuristic and always returns the same id for the same widget. Show raw api { "functions": \[\ {\ "name": "\_cycle",\ "desc": "Called every frame to handle all of the widget management. Any previous frame data is ammended and everything updates.\\n ",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 209,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_NoOp",\ "desc": "A dummy function which does nothing. Used as a placeholder for optional methods in a widget class.\\nUsed in \`Internal.WidgetConstructor\`\\n ",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "ignore": true,\ "source": {\ "line": 322,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "WidgetConstructor",\ "desc": "For each widget, a widget class is created which handles all the operations of a widget. This removes the class nature\\nof widgets, and simplifies the available functions which can be applied to any widget. The widgets themselves are\\ndumb tables containing all the data but no methods to handle any of the data apart from events.\\n ",\ "params": \[\ {\ "name": "type",\ "desc": "name used to denote the widget class.",\ "lua\_type": "string"\ },\ {\ "name": "widgetClass",\ "desc": "table of methods for the new widget.",\ "lua\_type": "Types.WidgetClass"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 336,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_Insert",\ "desc": "Every widget is created through \_Insert. An ID is generated based on the line of the calling code and is used to\\nfind the previous frame widget if it exists. If no widget exists, a new one is created.\\n ",\ "params": \[\ {\ "name": "widgetType:",\ "desc": "name of widget class.",\ "lua\_type": "string"\ },\ {\ "name": "arguments",\ "desc": "arguments of the widget.",\ "lua\_type": "{ \[string\]: number }"\ },\ {\ "name": "states",\ "desc": "states of the widget.",\ "lua\_type": "{ \[string\]: States }?"\ }\ \],\ "returns": \[\ {\ "desc": "the widget.",\ "lua\_type": "Widget"\ }\ \],\ "function\_type": "static",\ "source": {\ "line": 445,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_GenNewWidget",\ "desc": "All widgets are created as tables with properties. The widget class contains the functions to create the UI instances and\\nupdate the widget or change state.\\n ",\ "params": \[\ {\ "name": "widgetType",\ "desc": "",\ "lua\_type": "string"\ },\ {\ "name": "arguments",\ "desc": "arguments of the widget.",\ "lua\_type": "{ \[string\]: any }"\ },\ {\ "name": "states",\ "desc": "states of the widget.",\ "lua\_type": "{ \[string\]: State }?"\ },\ {\ "name": "ID",\ "desc": "id of the new widget. Determined in \`Internal.\_Insert\`",\ "lua\_type": "ID"\ }\ \],\ "returns": \[\ {\ "desc": "the newly created widget.",\ "lua\_type": "Widget"\ }\ \],\ "function\_type": "static",\ "source": {\ "line": 546,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_ContinueWidget",\ "desc": "Since the widget has already been created this frame, we can just add it back to the stack. There is no checking of\\narguments or states.\\nBasically equivalent to the end of \`Internal.\_Insert\`.\\n ",\ "params": \[\ {\ "name": "ID",\ "desc": "id of the widget.",\ "lua\_type": "ID"\ },\ {\ "name": "widgetType",\ "desc": "",\ "lua\_type": "string"\ }\ \],\ "returns": \[\ {\ "desc": "the widget.",\ "lua\_type": "Widget"\ }\ \],\ "function\_type": "static",\ "source": {\ "line": 631,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_DiscardWidget",\ "desc": "Destroys the widget instance and updates any parent. This happens if the widget was not called in the\\nprevious frame. There is no code which needs to update any widget tables since they are already reset\\nat the start before discarding happens.\\n ",\ "params": \[\ {\ "name": "widgetToDiscard",\ "desc": "",\ "lua\_type": "Widget"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 654,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_widgetState",\ "desc": "Connects the state to the widget. If no state exists then a new one is created. Called for every state in every\\nwidget if the user does not provide a state.\\n ",\ "params": \[\ {\ "name": "thisWidget",\ "desc": "widget the state belongs to.",\ "lua\_type": "Widget"\ },\ {\ "name": "stateName",\ "desc": "",\ "lua\_type": "string"\ },\ {\ "name": "initialValue",\ "desc": "",\ "lua\_type": "any"\ }\ \],\ "returns": \[\ {\ "desc": "the state for the widget.",\ "lua\_type": "State"\ }\ \],\ "function\_type": "static",\ "source": {\ "line": 679,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_EventCall",\ "desc": "A wrapper for any event on any widget. Automatically, Iris does not initialize events unless they are explicitly\\ncalled so in the first frame, the event connections are set up. Every event is a function which returns a boolean.\\n ",\ "params": \[\ {\ "name": "thisWidget",\ "desc": "",\ "lua\_type": "Widget"\ },\ {\ "name": "evetName",\ "desc": "",\ "lua\_type": "string"\ }\ \],\ "returns": \[\ {\ "desc": "the value of the event.",\ "lua\_type": "boolean"\ }\ \],\ "function\_type": "static",\ "source": {\ "line": 709,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_GetParentWidget",\ "desc": "Returns the parent widget of the currently active widget, based on the stack depth.\\n ",\ "params": \[\],\ "returns": \[\ {\ "desc": "the parent widget",\ "lua\_type": "Widget"\ }\ \],\ "function\_type": "static",\ "source": {\ "line": 728,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_generateEmptyVDOM",\ "desc": "Creates the VDOM at the start of each frame containing just the root instance.\\n ",\ "params": \[\],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "{ \[ID\]: Widget }"\ }\ \],\ "function\_type": "static",\ "ignore": true,\ "source": {\ "line": 742,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_generateRootInstance",\ "desc": "Creates the root instance.\\n ",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "ignore": true,\ "source": {\ "line": 755,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_generateSelctionImageObject",\ "desc": "Creates the selection object for buttons.\\n ",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "ignore": true,\ "source": {\ "line": 769,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_getID",\ "desc": "Generates a unique ID for each widget which is based on the line that the widget is\\ncreated from. This ensures that the function is heuristic and always returns the same\\nid for the same widget.\\n ",\ "params": \[\ {\ "name": "levelsToIgnore",\ "desc": "used to skip over internal calls to \`\_getID\`.",\ "lua\_type": "number"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "ID"\ }\ \],\ "function\_type": "static",\ "source": {\ "line": 799,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_deepCompare",\ "desc": "Compares two tables to check if they are the same. It uses a recursive iteration through one table\\nto compare against the other. Used to determine if the arguments of a widget have changed since last\\nframe.\\n ",\ "params": \[\ {\ "name": "t1",\ "desc": "",\ "lua\_type": "{}"\ },\ {\ "name": "t2",\ "desc": "",\ "lua\_type": "{}"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "boolean"\ }\ \],\ "function\_type": "static",\ "ignore": true,\ "source": {\ "line": 846,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "\_deepCopy",\ "desc": "Performs a deep copy of a table so that neither table contains a shared reference.\\n ",\ "params": \[\ {\ "name": "t",\ "desc": "",\ "lua\_type": "{}"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "{}"\ }\ \],\ "function\_type": "static",\ "ignore": true,\ "source": {\ "line": 877,\ "path": "lib/Internal.lua"\ }\ }\ \], "properties": \[\ {\ "name": "\_cycleCoroutine",\ "desc": "The thread which handles all connected functions. Each connection is within a pcall statement which prevents\\nIris from crashing and instead stopping at the error.\\n ",\ "lua\_type": "thread",\ "source": {\ "line": 73,\ "path": "lib/Internal.lua"\ }\ }\ \], "types": \[\], "name": "Internal", "desc": "An internal class within Iris containing all the backend data and functions for Iris to operate.\\nIt is recommended that you don't generally interact with Internal unless you understand what you are doing.\\n ", "source": { "line": 9, "path": "lib/Internal.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Internal#properties) * [\_cycleCoroutine](https://sirmallard.github.io/Iris/api/Internal#_cycleCoroutine) * [Functions](https://sirmallard.github.io/Iris/api/Internal#functions) * [.\_ContinueWidget](https://sirmallard.github.io/Iris/api/Internal#_ContinueWidget) * [.\_cycle](https://sirmallard.github.io/Iris/api/Internal#_cycle) * [.\_DiscardWidget](https://sirmallard.github.io/Iris/api/Internal#_DiscardWidget) * [.\_EventCall](https://sirmallard.github.io/Iris/api/Internal#_EventCall) * [.\_GenNewWidget](https://sirmallard.github.io/Iris/api/Internal#_GenNewWidget) * [.\_getID](https://sirmallard.github.io/Iris/api/Internal#_getID) * [.\_GetParentWidget](https://sirmallard.github.io/Iris/api/Internal#_GetParentWidget) * [.\_Insert](https://sirmallard.github.io/Iris/api/Internal#_Insert) * [.\_widgetState](https://sirmallard.github.io/Iris/api/Internal#_widgetState) * [.WidgetConstructor](https://sirmallard.github.io/Iris/api/Internal#WidgetConstructor) --- # Iris | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Iris#__docusaurus_skipToContent_fallback) On this page Types[​](https://sirmallard.github.io/Iris/api/Iris#types "Direct link to Types") ---------------------------------------------------------------------------------- ### `ID`[​](https://sirmallard.github.io/Iris/api/Iris#ID "Direct link to ID") [](https://github.com/SirMallard/Iris/blob/main/lib/WidgetTypes.lua#L5) `type` `ID =` `string` ### `Widget`[​](https://sirmallard.github.io/Iris/api/Iris#Widget "Direct link to Widget") [](https://github.com/SirMallard/Iris/blob/main/lib/WidgetTypes.lua#L28) `type` `Widget =` `{` `ID:` `[ID](https://sirmallard.github.io/Iris/api/Iris#ID) ``,` `type:` `string``,` `lastCycleTick:` `number``,` `parentWidget:` `[Widget](https://sirmallard.github.io/Iris/api/Iris#Widget) ``,` `Instance:` `[GuiObject](https://developer.roblox.com/en-us/api-reference/class/GuiObject)` `,` `ZIndex:` `number``,` `arguments:` `{``[``string``]``:` `any``}` `}` Properties[​](https://sirmallard.github.io/Iris/api/Iris#properties "Direct link to Properties") ------------------------------------------------------------------------------------------------- ### `Disabled`[​](https://sirmallard.github.io/Iris/api/Iris#Disabled "Direct link to Disabled") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L34) `Iris.Disabled:` `boolean` While Iris.Disabled is true, execution of Iris and connected functions will be paused. The widgets are not destroyed, they are just frozen so no changes will happen to them. ### `Args`[​](https://sirmallard.github.io/Iris/api/Iris#Args "Direct link to Args") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L47) `Iris.Args:` `{``[``string``]``:` `{``[``string``]``:` `any``}``}` Provides a list of every possible Argument for each type of widget to it's index. For instance, `Iris.Args.Window.NoResize`. The Args table is useful for using widget Arguments without remembering their order. Iris.Window({"My Window", [Iris.Args.Window.NoResize] = true}) ### `TemplateConfig`[​](https://sirmallard.github.io/Iris/api/Iris#TemplateConfig "Direct link to TemplateConfig") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L335) `Iris.TemplateConfig:` `{``[``string``]``:` `{``[``string``]``:` `any``}``}` TemplateConfig provides a table of default styles and configurations which you may apply to your UI. Functions[​](https://sirmallard.github.io/Iris/api/Iris#functions "Direct link to Functions") ---------------------------------------------------------------------------------------------- ### `SetFocusedWindow`[​](https://sirmallard.github.io/Iris/api/Iris#SetFocusedWindow "Direct link to SetFocusedWindow") [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L91) `Iris.``SetFocusedWindow``(` `window:` `Types.Window`\-- the window to focus. `) →` `(``)` Sets the focused window to the window provided, which brings it to the front and makes it active. ### `Init`[​](https://sirmallard.github.io/Iris/api/Iris#Init "Direct link to Init") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L73) `Iris.``Init``(` `parentInstance:` `[Instance?](https://developer.roblox.com/en-us/api-reference/datatype/Instance)` `,`\-- where Iris will place widgets UIs under, defaulting to [PlayerGui](https://developer.roblox.com/en-us/api-reference/class/PlayerGui) `eventConnection:` `(``[RBXScriptSignal](https://developer.roblox.com/en-us/api-reference/datatype/RBXScriptSignal)`  `|` `(``)` `→` `(``)` `|` `false``)``?``,`\-- the event to determine an Iris cycle, defaulting to \[Heartbeat\] `allowMultipleInits:` `boolean?`\-- allows subsequent calls 'Iris.Init()' to do nothing rather than error about initialising again, defaulting to false `) →` `[Iris](https://sirmallard.github.io/Iris/api/Iris) ` Initializes Iris and begins rendering. Can only be called once. See [Iris.Shutdown](https://sirmallard.github.io/Iris/api/Iris#Shutdown) to stop Iris, or [Iris.Disabled](https://sirmallard.github.io/Iris/api/Iris#Disabled) to temporarily disable Iris. Once initialized, [Iris:Connect](https://sirmallard.github.io/Iris/api/Iris#Connect) can be used to create a widget. If the `eventConnection` is `false` then Iris will not create a cycle loop and the user will need to call [Internal.\_cycle](https://sirmallard.github.io/Iris/api/Internal#_cycle) every frame. ### `Shutdown`[​](https://sirmallard.github.io/Iris/api/Iris#Shutdown "Direct link to Shutdown") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L122) `Iris.``Shutdown``(``) →` `(``)` Shuts Iris down. This can only be called once, and Iris cannot be started once shut down. ### `Append`[​](https://sirmallard.github.io/Iris/api/Iris#Append "Direct link to Append") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L180) `Iris.``Append``(` `userInstance:` `[GuiObject](https://developer.roblox.com/en-us/api-reference/class/GuiObject)` \-- the Roblox [Instance](https://developer.roblox.com/en-us/api-reference/datatype/Instance) to insert into Iris `) →` `(``)` Inserts any Roblox [Instance](https://developer.roblox.com/en-us/api-reference/datatype/Instance) into Iris. The parent of the inserted instance can either be determined by the `_config.Parent` property or by the current parent widget from the stack. ### `End`[​](https://sirmallard.github.io/Iris/api/Iris#End "Direct link to End") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L218) `Iris.``End``(``) →` `(``)` Marks the end of any widgets which contain children. For example: -- Widgets placed here **will not** be inside the tree Iris.Text({"Above and outside the tree"}) -- A Tree widget can contain children. -- We must therefore remember to call `Iris.End()` Iris.Tree({"My First Tree"}) -- Widgets placed here **will** be inside the tree Iris.Text({"Tree item 1"}) Iris.Text({"Tree item 2"}) Iris.End() -- Widgets placed here **will not** be inside the tree Iris.Text({"Below and outside the tree"}) ##### Caution: Error Seeing the error `Callback has too few calls to Iris.End()` or `Callback has too many calls to Iris.End()`? Using the wrong amount of `Iris.End()` calls in your code will lead to an error. Each widget called which might have children should be paired with a call to `Iris.End()`, **even if the Widget doesnt currently have any children**. ### `ForceRefresh`[​](https://sirmallard.github.io/Iris/api/Iris#ForceRefresh "Direct link to ForceRefresh") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L243) `Iris.``ForceRefresh``(``) →` `(``)` Destroys and regenerates all instances used by Iris. Useful if you want to propogate state changes. ##### Caution: Performance Because this function Deletes and Initializes many instances, it may cause **performance issues** when used with many widgets. In **no** case should it be called every frame. ### `UpdateGlobalConfig`[​](https://sirmallard.github.io/Iris/api/Iris#UpdateGlobalConfig "Direct link to UpdateGlobalConfig") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L265) `Iris.``UpdateGlobalConfig``(` `deltaStyle:` `{``[``string``]``:` `any``}`\-- a table containing the changes in style ex: `{ItemWidth = UDim.new(0, 100)}` `) →` `(``)` Customizes the configuration which **every** widget will inherit from. It can be used along with [Iris.TemplateConfig](https://sirmallard.github.io/Iris/api/Iris#TemplateConfig) to easily swap styles, for example: Iris.UpdateGlobalConfig(Iris.TemplateConfig.colorLight) -- use light theme ##### Caution: Performance This function internally calls [Iris.ForceRefresh](https://sirmallard.github.io/Iris/api/Iris#ForceRefresh) so that style changes are propogated. As such, it may cause **performance issues** when used with many widgets. In **no** case should it be called every frame. ### `PushConfig`[​](https://sirmallard.github.io/Iris/api/Iris#PushConfig "Direct link to PushConfig") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L290) `Iris.``PushConfig``(` `deltaStyle:` `{``[``string``]``:` `any``}`\-- a table containing the changes in style ex: `{ItemWidth = UDim.new(0, 100)}` `) →` `(``)` Allows cascading of a style by allowing styles to be locally and hierarchically applied. Each call to Iris.PushConfig must be paired with a call to [Iris.PopConfig](https://sirmallard.github.io/Iris/api/Iris#PopConfig) , for example: Iris.Text({"boring text"}) Iris.PushConfig({TextColor = Color3.fromRGB(128, 0, 256)}) Iris.Text({"Colored Text!"}) Iris.PopConfig() Iris.Text({"boring text"}) ### `PopConfig`[​](https://sirmallard.github.io/Iris/api/Iris#PopConfig "Direct link to PopConfig") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L318) `Iris.``PopConfig``(``) →` `(``)` Ends a [Iris.PushConfig](https://sirmallard.github.io/Iris/api/Iris#PushConfig) style. Each call to [Iris.PopConfig](https://sirmallard.github.io/Iris/api/Iris#PopConfig) should match a call to [Iris.PushConfig](https://sirmallard.github.io/Iris/api/Iris#PushConfig) . ### `PushId`[​](https://sirmallard.github.io/Iris/api/Iris#PushId "Direct link to PushId") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L354) `Iris.``PushId``(` `id:` `[ID](https://sirmallard.github.io/Iris/api/Iris#ID) `\-- custom id `) →` `(``)` Pushes an id onto the id stack for all future widgets. Use [Iris.PopId](https://sirmallard.github.io/Iris/api/Iris#PopId) to pop it off the stack. ### `PopID`[​](https://sirmallard.github.io/Iris/api/Iris#PopID "Direct link to PopID") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L367) `Iris.``PopID``(``) →` `(``)` Removes the most recent pushed id from the id stack. ### `SetNextWidgetID`[​](https://sirmallard.github.io/Iris/api/Iris#SetNextWidgetID "Direct link to SetNextWidgetID") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L397) `Iris.``SetNextWidgetID``(` `id:` `[ID](https://sirmallard.github.io/Iris/api/Iris#ID) `\-- custom id. `) →` `(``)` Sets the id for the next widget. Useful for using [Iris.Append](https://sirmallard.github.io/Iris/api/Iris#Append) on the same widget. Iris.SetNextWidgetId("demo_window") Iris.Window({ "Window" }) Iris.Text({ "Text one placed here." }) Iris.End() -- later in the code Iris.SetNextWidgetId("demo_window") Iris.Window() Iris.Text({ "Text two placed here." }) Iris.End() -- both text widgets will be placed under the same window despite being called separately. ### `State`[​](https://sirmallard.github.io/Iris/api/Iris#State%3CT%3E "Direct link to State") State [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L439) `Iris.``State``(` `initialValue:` `T`\-- the initial value for the state `) →` `[State](https://sirmallard.github.io/Iris/api/State) ``<``T``>` Constructs a new [State](https://sirmallard.github.io/Iris/api/State) object. Subsequent ID calls will return the same object. ##### INFO Iris.State allows you to create "references" to the same value while inside your UI drawing loop. For example: Iris:Connect(function() local myNumber = 5 myNumber = myNumber + 1 Iris.Text({"The number is: " .. myNumber}) end) This is problematic. Each time the function is called, a new myNumber is initialized, instead of retrieving the old one. The above code will always display 6. * * * Iris.State solves this problem: Iris:Connect(function() local myNumber = Iris.State(5) myNumber:set(myNumber:get() + 1) Iris.Text({"The number is: " .. myNumber}) end) In this example, the code will work properly, and increment every frame. ### `WeakState`[​](https://sirmallard.github.io/Iris/api/Iris#WeakState%3CT%3E "Direct link to WeakState") State [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L465) `Iris.``WeakState``(` `initialValue:` `T`\-- the initial value for the state `) →` `[State](https://sirmallard.github.io/Iris/api/State) ``<``T``>` Constructs a new state object, subsequent ID calls will return the same object, except all widgets connected to the state are discarded, the state reverts to the passed initialValue ### `VariableState`[​](https://sirmallard.github.io/Iris/api/Iris#VariableState%3CT%3E "Direct link to VariableState") State [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L524) `Iris.``VariableState``(` `variable:` `T``,`\-- the variable to track `callback:` `(``T``)` `→` `(``)`\-- a function which sets the new variable locally `) →` `[State](https://sirmallard.github.io/Iris/api/State) ``<``T``>` Returns a state object linked to a local variable. The passed variable is used to check whether the state object should update. The callback method is used to change the local variable when the state changes. The existence of such a function is to make working with local variables easier. Since Iris cannot directly manipulate the memory of the variable, like in C++, it must instead rely on the user updating it through the callback provided. Additionally, because the state value is not updated when created or called we cannot return the new value back, instead we require a callback for the user to update. local myNumber = 5 local state = Iris.VariableState(myNumber, function(value) myNumber = value end) Iris.DragNum({ "My number" }, { number = state }) This is how Dear ImGui does the same in C++ where we can just provide the memory location to the variable which is then updated directly. static int myNumber = 5; ImGui::DragInt("My number", &myNumber); // Here in C++, we can directly pass the variable. ##### Caution: Update Order If the variable and state value are different when calling this, the variable value takes precedence. Therefore, if you update the state using `state.value = ...` then it will be overwritten by the variable value. You must use `state:set(...)` if you want the variable to update to the state's value. ### `TableState`[​](https://sirmallard.github.io/Iris/api/Iris#TableState%3CK,%20V%3E "Direct link to TableState") State [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L604) `Iris.``TableState``(` `table:` `{``[``K``]``:` `V``}``,`\-- the table containing the value `key:` `K``,`\-- the key to the value in table `callback:` `(``(``newValue:` `V``)` `→` `false?``)``?`\-- a function called when the state is changed `) →` `[State](https://sirmallard.github.io/Iris/api/State) ``<``V``>` Similar to Iris.VariableState but takes a table and key to modify a specific value and a callback to determine whether to update the value. The passed table and key are used to check the value. The callback is called when the state changes value and determines whether we update the table. This is useful if we want to monitor a table value which needs to call other functions when changed. Since tables are pass-by-reference, we can modify the table anywhere and it will update all other instances. Therefore, we don't need a callback by default. local data = { myNumber = 5 } local state = Iris.TableState(data, "myNumber") Iris.DragNum({ "My number" }, { number = state }) Here the `data._started` should never be updated directly, only through the `toggle` function. However, we still want to monitor the value and be able to change it. Therefore, we use the callback to toggle the function for us and prevent Iris from updating the table value by returning false. local data = { _started = false } local function toggle(enabled: boolean) data._started = enabled if data._started then start(...) else stop(...) end end local state = Iris.TableState(data, "_started", function(stateValue: boolean) toggle(stateValue) return false end) Iris.Checkbox({ "Started" }, { isChecked = state }) ##### Caution: Update Order If the table value and state value are different when calling this, the table value value takes precedence. Therefore, if you update the state using `state.value = ...` then it will be overwritten by the table value. You must use `state:set(...)` if you want the table value to update to the state's value. ### `ComputedState`[​](https://sirmallard.github.io/Iris/api/Iris#ComputedState%3CT,%20U%3E "Direct link to ComputedState") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L657) `Iris.``ComputedState``(` `firstState:` `[State](https://sirmallard.github.io/Iris/api/State) ``<``T``>``,`\-- State to bind to. `onChangeCallback:` `(``firstValue:` `T``)` `→` `U`\-- callback which should return a value transformed from the firstState value `) →` `[State](https://sirmallard.github.io/Iris/api/State) ``<``U``>` Constructs a new State object, but binds its value to the value of another State. ##### INFO A common use case for this constructor is when a boolean State needs to be inverted: Iris.ComputedState(otherState, function(newValue) return not newValue end) ### `ShowDemoWindow`[​](https://sirmallard.github.io/Iris/api/Iris#ShowDemoWindow "Direct link to ShowDemoWindow") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L691) `Iris.``ShowDemoWindow``(``) →` `(``)` ShowDemoWindow is a function which creates a Demonstration window. this window contains many useful utilities for coders, and serves as a refrence for using each part of the library. Ideally, the DemoWindow should always be available in your UI. It is the same as any other callback you would connect to Iris using [Iris.Connect](https://sirmallard.github.io/Iris/api/Iris#Connect) Iris:Connect(Iris.ShowDemoWindow) ### `Connect`[​](https://sirmallard.github.io/Iris/api/Iris#Connect "Direct link to Connect") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L159) `Iris:``Connect``(` `callback:` `(``)` `→` `(``)`\-- the callback containg the Iris code `) →` `(``)` `→` `(``)`\-- call to disconnect it Connects a function which will execute every Iris cycle. [Iris.Init](https://sirmallard.github.io/Iris/api/Iris#Init) must be called before connecting. A cycle is determined by the `eventConnection` passed to [Iris.Init](https://sirmallard.github.io/Iris/api/Iris#Init) (default to [RunService.Heartbeat](https://developer.roblox.com/en-us/api-reference/class/RunService#Heartbeat) ). Multiple callbacks can be added to Iris from many different scripts or modules. Show raw api { "functions": \[\ {\ "name": "SetFocusedWindow",\ "desc": "Sets the focused window to the window provided, which brings it to the front and makes it active.\\n ",\ "params": \[\ {\ "name": "window",\ "desc": "the window to focus.",\ "lua\_type": "Types.Window"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 91,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "Init",\ "desc": "Initializes Iris and begins rendering. Can only be called once.\\nSee \[Iris.Shutdown\] to stop Iris, or \[Iris.Disabled\] to temporarily disable Iris.\\n\\nOnce initialized, \[Iris:Connect\] can be used to create a widget.\\n\\nIf the \`eventConnection\` is \`false\` then Iris will not create a cycle loop and the user will need to call \[Internal.\_cycle\] every frame.",\ "params": \[\ {\ "name": "parentInstance",\ "desc": "where Iris will place widgets UIs under, defaulting to \[PlayerGui\]",\ "lua\_type": "Instance?"\ },\ {\ "name": "eventConnection",\ "desc": "the event to determine an Iris cycle, defaulting to \[Heartbeat\]",\ "lua\_type": "(RBXScriptSignal | () -> () | false)?"\ },\ {\ "name": "allowMultipleInits",\ "desc": "allows subsequent calls 'Iris.Init()' to do nothing rather than error about initialising again, defaulting to false",\ "lua\_type": "boolean?"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "Iris"\ }\ \],\ "function\_type": "static",\ "source": {\ "line": 73,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "Shutdown",\ "desc": "Shuts Iris down. This can only be called once, and Iris cannot be started once shut down.",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 122,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "Connect",\ "desc": "Connects a function which will execute every Iris cycle. \[Iris.Init\] must be called before connecting.\\n\\nA cycle is determined by the \`eventConnection\` passed to \[Iris.Init\] (default to \[RunService.Heartbeat\]).\\n\\nMultiple callbacks can be added to Iris from many different scripts or modules.",\ "params": \[\ {\ "name": "callback",\ "desc": "the callback containg the Iris code",\ "lua\_type": "() -> ()"\ }\ \],\ "returns": \[\ {\ "desc": "call to disconnect it",\ "lua\_type": "() -> ()"\ }\ \],\ "function\_type": "method",\ "source": {\ "line": 159,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "Append",\ "desc": "Inserts any Roblox \[Instance\] into Iris.\\n\\nThe parent of the inserted instance can either be determined by the \`\_config.Parent\`\\nproperty or by the current parent widget from the stack.",\ "params": \[\ {\ "name": "userInstance",\ "desc": "the Roblox \[Instance\] to insert into Iris",\ "lua\_type": "GuiObject"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 180,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "End",\ "desc": "Marks the end of any widgets which contain children. For example:\\n\`\`\`lua\\n-- Widgets placed here \*\*will not\*\* be inside the tree\\nIris.Text({\\"Above and outside the tree\\"})\\n\\n-- A Tree widget can contain children.\\n-- We must therefore remember to call \`Iris.End()\`\\nIris.Tree({\\"My First Tree\\"})\\n -- Widgets placed here \*\*will\*\* be inside the tree\\n Iris.Text({\\"Tree item 1\\"})\\n Iris.Text({\\"Tree item 2\\"})\\nIris.End()\\n\\n-- Widgets placed here \*\*will not\*\* be inside the tree\\nIris.Text({\\"Below and outside the tree\\"})\\n\`\`\`\\n:::caution Caution: Error\\nSeeing the error \`Callback has too few calls to Iris.End()\` or \`Callback has too many calls to Iris.End()\`?\\nUsing the wrong amount of \`Iris.End()\` calls in your code will lead to an error.\\n\\nEach widget called which might have children should be paired with a call to \`Iris.End()\`, \*\*even if the Widget doesnt currently have any children\*\*.\\n:::",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 218,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "ForceRefresh",\ "desc": "Destroys and regenerates all instances used by Iris. Useful if you want to propogate state changes.\\n:::caution Caution: Performance\\nBecause this function Deletes and Initializes many instances, it may cause \*\*performance issues\*\* when used with many widgets.\\nIn \*\*no\*\* case should it be called every frame.\\n:::",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 243,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "UpdateGlobalConfig",\ "desc": "Customizes the configuration which \*\*every\*\* widget will inherit from.\\n\\nIt can be used along with \[Iris.TemplateConfig\] to easily swap styles, for example:\\n\`\`\`lua\\nIris.UpdateGlobalConfig(Iris.TemplateConfig.colorLight) -- use light theme\\n\`\`\`\\n:::caution Caution: Performance\\nThis function internally calls \[Iris.ForceRefresh\] so that style changes are propogated.\\n\\nAs such, it may cause \*\*performance issues\*\* when used with many widgets.\\nIn \*\*no\*\* case should it be called every frame.\\n:::",\ "params": \[\ {\ "name": "deltaStyle",\ "desc": "a table containing the changes in style ex: \`{ItemWidth = UDim.new(0, 100)}\`",\ "lua\_type": "{ \[string\]: any }"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 265,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "PushConfig",\ "desc": "Allows cascading of a style by allowing styles to be locally and hierarchically applied.\\n\\nEach call to Iris.PushConfig must be paired with a call to \[Iris.PopConfig\], for example:\\n\`\`\`lua\\nIris.Text({\\"boring text\\"})\\n\\nIris.PushConfig({TextColor = Color3.fromRGB(128, 0, 256)})\\n Iris.Text({\\"Colored Text!\\"})\\nIris.PopConfig()\\n\\nIris.Text({\\"boring text\\"})\\n\`\`\`",\ "params": \[\ {\ "name": "deltaStyle",\ "desc": "a table containing the changes in style ex: \`{ItemWidth = UDim.new(0, 100)}\`",\ "lua\_type": "{ \[string\]: any }"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 290,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "PopConfig",\ "desc": "Ends a \[Iris.PushConfig\] style.\\n\\nEach call to \[Iris.PopConfig\] should match a call to \[Iris.PushConfig\].",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 318,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "PushId",\ "desc": "Pushes an id onto the id stack for all future widgets. Use \[Iris.PopId\] to pop it off the stack.",\ "params": \[\ {\ "name": "id",\ "desc": "custom id",\ "lua\_type": "ID"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 354,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "PopID",\ "desc": "Removes the most recent pushed id from the id stack.",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 367,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "SetNextWidgetID",\ "desc": "Sets the id for the next widget. Useful for using \[Iris.Append\] on the same widget.\\n\`\`\`lua\\nIris.SetNextWidgetId(\\"demo\_window\\")\\nIris.Window({ \\"Window\\" })\\n Iris.Text({ \\"Text one placed here.\\" })\\nIris.End()\\n\\n-- later in the code\\n\\nIris.SetNextWidgetId(\\"demo\_window\\")\\nIris.Window()\\n Iris.Text({ \\"Text two placed here.\\" })\\nIris.End()\\n\\n-- both text widgets will be placed under the same window despite being called separately.\\n\`\`\`",\ "params": \[\ {\ "name": "id",\ "desc": "custom id.",\ "lua\_type": "ID"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 397,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "State",\ "desc": "Constructs a new \[State\] object. Subsequent ID calls will return the same object.\\n:::info\\nIris.State allows you to create \\"references\\" to the same value while inside your UI drawing loop.\\nFor example:\\n\`\`\`lua\\nIris:Connect(function()\\n local myNumber = 5\\n myNumber = myNumber + 1\\n Iris.Text({\\"The number is: \\" .. myNumber})\\nend)\\n\`\`\`\\nThis is problematic. Each time the function is called, a new myNumber is initialized, instead of retrieving the old one.\\nThe above code will always display 6.\\n\*\*\*\\nIris.State solves this problem:\\n\`\`\`lua\\nIris:Connect(function()\\n local myNumber = Iris.State(5)\\n myNumber:set(myNumber:get() + 1)\\n Iris.Text({\\"The number is: \\" .. myNumber})\\nend)\\n\`\`\`\\nIn this example, the code will work properly, and increment every frame.\\n:::",\ "params": \[\ {\ "name": "initialValue",\ "desc": "the initial value for the state",\ "lua\_type": "T"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "State"\ }\ \],\ "function\_type": "static",\ "tags": \[\ "State"\ \],\ "source": {\ "line": 439,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "WeakState",\ "desc": "Constructs a new state object, subsequent ID calls will return the same object, except all widgets connected to the state are discarded, the state reverts to the passed initialValue",\ "params": \[\ {\ "name": "initialValue",\ "desc": "the initial value for the state",\ "lua\_type": "T"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "State"\ }\ \],\ "function\_type": "static",\ "tags": \[\ "State"\ \],\ "source": {\ "line": 465,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "VariableState",\ "desc": "Returns a state object linked to a local variable.\\n\\nThe passed variable is used to check whether the state object should update. The callback method is used to change the local variable when the state changes.\\n\\nThe existence of such a function is to make working with local variables easier.\\nSince Iris cannot directly manipulate the memory of the variable, like in C++, it must instead rely on the user updating it through the callback provided.\\nAdditionally, because the state value is not updated when created or called we cannot return the new value back, instead we require a callback for the user to update.\\n\\n\`\`\`lua\\nlocal myNumber = 5\\n\\nlocal state = Iris.VariableState(myNumber, function(value)\\n myNumber = value\\nend)\\nIris.DragNum({ \\"My number\\" }, { number = state })\\n\`\`\`\\n\\nThis is how Dear ImGui does the same in C++ where we can just provide the memory location to the variable which is then updated directly.\\n\`\`\`cpp\\nstatic int myNumber = 5;\\nImGui::DragInt(\\"My number\\", &myNumber); // Here in C++, we can directly pass the variable.\\n\`\`\`\\n\\n:::caution Caution: Update Order\\nIf the variable and state value are different when calling this, the variable value takes precedence.\\n\\nTherefore, if you update the state using \`state.value = ...\` then it will be overwritten by the variable value.\\nYou must use \`state:set(...)\` if you want the variable to update to the state's value.\\n:::",\ "params": \[\ {\ "name": "variable",\ "desc": "the variable to track",\ "lua\_type": "T"\ },\ {\ "name": "callback",\ "desc": "a function which sets the new variable locally",\ "lua\_type": "(T) -> ()"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "State"\ }\ \],\ "function\_type": "static",\ "tags": \[\ "State"\ \],\ "source": {\ "line": 524,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "TableState",\ "desc": "Similar to Iris.VariableState but takes a table and key to modify a specific value and a callback to determine whether to update the value.\\n\\nThe passed table and key are used to check the value. The callback is called when the state changes value and determines whether we update the table.\\nThis is useful if we want to monitor a table value which needs to call other functions when changed.\\n\\nSince tables are pass-by-reference, we can modify the table anywhere and it will update all other instances. Therefore, we don't need a callback by default.\\n\`\`\`lua\\nlocal data = {\\n myNumber = 5\\n}\\n\\nlocal state = Iris.TableState(data, \\"myNumber\\")\\nIris.DragNum({ \\"My number\\" }, { number = state })\\n\`\`\`\\n\\nHere the \`data.\_started\` should never be updated directly, only through the \`toggle\` function. However, we still want to monitor the value and be able to change it.\\nTherefore, we use the callback to toggle the function for us and prevent Iris from updating the table value by returning false.\\n\`\`\`lua\\nlocal data = {\\n \_started = false\\n}\\n\\nlocal function toggle(enabled: boolean)\\n data.\_started = enabled\\n if data.\_started then\\n start(...)\\n else\\n stop(...)\\n end\\nend\\n\\nlocal state = Iris.TableState(data, \\"\_started\\", function(stateValue: boolean)\\n toggle(stateValue)\\n return false\\nend)\\nIris.Checkbox({ \\"Started\\" }, { isChecked = state })\\n\`\`\`\\n\\n:::caution Caution: Update Order\\nIf the table value and state value are different when calling this, the table value value takes precedence.\\n\\nTherefore, if you update the state using \`state.value = ...\` then it will be overwritten by the table value.\\nYou must use \`state:set(...)\` if you want the table value to update to the state's value.\\n:::",\ "params": \[\ {\ "name": "table",\ "desc": "the table containing the value",\ "lua\_type": "{ \[K\]: V }"\ },\ {\ "name": "key",\ "desc": "the key to the value in table",\ "lua\_type": "K"\ },\ {\ "name": "callback",\ "desc": "a function called when the state is changed",\ "lua\_type": "((newValue: V) -> false?)?"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "State"\ }\ \],\ "function\_type": "static",\ "tags": \[\ "State"\ \],\ "source": {\ "line": 604,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "ComputedState",\ "desc": "Constructs a new State object, but binds its value to the value of another State.\\n:::info\\nA common use case for this constructor is when a boolean State needs to be inverted:\\n\`\`\`lua\\nIris.ComputedState(otherState, function(newValue)\\n return not newValue\\nend)\\n\`\`\`\\n:::",\ "params": \[\ {\ "name": "firstState",\ "desc": "State to bind to.",\ "lua\_type": "State"\ },\ {\ "name": "onChangeCallback",\ "desc": "callback which should return a value transformed from the firstState value",\ "lua\_type": "(firstValue: T) -> U"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "State"\ }\ \],\ "function\_type": "static",\ "source": {\ "line": 657,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "ShowDemoWindow",\ "desc": "ShowDemoWindow is a function which creates a Demonstration window. this window contains many useful utilities for coders,\\nand serves as a refrence for using each part of the library. Ideally, the DemoWindow should always be available in your UI.\\nIt is the same as any other callback you would connect to Iris using \[Iris.Connect\]\\n\`\`\`lua\\nIris:Connect(Iris.ShowDemoWindow)\\n\`\`\`",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 691,\ "path": "lib/init.lua"\ }\ }\ \], "properties": \[\ {\ "name": "Disabled",\ "desc": "While Iris.Disabled is true, execution of Iris and connected functions will be paused.\\nThe widgets are not destroyed, they are just frozen so no changes will happen to them.",\ "lua\_type": "boolean",\ "source": {\ "line": 34,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "Args",\ "desc": "Provides a list of every possible Argument for each type of widget to it's index.\\nFor instance, \`Iris.Args.Window.NoResize\`.\\nThe Args table is useful for using widget Arguments without remembering their order.\\n\`\`\`lua\\nIris.Window({\\"My Window\\", \[Iris.Args.Window.NoResize\] = true})\\n\`\`\`",\ "lua\_type": "{ \[string\]: { \[string\]: any } }",\ "source": {\ "line": 47,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "Events",\ "desc": "-todo: work out what this is used for.",\ "lua\_type": "table",\ "ignore": true,\ "source": {\ "line": 56,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "TemplateConfig",\ "desc": "TemplateConfig provides a table of default styles and configurations which you may apply to your UI.",\ "lua\_type": "{ \[string\]: { \[string\]: any } }",\ "source": {\ "line": 335,\ "path": "lib/init.lua"\ }\ }\ \], "types": \[\ {\ "name": "ID",\ "desc": "",\ "lua\_type": "string",\ "source": {\ "line": 5,\ "path": "lib/WidgetTypes.lua"\ }\ },\ {\ "name": "Widget",\ "desc": "",\ "lua\_type": "{ ID: ID, type: string, lastCycleTick: number, parentWidget: Widget, Instance: GuiObject, ZIndex: number, arguments: { \[string\]: any }}",\ "source": {\ "line": 28,\ "path": "lib/WidgetTypes.lua"\ }\ }\ \], "name": "Iris", "desc": "Iris; contains the all user-facing functions and properties.\\nA set of internal functions can be found in \`Iris.Internal\` (only use if you understand).\\n\\nIn its simplest form, users may start Iris by using\\n\`\`\`lua\\nIris.Init()\\n\\nIris:Connect(function()\\n Iris.Window({\\"My First Window!\\"})\\n Iris.Text({\\"Hello, World\\"})\\n Iris.Button({\\"Save\\"})\\n Iris.InputNum({\\"Input\\"})\\n Iris.End()\\nend)\\n\`\`\`", "source": { "line": 23, "path": "lib/init.lua" } } * [Types](https://sirmallard.github.io/Iris/api/Iris#types) * [ID](https://sirmallard.github.io/Iris/api/Iris#ID) * [Widget](https://sirmallard.github.io/Iris/api/Iris#Widget) * [Properties](https://sirmallard.github.io/Iris/api/Iris#properties) * [Args](https://sirmallard.github.io/Iris/api/Iris#Args) * [Disabled](https://sirmallard.github.io/Iris/api/Iris#Disabled) * [TemplateConfig](https://sirmallard.github.io/Iris/api/Iris#TemplateConfig) * [Functions](https://sirmallard.github.io/Iris/api/Iris#functions) * [:Connect](https://sirmallard.github.io/Iris/api/Iris#Connect) * [.Append](https://sirmallard.github.io/Iris/api/Iris#Append) * [.ComputedState](https://sirmallard.github.io/Iris/api/Iris#ComputedState%3CT,%20U%3E) * [.End](https://sirmallard.github.io/Iris/api/Iris#End) * [.ForceRefresh](https://sirmallard.github.io/Iris/api/Iris#ForceRefresh) * [.Init](https://sirmallard.github.io/Iris/api/Iris#Init) * [.PopConfig](https://sirmallard.github.io/Iris/api/Iris#PopConfig) * [.PopID](https://sirmallard.github.io/Iris/api/Iris#PopID) * [.PushConfig](https://sirmallard.github.io/Iris/api/Iris#PushConfig) * [.PushId](https://sirmallard.github.io/Iris/api/Iris#PushId) * [.SetFocusedWindow](https://sirmallard.github.io/Iris/api/Iris#SetFocusedWindow) * [.SetNextWidgetID](https://sirmallard.github.io/Iris/api/Iris#SetNextWidgetID) * [.ShowDemoWindow](https://sirmallard.github.io/Iris/api/Iris#ShowDemoWindow) * [.Shutdown](https://sirmallard.github.io/Iris/api/Iris#Shutdown) * [.State](https://sirmallard.github.io/Iris/api/Iris#State%3CT%3E) * [.TableState](https://sirmallard.github.io/Iris/api/Iris#TableState%3CK,%20V%3E) * [.UpdateGlobalConfig](https://sirmallard.github.io/Iris/api/Iris#UpdateGlobalConfig) * [.VariableState](https://sirmallard.github.io/Iris/api/Iris#VariableState%3CT%3E) * [.WeakState](https://sirmallard.github.io/Iris/api/Iris#WeakState%3CT%3E) --- # Format | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Format#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Format#properties "Direct link to Properties") --------------------------------------------------------------------------------------------------- ### `Separator`[​](https://sirmallard.github.io/Iris/api/Format#Separator "Direct link to Separator") Widget [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L299) `Format.Separator:` `Iris.Separator` A vertical or horizonal line, depending on the context, which visually seperates widgets. Iris.Window({"Separator Demo"}) Iris.Text({"Some text here!"}) Iris.Separator() Iris.Text({"This text has been separated!"}) Iris.End() ![Example Separator](https://sirmallard.github.io/Iris/assets/api/format/basicSeparator.png) hasChildren = false hasState = false ### `Indent`[​](https://sirmallard.github.io/Iris/api/Format#Indent "Direct link to Indent") WidgetHasChildren [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L328) `Format.Indent:` `Iris.Indent` Indents its child widgets. Iris.Window({"Indent Demo"}) Iris.Text({"Unindented text!"}) Iris.Indent() Iris.Text({"This text has been indented!"}) Iris.End() Iris.End() ![Example Indent](https://sirmallard.github.io/Iris/assets/api/format/basicIndent.png) hasChildren = true hasState = false Arguments = { Width: number? = Iris._config.IndentSpacing -- indent width ammount. } ### `SameLine`[​](https://sirmallard.github.io/Iris/api/Format#SameLine "Direct link to SameLine") WidgetHasChildren [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L361) `Format.SameLine:` `Iris.SameLine` Positions its children in a row, horizontally. Iris.Window({"Same Line Demo"}) Iris.Text({"All of these buttons are on the same line!"}) Iris.SameLine() Iris.Button({"Button 1"}) Iris.Button({"Button 2"}) Iris.Button({"Button 3"}) Iris.End() Iris.End() ![Example SameLine](https://sirmallard.github.io/Iris/assets/api/format/basicSameLine.png) hasChildren = true hasState = false Arguments = { Width: number? = Iris._config.ItemSpacing.X, -- horizontal spacing between child widgets. VerticalAlignment: Enum.VerticalAlignment? = Enum.VerticalAlignment.Center -- how widgets vertically to each other. HorizontalAlignment: Enum.HorizontalAlignment? = Enum.HorizontalAlignment.Center -- how widgets are horizontally. } ### `Group`[​](https://sirmallard.github.io/Iris/api/Format#Group "Direct link to Group") WidgetHasChildren [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L376) `Format.Group:` `Iris.Group` Layout widget which contains its children as a single group. hasChildren = true hasState = false Show raw api { "functions": \[\], "properties": \[\ {\ "name": "Separator",\ "desc": "A vertical or horizonal line, depending on the context, which visually seperates widgets.\\n\\n\`\`\`lua\\nIris.Window({\\"Separator Demo\\"})\\n Iris.Text({\\"Some text here!\\"})\\n Iris.Separator()\\n Iris.Text({\\"This text has been separated!\\"})\\nIris.End()\\n\`\`\`\\n\\n!\[Example Separator\](/Iris/assets/api/format/basicSeparator.png)\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = false\\n\`\`\`\\n ",\ "lua\_type": "Iris.Separator",\ "tags": \[\ "Widget"\ \],\ "source": {\ "line": 299,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "Indent",\ "desc": "Indents its child widgets.\\n\\n\`\`\`lua\\nIris.Window({\\"Indent Demo\\"})\\n Iris.Text({\\"Unindented text!\\"})\\n Iris.Indent()\\n Iris.Text({\\"This text has been indented!\\"})\\n Iris.End()\\nIris.End()\\n\`\`\`\\n\\n!\[Example Indent\](/Iris/assets/api/format/basicIndent.png)\\n\\n\`\`\`lua\\nhasChildren = true\\nhasState = false\\nArguments = {\\n Width: number? = Iris.\_config.IndentSpacing -- indent width ammount.\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Indent",\ "tags": \[\ "Widget",\ "HasChildren"\ \],\ "source": {\ "line": 328,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "SameLine",\ "desc": "Positions its children in a row, horizontally.\\n\\n\`\`\`lua\\nIris.Window({\\"Same Line Demo\\"})\\n Iris.Text({\\"All of these buttons are on the same line!\\"})\\n Iris.SameLine()\\n Iris.Button({\\"Button 1\\"})\\n Iris.Button({\\"Button 2\\"})\\n Iris.Button({\\"Button 3\\"})\\n Iris.End()\\nIris.End()\\n\`\`\`\\n\\n!\[Example SameLine\](/Iris/assets/api/format/basicSameLine.png)\\n\\n\`\`\`lua\\nhasChildren = true\\nhasState = false\\nArguments = {\\n Width: number? = Iris.\_config.ItemSpacing.X, -- horizontal spacing between child widgets.\\n VerticalAlignment: Enum.VerticalAlignment? = Enum.VerticalAlignment.Center -- how widgets vertically to each other.\\n HorizontalAlignment: Enum.HorizontalAlignment? = Enum.HorizontalAlignment.Center -- how widgets are horizontally.\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.SameLine",\ "tags": \[\ "Widget",\ "HasChildren"\ \],\ "source": {\ "line": 361,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "Group",\ "desc": "Layout widget which contains its children as a single group.\\n\\n\`\`\`lua\\nhasChildren = true\\nhasState = false\\n\`\`\`\\n ",\ "lua\_type": "Iris.Group",\ "tags": \[\ "Widget",\ "HasChildren"\ \],\ "source": {\ "line": 376,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Format", "desc": "Format API\\n ", "source": { "line": 276, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Format#properties) * [Group](https://sirmallard.github.io/Iris/api/Format#Group) * [Indent](https://sirmallard.github.io/Iris/api/Format#Indent) * [SameLine](https://sirmallard.github.io/Iris/api/Format#SameLine) * [Separator](https://sirmallard.github.io/Iris/api/Format#Separator) --- # Iris | Iris [Skip to main content](https://sirmallard.github.io/Iris/api#__docusaurus_skipToContent_fallback) On this page Types[​](https://sirmallard.github.io/Iris/api#types "Direct link to Types") ----------------------------------------------------------------------------- ### `ID`[​](https://sirmallard.github.io/Iris/api#ID "Direct link to ID") [](https://github.com/SirMallard/Iris/blob/main/lib/WidgetTypes.lua#L5) `type` `ID =` `string` ### `Widget`[​](https://sirmallard.github.io/Iris/api#Widget "Direct link to Widget") [](https://github.com/SirMallard/Iris/blob/main/lib/WidgetTypes.lua#L28) `type` `Widget =` `{` `ID:` `[ID](https://sirmallard.github.io/Iris/api/Iris#ID) ``,` `type:` `string``,` `lastCycleTick:` `number``,` `parentWidget:` `[Widget](https://sirmallard.github.io/Iris/api/Iris#Widget) ``,` `Instance:` `[GuiObject](https://developer.roblox.com/en-us/api-reference/class/GuiObject)` `,` `ZIndex:` `number``,` `arguments:` `{``[``string``]``:` `any``}` `}` Properties[​](https://sirmallard.github.io/Iris/api#properties "Direct link to Properties") -------------------------------------------------------------------------------------------- ### `Disabled`[​](https://sirmallard.github.io/Iris/api#Disabled "Direct link to Disabled") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L34) `Iris.Disabled:` `boolean` While Iris.Disabled is true, execution of Iris and connected functions will be paused. The widgets are not destroyed, they are just frozen so no changes will happen to them. ### `Args`[​](https://sirmallard.github.io/Iris/api#Args "Direct link to Args") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L47) `Iris.Args:` `{``[``string``]``:` `{``[``string``]``:` `any``}``}` Provides a list of every possible Argument for each type of widget to it's index. For instance, `Iris.Args.Window.NoResize`. The Args table is useful for using widget Arguments without remembering their order. Iris.Window({"My Window", [Iris.Args.Window.NoResize] = true}) ### `TemplateConfig`[​](https://sirmallard.github.io/Iris/api#TemplateConfig "Direct link to TemplateConfig") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L335) `Iris.TemplateConfig:` `{``[``string``]``:` `{``[``string``]``:` `any``}``}` TemplateConfig provides a table of default styles and configurations which you may apply to your UI. Functions[​](https://sirmallard.github.io/Iris/api#functions "Direct link to Functions") ----------------------------------------------------------------------------------------- ### `SetFocusedWindow`[​](https://sirmallard.github.io/Iris/api#SetFocusedWindow "Direct link to SetFocusedWindow") [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L91) `Iris.``SetFocusedWindow``(` `window:` `Types.Window`\-- the window to focus. `) →` `(``)` Sets the focused window to the window provided, which brings it to the front and makes it active. ### `Init`[​](https://sirmallard.github.io/Iris/api#Init "Direct link to Init") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L73) `Iris.``Init``(` `parentInstance:` `[Instance?](https://developer.roblox.com/en-us/api-reference/datatype/Instance)` `,`\-- where Iris will place widgets UIs under, defaulting to [PlayerGui](https://developer.roblox.com/en-us/api-reference/class/PlayerGui) `eventConnection:` `(``[RBXScriptSignal](https://developer.roblox.com/en-us/api-reference/datatype/RBXScriptSignal)`  `|` `(``)` `→` `(``)` `|` `false``)``?``,`\-- the event to determine an Iris cycle, defaulting to \[Heartbeat\] `allowMultipleInits:` `boolean?`\-- allows subsequent calls 'Iris.Init()' to do nothing rather than error about initialising again, defaulting to false `) →` `[Iris](https://sirmallard.github.io/Iris/api/Iris) ` Initializes Iris and begins rendering. Can only be called once. See [Iris.Shutdown](https://sirmallard.github.io/Iris/api/Iris#Shutdown) to stop Iris, or [Iris.Disabled](https://sirmallard.github.io/Iris/api/Iris#Disabled) to temporarily disable Iris. Once initialized, [Iris:Connect](https://sirmallard.github.io/Iris/api/Iris#Connect) can be used to create a widget. If the `eventConnection` is `false` then Iris will not create a cycle loop and the user will need to call [Internal.\_cycle](https://sirmallard.github.io/Iris/api/Internal#_cycle) every frame. ### `Shutdown`[​](https://sirmallard.github.io/Iris/api#Shutdown "Direct link to Shutdown") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L122) `Iris.``Shutdown``(``) →` `(``)` Shuts Iris down. This can only be called once, and Iris cannot be started once shut down. ### `Append`[​](https://sirmallard.github.io/Iris/api#Append "Direct link to Append") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L180) `Iris.``Append``(` `userInstance:` `[GuiObject](https://developer.roblox.com/en-us/api-reference/class/GuiObject)` \-- the Roblox [Instance](https://developer.roblox.com/en-us/api-reference/datatype/Instance) to insert into Iris `) →` `(``)` Inserts any Roblox [Instance](https://developer.roblox.com/en-us/api-reference/datatype/Instance) into Iris. The parent of the inserted instance can either be determined by the `_config.Parent` property or by the current parent widget from the stack. ### `End`[​](https://sirmallard.github.io/Iris/api#End "Direct link to End") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L218) `Iris.``End``(``) →` `(``)` Marks the end of any widgets which contain children. For example: -- Widgets placed here **will not** be inside the tree Iris.Text({"Above and outside the tree"}) -- A Tree widget can contain children. -- We must therefore remember to call `Iris.End()` Iris.Tree({"My First Tree"}) -- Widgets placed here **will** be inside the tree Iris.Text({"Tree item 1"}) Iris.Text({"Tree item 2"}) Iris.End() -- Widgets placed here **will not** be inside the tree Iris.Text({"Below and outside the tree"}) ##### Caution: Error Seeing the error `Callback has too few calls to Iris.End()` or `Callback has too many calls to Iris.End()`? Using the wrong amount of `Iris.End()` calls in your code will lead to an error. Each widget called which might have children should be paired with a call to `Iris.End()`, **even if the Widget doesnt currently have any children**. ### `ForceRefresh`[​](https://sirmallard.github.io/Iris/api#ForceRefresh "Direct link to ForceRefresh") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L243) `Iris.``ForceRefresh``(``) →` `(``)` Destroys and regenerates all instances used by Iris. Useful if you want to propogate state changes. ##### Caution: Performance Because this function Deletes and Initializes many instances, it may cause **performance issues** when used with many widgets. In **no** case should it be called every frame. ### `UpdateGlobalConfig`[​](https://sirmallard.github.io/Iris/api#UpdateGlobalConfig "Direct link to UpdateGlobalConfig") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L265) `Iris.``UpdateGlobalConfig``(` `deltaStyle:` `{``[``string``]``:` `any``}`\-- a table containing the changes in style ex: `{ItemWidth = UDim.new(0, 100)}` `) →` `(``)` Customizes the configuration which **every** widget will inherit from. It can be used along with [Iris.TemplateConfig](https://sirmallard.github.io/Iris/api/Iris#TemplateConfig) to easily swap styles, for example: Iris.UpdateGlobalConfig(Iris.TemplateConfig.colorLight) -- use light theme ##### Caution: Performance This function internally calls [Iris.ForceRefresh](https://sirmallard.github.io/Iris/api/Iris#ForceRefresh) so that style changes are propogated. As such, it may cause **performance issues** when used with many widgets. In **no** case should it be called every frame. ### `PushConfig`[​](https://sirmallard.github.io/Iris/api#PushConfig "Direct link to PushConfig") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L290) `Iris.``PushConfig``(` `deltaStyle:` `{``[``string``]``:` `any``}`\-- a table containing the changes in style ex: `{ItemWidth = UDim.new(0, 100)}` `) →` `(``)` Allows cascading of a style by allowing styles to be locally and hierarchically applied. Each call to Iris.PushConfig must be paired with a call to [Iris.PopConfig](https://sirmallard.github.io/Iris/api/Iris#PopConfig) , for example: Iris.Text({"boring text"}) Iris.PushConfig({TextColor = Color3.fromRGB(128, 0, 256)}) Iris.Text({"Colored Text!"}) Iris.PopConfig() Iris.Text({"boring text"}) ### `PopConfig`[​](https://sirmallard.github.io/Iris/api#PopConfig "Direct link to PopConfig") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L318) `Iris.``PopConfig``(``) →` `(``)` Ends a [Iris.PushConfig](https://sirmallard.github.io/Iris/api/Iris#PushConfig) style. Each call to [Iris.PopConfig](https://sirmallard.github.io/Iris/api/Iris#PopConfig) should match a call to [Iris.PushConfig](https://sirmallard.github.io/Iris/api/Iris#PushConfig) . ### `PushId`[​](https://sirmallard.github.io/Iris/api#PushId "Direct link to PushId") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L354) `Iris.``PushId``(` `id:` `[ID](https://sirmallard.github.io/Iris/api/Iris#ID) `\-- custom id `) →` `(``)` Pushes an id onto the id stack for all future widgets. Use [Iris.PopId](https://sirmallard.github.io/Iris/api/Iris#PopId) to pop it off the stack. ### `PopID`[​](https://sirmallard.github.io/Iris/api#PopID "Direct link to PopID") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L367) `Iris.``PopID``(``) →` `(``)` Removes the most recent pushed id from the id stack. ### `SetNextWidgetID`[​](https://sirmallard.github.io/Iris/api#SetNextWidgetID "Direct link to SetNextWidgetID") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L397) `Iris.``SetNextWidgetID``(` `id:` `[ID](https://sirmallard.github.io/Iris/api/Iris#ID) `\-- custom id. `) →` `(``)` Sets the id for the next widget. Useful for using [Iris.Append](https://sirmallard.github.io/Iris/api/Iris#Append) on the same widget. Iris.SetNextWidgetId("demo_window") Iris.Window({ "Window" }) Iris.Text({ "Text one placed here." }) Iris.End() -- later in the code Iris.SetNextWidgetId("demo_window") Iris.Window() Iris.Text({ "Text two placed here." }) Iris.End() -- both text widgets will be placed under the same window despite being called separately. ### `State`[​](https://sirmallard.github.io/Iris/api#State%3CT%3E "Direct link to State") State [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L439) `Iris.``State``(` `initialValue:` `T`\-- the initial value for the state `) →` `[State](https://sirmallard.github.io/Iris/api/State) ``<``T``>` Constructs a new [State](https://sirmallard.github.io/Iris/api/State) object. Subsequent ID calls will return the same object. ##### INFO Iris.State allows you to create "references" to the same value while inside your UI drawing loop. For example: Iris:Connect(function() local myNumber = 5 myNumber = myNumber + 1 Iris.Text({"The number is: " .. myNumber}) end) This is problematic. Each time the function is called, a new myNumber is initialized, instead of retrieving the old one. The above code will always display 6. * * * Iris.State solves this problem: Iris:Connect(function() local myNumber = Iris.State(5) myNumber:set(myNumber:get() + 1) Iris.Text({"The number is: " .. myNumber}) end) In this example, the code will work properly, and increment every frame. ### `WeakState`[​](https://sirmallard.github.io/Iris/api#WeakState%3CT%3E "Direct link to WeakState") State [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L465) `Iris.``WeakState``(` `initialValue:` `T`\-- the initial value for the state `) →` `[State](https://sirmallard.github.io/Iris/api/State) ``<``T``>` Constructs a new state object, subsequent ID calls will return the same object, except all widgets connected to the state are discarded, the state reverts to the passed initialValue ### `VariableState`[​](https://sirmallard.github.io/Iris/api#VariableState%3CT%3E "Direct link to VariableState") State [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L524) `Iris.``VariableState``(` `variable:` `T``,`\-- the variable to track `callback:` `(``T``)` `→` `(``)`\-- a function which sets the new variable locally `) →` `[State](https://sirmallard.github.io/Iris/api/State) ``<``T``>` Returns a state object linked to a local variable. The passed variable is used to check whether the state object should update. The callback method is used to change the local variable when the state changes. The existence of such a function is to make working with local variables easier. Since Iris cannot directly manipulate the memory of the variable, like in C++, it must instead rely on the user updating it through the callback provided. Additionally, because the state value is not updated when created or called we cannot return the new value back, instead we require a callback for the user to update. local myNumber = 5 local state = Iris.VariableState(myNumber, function(value) myNumber = value end) Iris.DragNum({ "My number" }, { number = state }) This is how Dear ImGui does the same in C++ where we can just provide the memory location to the variable which is then updated directly. static int myNumber = 5; ImGui::DragInt("My number", &myNumber); // Here in C++, we can directly pass the variable. ##### Caution: Update Order If the variable and state value are different when calling this, the variable value takes precedence. Therefore, if you update the state using `state.value = ...` then it will be overwritten by the variable value. You must use `state:set(...)` if you want the variable to update to the state's value. ### `TableState`[​](https://sirmallard.github.io/Iris/api#TableState%3CK,%20V%3E "Direct link to TableState") State [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L604) `Iris.``TableState``(` `table:` `{``[``K``]``:` `V``}``,`\-- the table containing the value `key:` `K``,`\-- the key to the value in table `callback:` `(``(``newValue:` `V``)` `→` `false?``)``?`\-- a function called when the state is changed `) →` `[State](https://sirmallard.github.io/Iris/api/State) ``<``V``>` Similar to Iris.VariableState but takes a table and key to modify a specific value and a callback to determine whether to update the value. The passed table and key are used to check the value. The callback is called when the state changes value and determines whether we update the table. This is useful if we want to monitor a table value which needs to call other functions when changed. Since tables are pass-by-reference, we can modify the table anywhere and it will update all other instances. Therefore, we don't need a callback by default. local data = { myNumber = 5 } local state = Iris.TableState(data, "myNumber") Iris.DragNum({ "My number" }, { number = state }) Here the `data._started` should never be updated directly, only through the `toggle` function. However, we still want to monitor the value and be able to change it. Therefore, we use the callback to toggle the function for us and prevent Iris from updating the table value by returning false. local data = { _started = false } local function toggle(enabled: boolean) data._started = enabled if data._started then start(...) else stop(...) end end local state = Iris.TableState(data, "_started", function(stateValue: boolean) toggle(stateValue) return false end) Iris.Checkbox({ "Started" }, { isChecked = state }) ##### Caution: Update Order If the table value and state value are different when calling this, the table value value takes precedence. Therefore, if you update the state using `state.value = ...` then it will be overwritten by the table value. You must use `state:set(...)` if you want the table value to update to the state's value. ### `ComputedState`[​](https://sirmallard.github.io/Iris/api#ComputedState%3CT,%20U%3E "Direct link to ComputedState") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L657) `Iris.``ComputedState``(` `firstState:` `[State](https://sirmallard.github.io/Iris/api/State) ``<``T``>``,`\-- State to bind to. `onChangeCallback:` `(``firstValue:` `T``)` `→` `U`\-- callback which should return a value transformed from the firstState value `) →` `[State](https://sirmallard.github.io/Iris/api/State) ``<``U``>` Constructs a new State object, but binds its value to the value of another State. ##### INFO A common use case for this constructor is when a boolean State needs to be inverted: Iris.ComputedState(otherState, function(newValue) return not newValue end) ### `ShowDemoWindow`[​](https://sirmallard.github.io/Iris/api#ShowDemoWindow "Direct link to ShowDemoWindow") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L691) `Iris.``ShowDemoWindow``(``) →` `(``)` ShowDemoWindow is a function which creates a Demonstration window. this window contains many useful utilities for coders, and serves as a refrence for using each part of the library. Ideally, the DemoWindow should always be available in your UI. It is the same as any other callback you would connect to Iris using [Iris.Connect](https://sirmallard.github.io/Iris/api/Iris#Connect) Iris:Connect(Iris.ShowDemoWindow) ### `Connect`[​](https://sirmallard.github.io/Iris/api#Connect "Direct link to Connect") [](https://github.com/SirMallard/Iris/blob/main/lib/init.lua#L159) `Iris:``Connect``(` `callback:` `(``)` `→` `(``)`\-- the callback containg the Iris code `) →` `(``)` `→` `(``)`\-- call to disconnect it Connects a function which will execute every Iris cycle. [Iris.Init](https://sirmallard.github.io/Iris/api/Iris#Init) must be called before connecting. A cycle is determined by the `eventConnection` passed to [Iris.Init](https://sirmallard.github.io/Iris/api/Iris#Init) (default to [RunService.Heartbeat](https://developer.roblox.com/en-us/api-reference/class/RunService#Heartbeat) ). Multiple callbacks can be added to Iris from many different scripts or modules. Show raw api { "functions": \[\ {\ "name": "SetFocusedWindow",\ "desc": "Sets the focused window to the window provided, which brings it to the front and makes it active.\\n ",\ "params": \[\ {\ "name": "window",\ "desc": "the window to focus.",\ "lua\_type": "Types.Window"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 91,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "Init",\ "desc": "Initializes Iris and begins rendering. Can only be called once.\\nSee \[Iris.Shutdown\] to stop Iris, or \[Iris.Disabled\] to temporarily disable Iris.\\n\\nOnce initialized, \[Iris:Connect\] can be used to create a widget.\\n\\nIf the \`eventConnection\` is \`false\` then Iris will not create a cycle loop and the user will need to call \[Internal.\_cycle\] every frame.",\ "params": \[\ {\ "name": "parentInstance",\ "desc": "where Iris will place widgets UIs under, defaulting to \[PlayerGui\]",\ "lua\_type": "Instance?"\ },\ {\ "name": "eventConnection",\ "desc": "the event to determine an Iris cycle, defaulting to \[Heartbeat\]",\ "lua\_type": "(RBXScriptSignal | () -> () | false)?"\ },\ {\ "name": "allowMultipleInits",\ "desc": "allows subsequent calls 'Iris.Init()' to do nothing rather than error about initialising again, defaulting to false",\ "lua\_type": "boolean?"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "Iris"\ }\ \],\ "function\_type": "static",\ "source": {\ "line": 73,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "Shutdown",\ "desc": "Shuts Iris down. This can only be called once, and Iris cannot be started once shut down.",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 122,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "Connect",\ "desc": "Connects a function which will execute every Iris cycle. \[Iris.Init\] must be called before connecting.\\n\\nA cycle is determined by the \`eventConnection\` passed to \[Iris.Init\] (default to \[RunService.Heartbeat\]).\\n\\nMultiple callbacks can be added to Iris from many different scripts or modules.",\ "params": \[\ {\ "name": "callback",\ "desc": "the callback containg the Iris code",\ "lua\_type": "() -> ()"\ }\ \],\ "returns": \[\ {\ "desc": "call to disconnect it",\ "lua\_type": "() -> ()"\ }\ \],\ "function\_type": "method",\ "source": {\ "line": 159,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "Append",\ "desc": "Inserts any Roblox \[Instance\] into Iris.\\n\\nThe parent of the inserted instance can either be determined by the \`\_config.Parent\`\\nproperty or by the current parent widget from the stack.",\ "params": \[\ {\ "name": "userInstance",\ "desc": "the Roblox \[Instance\] to insert into Iris",\ "lua\_type": "GuiObject"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 180,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "End",\ "desc": "Marks the end of any widgets which contain children. For example:\\n\`\`\`lua\\n-- Widgets placed here \*\*will not\*\* be inside the tree\\nIris.Text({\\"Above and outside the tree\\"})\\n\\n-- A Tree widget can contain children.\\n-- We must therefore remember to call \`Iris.End()\`\\nIris.Tree({\\"My First Tree\\"})\\n -- Widgets placed here \*\*will\*\* be inside the tree\\n Iris.Text({\\"Tree item 1\\"})\\n Iris.Text({\\"Tree item 2\\"})\\nIris.End()\\n\\n-- Widgets placed here \*\*will not\*\* be inside the tree\\nIris.Text({\\"Below and outside the tree\\"})\\n\`\`\`\\n:::caution Caution: Error\\nSeeing the error \`Callback has too few calls to Iris.End()\` or \`Callback has too many calls to Iris.End()\`?\\nUsing the wrong amount of \`Iris.End()\` calls in your code will lead to an error.\\n\\nEach widget called which might have children should be paired with a call to \`Iris.End()\`, \*\*even if the Widget doesnt currently have any children\*\*.\\n:::",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 218,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "ForceRefresh",\ "desc": "Destroys and regenerates all instances used by Iris. Useful if you want to propogate state changes.\\n:::caution Caution: Performance\\nBecause this function Deletes and Initializes many instances, it may cause \*\*performance issues\*\* when used with many widgets.\\nIn \*\*no\*\* case should it be called every frame.\\n:::",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 243,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "UpdateGlobalConfig",\ "desc": "Customizes the configuration which \*\*every\*\* widget will inherit from.\\n\\nIt can be used along with \[Iris.TemplateConfig\] to easily swap styles, for example:\\n\`\`\`lua\\nIris.UpdateGlobalConfig(Iris.TemplateConfig.colorLight) -- use light theme\\n\`\`\`\\n:::caution Caution: Performance\\nThis function internally calls \[Iris.ForceRefresh\] so that style changes are propogated.\\n\\nAs such, it may cause \*\*performance issues\*\* when used with many widgets.\\nIn \*\*no\*\* case should it be called every frame.\\n:::",\ "params": \[\ {\ "name": "deltaStyle",\ "desc": "a table containing the changes in style ex: \`{ItemWidth = UDim.new(0, 100)}\`",\ "lua\_type": "{ \[string\]: any }"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 265,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "PushConfig",\ "desc": "Allows cascading of a style by allowing styles to be locally and hierarchically applied.\\n\\nEach call to Iris.PushConfig must be paired with a call to \[Iris.PopConfig\], for example:\\n\`\`\`lua\\nIris.Text({\\"boring text\\"})\\n\\nIris.PushConfig({TextColor = Color3.fromRGB(128, 0, 256)})\\n Iris.Text({\\"Colored Text!\\"})\\nIris.PopConfig()\\n\\nIris.Text({\\"boring text\\"})\\n\`\`\`",\ "params": \[\ {\ "name": "deltaStyle",\ "desc": "a table containing the changes in style ex: \`{ItemWidth = UDim.new(0, 100)}\`",\ "lua\_type": "{ \[string\]: any }"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 290,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "PopConfig",\ "desc": "Ends a \[Iris.PushConfig\] style.\\n\\nEach call to \[Iris.PopConfig\] should match a call to \[Iris.PushConfig\].",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 318,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "PushId",\ "desc": "Pushes an id onto the id stack for all future widgets. Use \[Iris.PopId\] to pop it off the stack.",\ "params": \[\ {\ "name": "id",\ "desc": "custom id",\ "lua\_type": "ID"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 354,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "PopID",\ "desc": "Removes the most recent pushed id from the id stack.",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 367,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "SetNextWidgetID",\ "desc": "Sets the id for the next widget. Useful for using \[Iris.Append\] on the same widget.\\n\`\`\`lua\\nIris.SetNextWidgetId(\\"demo\_window\\")\\nIris.Window({ \\"Window\\" })\\n Iris.Text({ \\"Text one placed here.\\" })\\nIris.End()\\n\\n-- later in the code\\n\\nIris.SetNextWidgetId(\\"demo\_window\\")\\nIris.Window()\\n Iris.Text({ \\"Text two placed here.\\" })\\nIris.End()\\n\\n-- both text widgets will be placed under the same window despite being called separately.\\n\`\`\`",\ "params": \[\ {\ "name": "id",\ "desc": "custom id.",\ "lua\_type": "ID"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 397,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "State",\ "desc": "Constructs a new \[State\] object. Subsequent ID calls will return the same object.\\n:::info\\nIris.State allows you to create \\"references\\" to the same value while inside your UI drawing loop.\\nFor example:\\n\`\`\`lua\\nIris:Connect(function()\\n local myNumber = 5\\n myNumber = myNumber + 1\\n Iris.Text({\\"The number is: \\" .. myNumber})\\nend)\\n\`\`\`\\nThis is problematic. Each time the function is called, a new myNumber is initialized, instead of retrieving the old one.\\nThe above code will always display 6.\\n\*\*\*\\nIris.State solves this problem:\\n\`\`\`lua\\nIris:Connect(function()\\n local myNumber = Iris.State(5)\\n myNumber:set(myNumber:get() + 1)\\n Iris.Text({\\"The number is: \\" .. myNumber})\\nend)\\n\`\`\`\\nIn this example, the code will work properly, and increment every frame.\\n:::",\ "params": \[\ {\ "name": "initialValue",\ "desc": "the initial value for the state",\ "lua\_type": "T"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "State"\ }\ \],\ "function\_type": "static",\ "tags": \[\ "State"\ \],\ "source": {\ "line": 439,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "WeakState",\ "desc": "Constructs a new state object, subsequent ID calls will return the same object, except all widgets connected to the state are discarded, the state reverts to the passed initialValue",\ "params": \[\ {\ "name": "initialValue",\ "desc": "the initial value for the state",\ "lua\_type": "T"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "State"\ }\ \],\ "function\_type": "static",\ "tags": \[\ "State"\ \],\ "source": {\ "line": 465,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "VariableState",\ "desc": "Returns a state object linked to a local variable.\\n\\nThe passed variable is used to check whether the state object should update. The callback method is used to change the local variable when the state changes.\\n\\nThe existence of such a function is to make working with local variables easier.\\nSince Iris cannot directly manipulate the memory of the variable, like in C++, it must instead rely on the user updating it through the callback provided.\\nAdditionally, because the state value is not updated when created or called we cannot return the new value back, instead we require a callback for the user to update.\\n\\n\`\`\`lua\\nlocal myNumber = 5\\n\\nlocal state = Iris.VariableState(myNumber, function(value)\\n myNumber = value\\nend)\\nIris.DragNum({ \\"My number\\" }, { number = state })\\n\`\`\`\\n\\nThis is how Dear ImGui does the same in C++ where we can just provide the memory location to the variable which is then updated directly.\\n\`\`\`cpp\\nstatic int myNumber = 5;\\nImGui::DragInt(\\"My number\\", &myNumber); // Here in C++, we can directly pass the variable.\\n\`\`\`\\n\\n:::caution Caution: Update Order\\nIf the variable and state value are different when calling this, the variable value takes precedence.\\n\\nTherefore, if you update the state using \`state.value = ...\` then it will be overwritten by the variable value.\\nYou must use \`state:set(...)\` if you want the variable to update to the state's value.\\n:::",\ "params": \[\ {\ "name": "variable",\ "desc": "the variable to track",\ "lua\_type": "T"\ },\ {\ "name": "callback",\ "desc": "a function which sets the new variable locally",\ "lua\_type": "(T) -> ()"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "State"\ }\ \],\ "function\_type": "static",\ "tags": \[\ "State"\ \],\ "source": {\ "line": 524,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "TableState",\ "desc": "Similar to Iris.VariableState but takes a table and key to modify a specific value and a callback to determine whether to update the value.\\n\\nThe passed table and key are used to check the value. The callback is called when the state changes value and determines whether we update the table.\\nThis is useful if we want to monitor a table value which needs to call other functions when changed.\\n\\nSince tables are pass-by-reference, we can modify the table anywhere and it will update all other instances. Therefore, we don't need a callback by default.\\n\`\`\`lua\\nlocal data = {\\n myNumber = 5\\n}\\n\\nlocal state = Iris.TableState(data, \\"myNumber\\")\\nIris.DragNum({ \\"My number\\" }, { number = state })\\n\`\`\`\\n\\nHere the \`data.\_started\` should never be updated directly, only through the \`toggle\` function. However, we still want to monitor the value and be able to change it.\\nTherefore, we use the callback to toggle the function for us and prevent Iris from updating the table value by returning false.\\n\`\`\`lua\\nlocal data = {\\n \_started = false\\n}\\n\\nlocal function toggle(enabled: boolean)\\n data.\_started = enabled\\n if data.\_started then\\n start(...)\\n else\\n stop(...)\\n end\\nend\\n\\nlocal state = Iris.TableState(data, \\"\_started\\", function(stateValue: boolean)\\n toggle(stateValue)\\n return false\\nend)\\nIris.Checkbox({ \\"Started\\" }, { isChecked = state })\\n\`\`\`\\n\\n:::caution Caution: Update Order\\nIf the table value and state value are different when calling this, the table value value takes precedence.\\n\\nTherefore, if you update the state using \`state.value = ...\` then it will be overwritten by the table value.\\nYou must use \`state:set(...)\` if you want the table value to update to the state's value.\\n:::",\ "params": \[\ {\ "name": "table",\ "desc": "the table containing the value",\ "lua\_type": "{ \[K\]: V }"\ },\ {\ "name": "key",\ "desc": "the key to the value in table",\ "lua\_type": "K"\ },\ {\ "name": "callback",\ "desc": "a function called when the state is changed",\ "lua\_type": "((newValue: V) -> false?)?"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "State"\ }\ \],\ "function\_type": "static",\ "tags": \[\ "State"\ \],\ "source": {\ "line": 604,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "ComputedState",\ "desc": "Constructs a new State object, but binds its value to the value of another State.\\n:::info\\nA common use case for this constructor is when a boolean State needs to be inverted:\\n\`\`\`lua\\nIris.ComputedState(otherState, function(newValue)\\n return not newValue\\nend)\\n\`\`\`\\n:::",\ "params": \[\ {\ "name": "firstState",\ "desc": "State to bind to.",\ "lua\_type": "State"\ },\ {\ "name": "onChangeCallback",\ "desc": "callback which should return a value transformed from the firstState value",\ "lua\_type": "(firstValue: T) -> U"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "State"\ }\ \],\ "function\_type": "static",\ "source": {\ "line": 657,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "ShowDemoWindow",\ "desc": "ShowDemoWindow is a function which creates a Demonstration window. this window contains many useful utilities for coders,\\nand serves as a refrence for using each part of the library. Ideally, the DemoWindow should always be available in your UI.\\nIt is the same as any other callback you would connect to Iris using \[Iris.Connect\]\\n\`\`\`lua\\nIris:Connect(Iris.ShowDemoWindow)\\n\`\`\`",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 691,\ "path": "lib/init.lua"\ }\ }\ \], "properties": \[\ {\ "name": "Disabled",\ "desc": "While Iris.Disabled is true, execution of Iris and connected functions will be paused.\\nThe widgets are not destroyed, they are just frozen so no changes will happen to them.",\ "lua\_type": "boolean",\ "source": {\ "line": 34,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "Args",\ "desc": "Provides a list of every possible Argument for each type of widget to it's index.\\nFor instance, \`Iris.Args.Window.NoResize\`.\\nThe Args table is useful for using widget Arguments without remembering their order.\\n\`\`\`lua\\nIris.Window({\\"My Window\\", \[Iris.Args.Window.NoResize\] = true})\\n\`\`\`",\ "lua\_type": "{ \[string\]: { \[string\]: any } }",\ "source": {\ "line": 47,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "Events",\ "desc": "-todo: work out what this is used for.",\ "lua\_type": "table",\ "ignore": true,\ "source": {\ "line": 56,\ "path": "lib/init.lua"\ }\ },\ {\ "name": "TemplateConfig",\ "desc": "TemplateConfig provides a table of default styles and configurations which you may apply to your UI.",\ "lua\_type": "{ \[string\]: { \[string\]: any } }",\ "source": {\ "line": 335,\ "path": "lib/init.lua"\ }\ }\ \], "types": \[\ {\ "name": "ID",\ "desc": "",\ "lua\_type": "string",\ "source": {\ "line": 5,\ "path": "lib/WidgetTypes.lua"\ }\ },\ {\ "name": "Widget",\ "desc": "",\ "lua\_type": "{ ID: ID, type: string, lastCycleTick: number, parentWidget: Widget, Instance: GuiObject, ZIndex: number, arguments: { \[string\]: any }}",\ "source": {\ "line": 28,\ "path": "lib/WidgetTypes.lua"\ }\ }\ \], "name": "Iris", "desc": "Iris; contains the all user-facing functions and properties.\\nA set of internal functions can be found in \`Iris.Internal\` (only use if you understand).\\n\\nIn its simplest form, users may start Iris by using\\n\`\`\`lua\\nIris.Init()\\n\\nIris:Connect(function()\\n Iris.Window({\\"My First Window!\\"})\\n Iris.Text({\\"Hello, World\\"})\\n Iris.Button({\\"Save\\"})\\n Iris.InputNum({\\"Input\\"})\\n Iris.End()\\nend)\\n\`\`\`", "source": { "line": 23, "path": "lib/init.lua" } } * [Types](https://sirmallard.github.io/Iris/api#types) * [ID](https://sirmallard.github.io/Iris/api#ID) * [Widget](https://sirmallard.github.io/Iris/api#Widget) * [Properties](https://sirmallard.github.io/Iris/api#properties) * [Args](https://sirmallard.github.io/Iris/api#Args) * [Disabled](https://sirmallard.github.io/Iris/api#Disabled) * [TemplateConfig](https://sirmallard.github.io/Iris/api#TemplateConfig) * [Functions](https://sirmallard.github.io/Iris/api#functions) * [:Connect](https://sirmallard.github.io/Iris/api#Connect) * [.Append](https://sirmallard.github.io/Iris/api#Append) * [.ComputedState](https://sirmallard.github.io/Iris/api#ComputedState%3CT,%20U%3E) * [.End](https://sirmallard.github.io/Iris/api#End) * [.ForceRefresh](https://sirmallard.github.io/Iris/api#ForceRefresh) * [.Init](https://sirmallard.github.io/Iris/api#Init) * [.PopConfig](https://sirmallard.github.io/Iris/api#PopConfig) * [.PopID](https://sirmallard.github.io/Iris/api#PopID) * [.PushConfig](https://sirmallard.github.io/Iris/api#PushConfig) * [.PushId](https://sirmallard.github.io/Iris/api#PushId) * [.SetFocusedWindow](https://sirmallard.github.io/Iris/api#SetFocusedWindow) * [.SetNextWidgetID](https://sirmallard.github.io/Iris/api#SetNextWidgetID) * [.ShowDemoWindow](https://sirmallard.github.io/Iris/api#ShowDemoWindow) * [.Shutdown](https://sirmallard.github.io/Iris/api#Shutdown) * [.State](https://sirmallard.github.io/Iris/api#State%3CT%3E) * [.TableState](https://sirmallard.github.io/Iris/api#TableState%3CK,%20V%3E) * [.UpdateGlobalConfig](https://sirmallard.github.io/Iris/api#UpdateGlobalConfig) * [.VariableState](https://sirmallard.github.io/Iris/api#VariableState%3CT%3E) * [.WeakState](https://sirmallard.github.io/Iris/api#WeakState%3CT%3E) --- # Image | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Image#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Image#properties "Direct link to Properties") -------------------------------------------------------------------------------------------------- ### `Image`[​](https://sirmallard.github.io/Iris/api/Image#Image "Direct link to Image") Widget [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L692) `Image.Image:` `Iris.Image` An image widget for displaying an image given its texture ID and a size. The widget also supports Rect Offset and Size allowing cropping of the image and the rest of the ScaleType properties. Some of the arguments are only used depending on the ScaleType property, such as TileSize or Slice which will be ignored. hasChildren = false hasState = false Arguments = { Image: string, -- the texture asset id Size: UDim2, Rect: Rect? = Rect.new(), -- Rect structure which is used to determine the offset or size. An empty, zeroed rect is equivalent to nil ScaleType: Enum.ScaleType? = Enum.ScaleType.Stretch, -- used to determine whether the TileSize, SliceCenter and SliceScale arguments are used ResampleMode: Enum.ResampleMode? = Enum.ResampleMode.Default, TileSize: UDim2? = UDim2.fromScale(1, 1), -- only used if the ScaleType is set to Tile SliceCenter: Rect? = Rect.new(), -- only used if the ScaleType is set to Slice SliceScale: number? = 1 -- only used if the ScaleType is set to Slice } Events = { hovered: () -> boolean } ### `ImageButton`[​](https://sirmallard.github.io/Iris/api/Image#ImageButton "Direct link to ImageButton") Widget [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L724) `Image.ImageButton:` `Iris.ImageButton` An image button widget for a button as an image given its texture ID and a size. The widget also supports Rect Offset and Size allowing cropping of the image, and the rest of the ScaleType properties. Supports all of the events of a regular button. hasChildren = false hasState = false Arguments = { Image: string, -- the texture asset id Size: UDim2, Rect: Rect? = Rect.new(), -- Rect structure which is used to determine the offset or size. An empty, zeroed rect is equivalent to nil ScaleType: Enum.ScaleType? = Enum.ScaleType.Stretch, -- used to determine whether the TileSize, SliceCenter and SliceScale arguments are used ResampleMode: Enum.ResampleMode? = Enum.ResampleMode.Default, TileSize: UDim2? = UDim2.fromScale(1, 1), -- only used if the ScaleType is set to Tile SliceCenter: Rect? = Rect.new(), -- only used if the ScaleType is set to Slice SliceScale: number? = 1 -- only used if the ScaleType is set to Slice } Events = { clicked: () -> boolean, rightClicked: () -> boolean, doubleClicked: () -> boolean, ctrlClicked: () -> boolean, -- when the control key is down and clicked. hovered: () -> boolean } Show raw api { "functions": \[\], "properties": \[\ {\ "name": "Image",\ "desc": "An image widget for displaying an image given its texture ID and a size. The widget also supports Rect Offset and Size allowing cropping of the image and the rest of the ScaleType properties.\\nSome of the arguments are only used depending on the ScaleType property, such as TileSize or Slice which will be ignored.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = false\\nArguments = {\\n Image: string, -- the texture asset id\\n Size: UDim2,\\n Rect: Rect? = Rect.new(), -- Rect structure which is used to determine the offset or size. An empty, zeroed rect is equivalent to nil\\n ScaleType: Enum.ScaleType? = Enum.ScaleType.Stretch, -- used to determine whether the TileSize, SliceCenter and SliceScale arguments are used\\n ResampleMode: Enum.ResampleMode? = Enum.ResampleMode.Default,\\n TileSize: UDim2? = UDim2.fromScale(1, 1), -- only used if the ScaleType is set to Tile\\n SliceCenter: Rect? = Rect.new(), -- only used if the ScaleType is set to Slice\\n SliceScale: number? = 1 -- only used if the ScaleType is set to Slice\\n}\\nEvents = {\\n hovered: () -> boolean\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Image",\ "tags": \[\ "Widget"\ \],\ "source": {\ "line": 692,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "ImageButton",\ "desc": "An image button widget for a button as an image given its texture ID and a size. The widget also supports Rect Offset and Size allowing cropping of the image, and the rest of the ScaleType properties.\\nSupports all of the events of a regular button.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = false\\nArguments = {\\n Image: string, -- the texture asset id\\n Size: UDim2,\\n Rect: Rect? = Rect.new(), -- Rect structure which is used to determine the offset or size. An empty, zeroed rect is equivalent to nil\\n ScaleType: Enum.ScaleType? = Enum.ScaleType.Stretch, -- used to determine whether the TileSize, SliceCenter and SliceScale arguments are used\\n ResampleMode: Enum.ResampleMode? = Enum.ResampleMode.Default,\\n TileSize: UDim2? = UDim2.fromScale(1, 1), -- only used if the ScaleType is set to Tile\\n SliceCenter: Rect? = Rect.new(), -- only used if the ScaleType is set to Slice\\n SliceScale: number? = 1 -- only used if the ScaleType is set to Slice\\n}\\nEvents = {\\n clicked: () -> boolean,\\n rightClicked: () -> boolean,\\n doubleClicked: () -> boolean,\\n ctrlClicked: () -> boolean, -- when the control key is down and clicked.\\n hovered: () -> boolean\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.ImageButton",\ "tags": \[\ "Widget"\ \],\ "source": {\ "line": 724,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Image", "desc": "Image Widget API\\n\\nProvides two widgets for Images and ImageButtons, which provide the same control as a an ImageLabel instance.\\n ", "source": { "line": 665, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Image#properties) * [Image](https://sirmallard.github.io/Iris/api/Image#Image) * [ImageButton](https://sirmallard.github.io/Iris/api/Image#ImageButton) --- # Input | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Input#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Input#properties "Direct link to Properties") -------------------------------------------------------------------------------------------------- ### `InputNum`[​](https://sirmallard.github.io/Iris/api/Input#InputNum "Direct link to InputNum") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L934) `Input.InputNum:` `Iris.InputNum` An input box for numbers. The number can be either an integer or a float. hasChildren = false hasState = true Arguments = { Text: string? = "InputNum", Increment: number? = nil, Min: number? = nil, Max: number? = nil, Format: string? | { string }? = [DYNAMIC], -- Iris will dynamically generate an approriate format. NoButtons: boolean? = false -- whether to display + and - buttons next to the input box. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `InputVector2`[​](https://sirmallard.github.io/Iris/api/Input#InputVector2 "Direct link to InputVector2") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L964) `Input.InputVector2:` `Iris.InputVector2` An input box for Vector2. The numbers can be either integers or floats. hasChildren = false hasState = true Arguments = { Text: string? = "InputVector2", Increment: Vector2? = nil, Min: Vector2? = nil, Max: Vector2? = nil, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `InputVector3`[​](https://sirmallard.github.io/Iris/api/Input#InputVector3 "Direct link to InputVector3") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L994) `Input.InputVector3:` `Iris.InputVector3` An input box for Vector3. The numbers can be either integers or floats. hasChildren = false hasState = true Arguments = { Text: string? = "InputVector3", Increment: Vector3? = nil, Min: Vector3? = nil, Max: Vector3? = nil, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `InputUDim`[​](https://sirmallard.github.io/Iris/api/Input#InputUDim "Direct link to InputUDim") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1025) `Input.InputUDim:` `Iris.InputUDim` An input box for UDim. The Scale box will be a float and the Offset box will be an integer, unless specified differently. hasChildren = false hasState = true Arguments = { Text: string? = "InputUDim", Increment: UDim? = nil, Min: UDim? = nil, Max: UDim? = nil, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `InputUDim2`[​](https://sirmallard.github.io/Iris/api/Input#InputUDim2 "Direct link to InputUDim2") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1056) `Input.InputUDim2:` `Iris.InputUDim2` An input box for UDim2. The Scale boxes will be floats and the Offset boxes will be integers, unless specified differently. hasChildren = false hasState = true Arguments = { Text: string? = "InputUDim2", Increment: UDim2? = nil, Min: UDim2? = nil, Max: UDim2? = nil, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `InputRect`[​](https://sirmallard.github.io/Iris/api/Input#InputRect "Direct link to InputRect") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1086) `Input.InputRect:` `Iris.InputRect` An input box for Rect. The numbers will default to integers, unless specified differently. hasChildren = false hasState = true Arguments = { Text: string? = "InputRect", Increment: Rect? = nil, Min: Rect? = nil, Max: Rect? = nil, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `InputColor3`[​](https://sirmallard.github.io/Iris/api/Input#InputColor3 "Direct link to InputColor3") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1323) `Input.InputColor3:` `Iris.InputColor3` An input box for Color3. The input boxes are draggable between 0 and 255 or if UseFloats then between 0 and 1. Input can also be done using HSV instead of the default RGB. If no format argument is provided then a default R, G, B or H, S, V prefix is applied. hasChildren = false hasState = true Arguments = { Text: string? = "InputColor3", UseFloats: boolean? = false, -- constrain the values between floats 0 and 1 or integers 0 and 255. UseHSV: boolean? = false, -- input using HSV instead. Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { color: State?, editingText: State? } ### `InputColor4`[​](https://sirmallard.github.io/Iris/api/Input#InputColor4 "Direct link to InputColor4") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1357) `Input.InputColor4:` `Iris.InputColor4` An input box for Color4. Color4 is a combination of Color3 and a fourth transparency argument. It has two states for this purpose. The input boxes are draggable between 0 and 255 or if UseFloats then between 0 and 1. Input can also be done using HSV instead of the default RGB. If no format argument is provided then a default R, G, B, T or H, S, V, T prefix is applied. hasChildren = false hasState = true Arguments = { Text: string? = "InputColor4", UseFloats: boolean? = false, -- constrain the values between floats 0 and 1 or integers 0 and 255. UseHSV: boolean? = false, -- input using HSV instead. Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { color: State?, transparency: State?, editingText: State? } Show raw api { "functions": \[\], "properties": \[\ {\ "name": "InputNum",\ "desc": "An input box for numbers. The number can be either an integer or a float.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"InputNum\\",\\n Increment: number? = nil,\\n Min: number? = nil,\\n Max: number? = nil,\\n Format: string? | { string }? = \[DYNAMIC\], -- Iris will dynamically generate an approriate format.\\n NoButtons: boolean? = false -- whether to display + and - buttons next to the input box.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.InputNum",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 934,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "InputVector2",\ "desc": "An input box for Vector2. The numbers can be either integers or floats.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"InputVector2\\",\\n Increment: Vector2? = nil,\\n Min: Vector2? = nil,\\n Max: Vector2? = nil,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.InputVector2",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 964,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "InputVector3",\ "desc": "An input box for Vector3. The numbers can be either integers or floats.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"InputVector3\\",\\n Increment: Vector3? = nil,\\n Min: Vector3? = nil,\\n Max: Vector3? = nil,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.InputVector3",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 994,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "InputUDim",\ "desc": "An input box for UDim. The Scale box will be a float and the Offset box will be\\nan integer, unless specified differently.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"InputUDim\\",\\n Increment: UDim? = nil,\\n Min: UDim? = nil,\\n Max: UDim? = nil,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.InputUDim",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1025,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "InputUDim2",\ "desc": "An input box for UDim2. The Scale boxes will be floats and the Offset boxes will be\\nintegers, unless specified differently.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"InputUDim2\\",\\n Increment: UDim2? = nil,\\n Min: UDim2? = nil,\\n Max: UDim2? = nil,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.InputUDim2",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1056,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "InputRect",\ "desc": "An input box for Rect. The numbers will default to integers, unless specified differently.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"InputRect\\",\\n Increment: Rect? = nil,\\n Min: Rect? = nil,\\n Max: Rect? = nil,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.InputRect",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1086,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "InputColor3",\ "desc": "An input box for Color3. The input boxes are draggable between 0 and 255 or if UseFloats then between 0 and 1.\\nInput can also be done using HSV instead of the default RGB.\\nIf no format argument is provided then a default R, G, B or H, S, V prefix is applied.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"InputColor3\\",\\n UseFloats: boolean? = false, -- constrain the values between floats 0 and 1 or integers 0 and 255.\\n UseHSV: boolean? = false, -- input using HSV instead.\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n color: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.InputColor3",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1323,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "InputColor4",\ "desc": "An input box for Color4. Color4 is a combination of Color3 and a fourth transparency argument.\\nIt has two states for this purpose.\\nThe input boxes are draggable between 0 and 255 or if UseFloats then between 0 and 1.\\nInput can also be done using HSV instead of the default RGB.\\nIf no format argument is provided then a default R, G, B, T or H, S, V, T prefix is applied.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"InputColor4\\",\\n UseFloats: boolean? = false, -- constrain the values between floats 0 and 1 or integers 0 and 255.\\n UseHSV: boolean? = false, -- input using HSV instead.\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n color: State?,\\n transparency: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.InputColor4",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1357,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Input", "desc": "Input Widget API\\n\\nInput Widgets are textboxes for typing in specific number values. See \[Drag\], \[Slider\] or \[InputText\](Text#InputText) for more input types.\\n\\nIris provides a set of specific inputs for the datatypes:\\nNumber,\\n\[Vector2\](https://create.roblox.com/docs/reference/engine/datatypes/Vector2),\\n\[Vector3\](https://create.roblox.com/docs/reference/engine/datatypes/Vector3),\\n\[UDim\](https://create.roblox.com/docs/reference/engine/datatypes/UDim),\\n\[UDim2\](https://create.roblox.com/docs/reference/engine/datatypes/UDim2),\\n\[Rect\](https://create.roblox.com/docs/reference/engine/datatypes/Rect),\\n\[Color3\](https://create.roblox.com/docs/reference/engine/datatypes/Color3)\\nand the custom \[Color4\](https://create.roblox.com/docs/reference/engine/datatypes/Color3).\\n\\nEach Input widget has the same arguments but the types depend of the DataType:\\n1. Text: string? = \\"Input{type}\\" -- the text to be displayed to the right of the textbox.\\n2. Increment: DataType? = nil, -- the increment argument determines how a value will be rounded once the textbox looses focus.\\n3. Min: DataType? = nil, -- the minimum value that the widget will allow, no clamping by default.\\n4. Max: DataType? = nil, -- the maximum value that the widget will allow, no clamping by default.\\n5. Format: string | { string }? = \[DYNAMIC\] -- uses \`string.format\` to customise visual display.\\n\\nThe format string can either by a single value which will apply to every box, or a table allowing specific text.\\n\\n:::note\\nIf you do not specify a format option then Iris will dynamically calculate a relevant number of sigifs and format option.\\nFor example, if you have Increment, Min and Max values of 1, 0 and 100, then Iris will guess that you are only using integers\\nand will format the value as an integer.\\nAs another example, if you have Increment, Min and max values of 0.005, 0, 1, then Iris will guess you are using a float of 3\\nsignificant figures.\\n\\nAdditionally, for certain DataTypes, Iris will append an prefix to each box if no format option is provided.\\nFor example, a Vector3 box will have the append values of \\"X: \\", \\"Y: \\" and \\"Z: \\" to the relevant input box.\\n:::\\n ", "source": { "line": 904, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Input#properties) * [InputColor3](https://sirmallard.github.io/Iris/api/Input#InputColor3) * [InputColor4](https://sirmallard.github.io/Iris/api/Input#InputColor4) * [InputNum](https://sirmallard.github.io/Iris/api/Input#InputNum) * [InputRect](https://sirmallard.github.io/Iris/api/Input#InputRect) * [InputUDim](https://sirmallard.github.io/Iris/api/Input#InputUDim) * [InputUDim2](https://sirmallard.github.io/Iris/api/Input#InputUDim2) * [InputVector2](https://sirmallard.github.io/Iris/api/Input#InputVector2) * [InputVector3](https://sirmallard.github.io/Iris/api/Input#InputVector3) --- # Plot | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Plot#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Plot#properties "Direct link to Properties") ------------------------------------------------------------------------------------------------- ### `ProgressBar`[​](https://sirmallard.github.io/Iris/api/Plot#ProgressBar "Direct link to ProgressBar") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1800) `Plot.ProgressBar:` `Iris.ProgressBar` A progress bar line with a state value to show the current state. hasChildren = false hasState = true Arguments = { Text: string? = "Progress Bar", Format: string? = nil -- optional to override with a custom progress such as `29/54` } Events = { hovered: () -> boolean, changed: () -> boolean } States = { progress: State? } ### `PlotLines`[​](https://sirmallard.github.io/Iris/api/Plot#PlotLines "Direct link to PlotLines") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1831) `Plot.PlotLines:` `Iris.PlotLines` A line graph for plotting a single line. Includes hovering to see a specific value on the graph, and automatic scaling. Has an overlay text option at the top of the plot for displaying any information. hasChildren = false hasState = true Arguments = { Text: string? = "Plot Lines", Height: number? = 0, Min: number? = min, -- Iris will use the minimum value from the values Max: number? = max, -- Iris will use the maximum value from the values TextOverlay: string? = "" } Events = { hovered: () -> boolean } States = { values: State<{number}>?, hovered: State<{number}>? -- read-only property } ### `PlotHistogram`[​](https://sirmallard.github.io/Iris/api/Plot#PlotHistogram "Direct link to PlotHistogram") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1863) `Plot.PlotHistogram:` `Iris.PlotHistogram` A hisogram graph for showing values. Includes hovering to see a specific block on the graph, and automatic scaling. Has an overlay text option at the top of the plot for displaying any information. Also supports a baseline option, which determines where the blocks start from. hasChildren = false hasState = true Arguments = { Text: string? = "Plot Histogram", Height: number? = 0, Min: number? = min, -- Iris will use the minimum value from the values Max: number? = max, -- Iris will use the maximum value from the values TextOverlay: string? = "", BaseLine: number? = 0 -- by default, blocks swap side at 0 } Events = { hovered: () -> boolean } States = { values: State<{number}>?, hovered: State<{number}>? -- read-only property } Show raw api { "functions": \[\], "properties": \[\ {\ "name": "ProgressBar",\ "desc": "A progress bar line with a state value to show the current state.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"Progress Bar\\",\\n Format: string? = nil -- optional to override with a custom progress such as \`29/54\`\\n}\\nEvents = {\\n hovered: () -> boolean,\\n changed: () -> boolean\\n}\\nStates = {\\n progress: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.ProgressBar",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1800,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "PlotLines",\ "desc": "A line graph for plotting a single line. Includes hovering to see a specific value on the graph,\\nand automatic scaling. Has an overlay text option at the top of the plot for displaying any\\ninformation.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"Plot Lines\\",\\n Height: number? = 0,\\n Min: number? = min, -- Iris will use the minimum value from the values\\n Max: number? = max, -- Iris will use the maximum value from the values\\n TextOverlay: string? = \\"\\"\\n}\\nEvents = {\\n hovered: () -> boolean\\n}\\nStates = {\\n values: State<{number}>?,\\n hovered: State<{number}>? -- read-only property\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.PlotLines",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1831,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "PlotHistogram",\ "desc": "A hisogram graph for showing values. Includes hovering to see a specific block on the graph,\\nand automatic scaling. Has an overlay text option at the top of the plot for displaying any\\ninformation. Also supports a baseline option, which determines where the blocks start from.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"Plot Histogram\\",\\n Height: number? = 0,\\n Min: number? = min, -- Iris will use the minimum value from the values\\n Max: number? = max, -- Iris will use the maximum value from the values\\n TextOverlay: string? = \\"\\",\\n BaseLine: number? = 0 -- by default, blocks swap side at 0\\n}\\nEvents = {\\n hovered: () -> boolean\\n}\\nStates = {\\n values: State<{number}>?,\\n hovered: State<{number}>? -- read-only property\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.PlotHistogram",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1863,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Plot", "desc": "Plot Widget API\\n ", "source": { "line": 1775, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Plot#properties) * [PlotHistogram](https://sirmallard.github.io/Iris/api/Plot#PlotHistogram) * [PlotLines](https://sirmallard.github.io/Iris/api/Plot#PlotLines) * [ProgressBar](https://sirmallard.github.io/Iris/api/Plot#ProgressBar) --- # Menu | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Menu#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Menu#properties "Direct link to Properties") ------------------------------------------------------------------------------------------------- ### `MenuBar`[​](https://sirmallard.github.io/Iris/api/Menu#MenuBar "Direct link to MenuBar") WidgetHasChildren [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L142) `Menu.MenuBar:` `Iris.MenuBar` Creates a MenuBar for the current window. Must be called directly under a Window and not within a child widget. ##### INFO This does not create any menus, just tells the window that we going to add menus within. hasChildren = true hasState = false ### `Menu`[​](https://sirmallard.github.io/Iris/api/Menu#Menu "Direct link to Menu") WidgetHasChildrenHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L192) `Menu.Menu:` `Iris.Menu` Creates an collapsable menu. If the Menu is created directly under a MenuBar, then the widget will be placed horizontally below the window title. If the menu Menu is created within another menu, then it will be placed vertically alongside MenuItems and display an arrow alongside. The opened menu will be a vertically listed box below or next to the button. Iris.Window({"Menu Demo"}) Iris.MenuBar() Iris.Menu({"Test Menu"}) Iris.Button({"Menu Option 1"}) Iris.Button({"Menu Option 2"}) Iris.End() Iris.End() Iris.End() ![Example menu](https://sirmallard.github.io/Iris/assets/api/menu/basicMenu.gif) ##### INFO There are widgets which are designed for being parented to a menu whilst other happens to work. There is nothing preventing you from adding any widget as a child, but the behaviour is unexplained and not intended. hasChildren = true hasState = true Arguments = { Text: string -- menu text. } Events = { clicked: () -> boolean, opened: () -> boolean, -- once when opened. closed: () -> boolean, -- once when closed. hovered: () -> boolean } States = { isOpened: State? -- whether the menu is open, including any sub-menus within. } ### `MenuItem`[​](https://sirmallard.github.io/Iris/api/Menu#MenuItem "Direct link to MenuItem") Widget [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L226) `Menu.MenuItem:` `Iris.MenuItem` Creates a button within a menu. The optional KeyCode and ModiferKey arguments will show the keys next to the title, but **will not** bind any connection to them. You will need to do this yourself. Iris.Window({"MenuToggle Demo"}) Iris.MenuBar() Iris.MenuToggle({"Menu Item"}) Iris.End() Iris.End() ![Example Menu Item](https://sirmallard.github.io/Iris/assets/api/menu/basicMenuItem.gif) hasChildren = false hasState = false Arguments = { Text: string, KeyCode: Enum.KeyCode? = nil, -- an optional keycode, does not actually connect an event. ModifierKey: Enum.ModifierKey? = nil -- an optional modifer key for the key code. } Events = { clicked: () -> boolean, hovered: () -> boolean } ### `MenuToggle`[​](https://sirmallard.github.io/Iris/api/Menu#MenuToggle "Direct link to MenuToggle") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L265) `Menu.MenuToggle:` `Iris.MenuToggle` Creates a togglable button within a menu. The optional KeyCode and ModiferKey arguments act the same as the MenuItem. It is not visually the same as a checkbox, but has the same functionality. Iris.Window({"MenuToggle Demo"}) Iris.MenuBar() Iris.MenuToggle({"Menu Toggle"}) Iris.End() Iris.End() ![Example Menu Toggle](https://sirmallard.github.io/Iris/assets/api/menu/basicMenuToggle.gif) hasChildren = false hasState = true Arguments = { Text: string, KeyCode: Enum.KeyCode? = nil, -- an optional keycode, does not actually connect an event. ModifierKey: Enum.ModifierKey? = nil -- an optional modifer key for the key code. } Events = { checked: () -> boolean, -- once on check. unchecked: () -> boolean, -- once on uncheck. hovered: () -> boolean } States = { isChecked: State? } Show raw api { "functions": \[\], "properties": \[\ {\ "name": "MenuBar",\ "desc": "Creates a MenuBar for the current window. Must be called directly under a Window and not within a child widget.\\n:::info\\n This does not create any menus, just tells the window that we going to add menus within.\\n:::\\n\\n\`\`\`lua\\nhasChildren = true\\nhasState = false\\n\`\`\`\\n ",\ "lua\_type": "Iris.MenuBar",\ "tags": \[\ "Widget",\ "HasChildren"\ \],\ "source": {\ "line": 142,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "Menu",\ "desc": "Creates an collapsable menu. If the Menu is created directly under a MenuBar, then the widget will\\nbe placed horizontally below the window title. If the menu Menu is created within another menu, then\\nit will be placed vertically alongside MenuItems and display an arrow alongside.\\n\\nThe opened menu will be a vertically listed box below or next to the button.\\n\\n\`\`\`lua\\n Iris.Window({\\"Menu Demo\\"})\\n Iris.MenuBar()\\n Iris.Menu({\\"Test Menu\\"})\\n Iris.Button({\\"Menu Option 1\\"})\\n Iris.Button({\\"Menu Option 2\\"})\\n Iris.End()\\n Iris.End()\\n Iris.End()\\n\`\`\`\\n\\n!\[Example menu\](/Iris/assets/api/menu/basicMenu.gif)\\n\\n:::info\\nThere are widgets which are designed for being parented to a menu whilst other happens to work. There is nothing\\npreventing you from adding any widget as a child, but the behaviour is unexplained and not intended.\\n:::\\n\\n\`\`\`lua\\nhasChildren = true\\nhasState = true\\nArguments = {\\n Text: string -- menu text.\\n}\\nEvents = {\\n clicked: () -> boolean,\\n opened: () -> boolean, -- once when opened.\\n closed: () -> boolean, -- once when closed.\\n hovered: () -> boolean\\n}\\nStates = {\\n isOpened: State? -- whether the menu is open, including any sub-menus within.\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Menu",\ "tags": \[\ "Widget",\ "HasChildren",\ "HasState"\ \],\ "source": {\ "line": 192,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "MenuItem",\ "desc": "Creates a button within a menu. The optional KeyCode and ModiferKey arguments will show the keys next\\nto the title, but \*\*will not\*\* bind any connection to them. You will need to do this yourself.\\n\\n\`\`\`lua\\nIris.Window({\\"MenuToggle Demo\\"})\\n Iris.MenuBar()\\n Iris.MenuToggle({\\"Menu Item\\"})\\n Iris.End()\\nIris.End()\\n\`\`\`\\n\\n!\[Example Menu Item\](/Iris/assets/api/menu/basicMenuItem.gif)\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = false\\nArguments = {\\n Text: string,\\n KeyCode: Enum.KeyCode? = nil, -- an optional keycode, does not actually connect an event.\\n ModifierKey: Enum.ModifierKey? = nil -- an optional modifer key for the key code.\\n}\\nEvents = {\\n clicked: () -> boolean,\\n hovered: () -> boolean\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.MenuItem",\ "tags": \[\ "Widget"\ \],\ "source": {\ "line": 226,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "MenuToggle",\ "desc": "Creates a togglable button within a menu. The optional KeyCode and ModiferKey arguments act the same\\nas the MenuItem. It is not visually the same as a checkbox, but has the same functionality.\\n\\n\`\`\`lua\\nIris.Window({\\"MenuToggle Demo\\"})\\n Iris.MenuBar()\\n Iris.MenuToggle({\\"Menu Toggle\\"})\\n Iris.End()\\nIris.End()\\n\`\`\`\\n\\n!\[Example Menu Toggle\](/Iris/assets/api/menu/basicMenuToggle.gif)\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string,\\n KeyCode: Enum.KeyCode? = nil, -- an optional keycode, does not actually connect an event.\\n ModifierKey: Enum.ModifierKey? = nil -- an optional modifer key for the key code.\\n}\\nEvents = {\\n checked: () -> boolean, -- once on check.\\n unchecked: () -> boolean, -- once on uncheck.\\n hovered: () -> boolean\\n}\\nStates = {\\n isChecked: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.MenuToggle",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 265,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Menu", "desc": "Menu API\\n ", "source": { "line": 125, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Menu#properties) * [Menu](https://sirmallard.github.io/Iris/api/Menu#Menu) * [MenuBar](https://sirmallard.github.io/Iris/api/Menu#MenuBar) * [MenuItem](https://sirmallard.github.io/Iris/api/Menu#MenuItem) * [MenuToggle](https://sirmallard.github.io/Iris/api/Menu#MenuToggle) --- # Slider | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Slider#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Slider#properties "Direct link to Properties") --------------------------------------------------------------------------------------------------- ### `SliderNum`[​](https://sirmallard.github.io/Iris/api/Slider#SliderNum "Direct link to SliderNum") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1403) `Slider.SliderNum:` `Iris.SliderNum` A field which allows the user to slide a grip to enter a number within a range. You can ctrl + click to directly input a number, like InputNum. hasChildren = false hasState = true Arguments = { Text: string? = "SliderNum", Increment: number? = 1, Min: number? = 0, Max: number? = 100, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `SliderVector2`[​](https://sirmallard.github.io/Iris/api/Slider#SliderVector2 "Direct link to SliderVector2") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1434) `Slider.SliderVector2:` `Iris.SliderVector2` A field which allows the user to slide a grip to enter a Vector2 within a range. You can ctrl + click to directly input a Vector2, like InputVector2. hasChildren = false hasState = true Arguments = { Text: string? = "SliderVector2", Increment: Vector2? = { 1, 1 }, Min: Vector2? = { 0, 0 }, Max: Vector2? = { 100, 100 }, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `SliderVector3`[​](https://sirmallard.github.io/Iris/api/Slider#SliderVector3 "Direct link to SliderVector3") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1465) `Slider.SliderVector3:` `Iris.SliderVector3` A field which allows the user to slide a grip to enter a Vector3 within a range. You can ctrl + click to directly input a Vector3, like InputVector3. hasChildren = false hasState = true Arguments = { Text: string? = "SliderVector3", Increment: Vector3? = { 1, 1, 1 }, Min: Vector3? = { 0, 0, 0 }, Max: Vector3? = { 100, 100, 100 }, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `SliderUDim`[​](https://sirmallard.github.io/Iris/api/Slider#SliderUDim "Direct link to SliderUDim") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1496) `Slider.SliderUDim:` `Iris.SliderUDim` A field which allows the user to slide a grip to enter a UDim within a range. You can ctrl + click to directly input a UDim, like InputUDim. hasChildren = false hasState = true Arguments = { Text: string? = "SliderUDim", Increment: UDim? = { 0.01, 1 }, Min: UDim? = { 0, 0 }, Max: UDim? = { 1, 960 }, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `SliderUDim2`[​](https://sirmallard.github.io/Iris/api/Slider#SliderUDim2 "Direct link to SliderUDim2") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1527) `Slider.SliderUDim2:` `Iris.SliderUDim2` A field which allows the user to slide a grip to enter a UDim2 within a range. You can ctrl + click to directly input a UDim2, like InputUDim2. hasChildren = false hasState = true Arguments = { Text: string? = "SliderUDim2", Increment: UDim2? = { 0.01, 1, 0.01, 1 }, Min: UDim2? = { 0, 0, 0, 0 }, Max: UDim2? = { 1, 960, 1, 960 }, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } ### `SliderRect`[​](https://sirmallard.github.io/Iris/api/Slider#SliderRect "Direct link to SliderRect") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1558) `Slider.SliderRect:` `Iris.SliderRect` A field which allows the user to slide a grip to enter a Rect within a range. You can ctrl + click to directly input a Rect, like InputRect. hasChildren = false hasState = true Arguments = { Text: string? = "SliderRect", Increment: Rect? = { 1, 1, 1, 1 }, Min: Rect? = { 0, 0, 0, 0 }, Max: Rect? = { 960, 960, 960, 960 }, Format: string? | { string }? = [DYNAMIC] -- Iris will dynamically generate an approriate format. } Events = { numberChanged: () -> boolean, hovered: () -> boolean } States = { number: State?, editingText: State? } Show raw api { "functions": \[\], "properties": \[\ {\ "name": "SliderNum",\ "desc": "A field which allows the user to slide a grip to enter a number within a range.\\nYou can ctrl + click to directly input a number, like InputNum.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"SliderNum\\",\\n Increment: number? = 1,\\n Min: number? = 0,\\n Max: number? = 100,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.SliderNum",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1403,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "SliderVector2",\ "desc": "A field which allows the user to slide a grip to enter a Vector2 within a range.\\nYou can ctrl + click to directly input a Vector2, like InputVector2.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"SliderVector2\\",\\n Increment: Vector2? = { 1, 1 },\\n Min: Vector2? = { 0, 0 },\\n Max: Vector2? = { 100, 100 },\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.SliderVector2",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1434,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "SliderVector3",\ "desc": "A field which allows the user to slide a grip to enter a Vector3 within a range.\\nYou can ctrl + click to directly input a Vector3, like InputVector3.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"SliderVector3\\",\\n Increment: Vector3? = { 1, 1, 1 },\\n Min: Vector3? = { 0, 0, 0 },\\n Max: Vector3? = { 100, 100, 100 },\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.SliderVector3",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1465,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "SliderUDim",\ "desc": "A field which allows the user to slide a grip to enter a UDim within a range.\\nYou can ctrl + click to directly input a UDim, like InputUDim.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"SliderUDim\\",\\n Increment: UDim? = { 0.01, 1 },\\n Min: UDim? = { 0, 0 },\\n Max: UDim? = { 1, 960 },\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.SliderUDim",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1496,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "SliderUDim2",\ "desc": "A field which allows the user to slide a grip to enter a UDim2 within a range.\\nYou can ctrl + click to directly input a UDim2, like InputUDim2.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"SliderUDim2\\",\\n Increment: UDim2? = { 0.01, 1, 0.01, 1 },\\n Min: UDim2? = { 0, 0, 0, 0 },\\n Max: UDim2? = { 1, 960, 1, 960 },\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.SliderUDim2",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1527,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "SliderRect",\ "desc": "A field which allows the user to slide a grip to enter a Rect within a range.\\nYou can ctrl + click to directly input a Rect, like InputRect.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"SliderRect\\",\\n Increment: Rect? = { 1, 1, 1, 1 },\\n Min: Rect? = { 0, 0, 0, 0 },\\n Max: Rect? = { 960, 960, 960, 960 },\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.SliderRect",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 1558,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "InputEnum",\ "desc": "A field which allows the user to slide a grip to enter a number within a range.\\nYou can ctrl + click to directly input a number, like InputNum.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"InputEnum\\",\\n Increment: number? = 1,\\n Min: number? = 0,\\n Max: number? = 100,\\n Format: string? | { string }? = \[DYNAMIC\] -- Iris will dynamically generate an approriate format.\\n}\\nEvents = {\\n numberChanged: () -> boolean,\\n hovered: () -> boolean\\n}\\nStates = {\\n number: State?,\\n editingText: State?,\\n enumItem: EnumItem\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.InputEnum",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "private": true,\ "source": {\ "line": 1764,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Slider", "desc": "Slider Widget API\\n\\nA draggable widget with a visual bar constrained between a min and max for each datatype.\\nAllows direct typing input but also dragging the slider by clicking and holding anywhere in the box.\\n\\nSee \[Input\] for more details on the arguments.\\n ", "source": { "line": 1373, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Slider#properties) * [SliderNum](https://sirmallard.github.io/Iris/api/Slider#SliderNum) * [SliderRect](https://sirmallard.github.io/Iris/api/Slider#SliderRect) * [SliderUDim](https://sirmallard.github.io/Iris/api/Slider#SliderUDim) * [SliderUDim2](https://sirmallard.github.io/Iris/api/Slider#SliderUDim2) * [SliderVector2](https://sirmallard.github.io/Iris/api/Slider#SliderVector2) * [SliderVector3](https://sirmallard.github.io/Iris/api/Slider#SliderVector3) --- # State | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/State#__docusaurus_skipToContent_fallback) On this page Types[​](https://sirmallard.github.io/Iris/api/State#types "Direct link to Types") ----------------------------------------------------------------------------------- ### `State`[​](https://sirmallard.github.io/Iris/api/State#State%3CT%3E "Direct link to State") [](https://github.com/SirMallard/Iris/blob/main/lib/WidgetTypes.lua#L11) `type` `State =` `{` `ID:` `[ID](https://sirmallard.github.io/Iris/api/Iris#ID) ``,` `value:` `T``,` `get:` `(``self``)` `→` `T``,` `set:` `(` `self``,` `newValue:` `T` `)` `→` `T``,` `onChange:` `(` `self``,` `callback:` `(``newValue:` `T``)` `→` `(``)` `)` `→` `(``)``,` `ConnectedWidgets:` `{``[``[ID](https://sirmallard.github.io/Iris/api/Iris#ID) ``]``:` `[Widget](https://sirmallard.github.io/Iris/api/Iris#Widget) ``}``,` `ConnectedFunctions:` `{``(``newValue:` `T``)` `→` `(``)``}` `}` Functions[​](https://sirmallard.github.io/Iris/api/State#functions "Direct link to Functions") ----------------------------------------------------------------------------------------------- ### `get`[​](https://sirmallard.github.io/Iris/api/State#get%3CT%3E "Direct link to get") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L131) `State:``get``(``) →` `T` Returns the states current value. ### `set`[​](https://sirmallard.github.io/Iris/api/State#set%3CT%3E "Direct link to set") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L144) `State:``set``(` `newValue:` `T``,` `force:` `boolean?`\-- force an update to all connections `) →` `T` Allows the caller to assign the state object a new value, and returns the new value. ### `onChange`[​](https://sirmallard.github.io/Iris/api/State#onChange%3CT%3E "Direct link to onChange") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L176) `State:``onChange``(``callback:` `(``newValue:` `T``)` `→` `(``)``) →` `(``)` `→` `(``)` Allows the caller to connect a callback which is called when the states value is changed. ##### Caution: Single Calling `:onChange()` every frame will add a new function every frame. You must ensure you are only calling `:onChange()` once for each callback for the state's entire lifetime. ### `changed`[​](https://sirmallard.github.io/Iris/api/State#changed%3CT%3E "Direct link to changed") [](https://github.com/SirMallard/Iris/blob/main/lib/Internal.lua#L191) `State:``changed``(``) →` `boolean` Returns true if the state was changed on this frame. Show raw api { "functions": \[\ {\ "name": "get",\ "desc": "Returns the states current value.\\n ",\ "params": \[\],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "T"\ }\ \],\ "function\_type": "method",\ "source": {\ "line": 131,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "set",\ "desc": "Allows the caller to assign the state object a new value, and returns the new value.\\n ",\ "params": \[\ {\ "name": "newValue",\ "desc": "",\ "lua\_type": "T"\ },\ {\ "name": "force",\ "desc": "force an update to all connections",\ "lua\_type": "boolean?"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "T"\ }\ \],\ "function\_type": "method",\ "source": {\ "line": 144,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "onChange",\ "desc": "Allows the caller to connect a callback which is called when the states value is changed.\\n\\n:::caution Caution: Single\\nCalling \`:onChange()\` every frame will add a new function every frame.\\nYou must ensure you are only calling \`:onChange()\` once for each callback for the state's entire lifetime.\\n:::\\n ",\ "params": \[\ {\ "name": "callback",\ "desc": "",\ "lua\_type": "(newValue: T) -> ()"\ }\ \],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "() -> ()"\ }\ \],\ "function\_type": "method",\ "source": {\ "line": 176,\ "path": "lib/Internal.lua"\ }\ },\ {\ "name": "changed",\ "desc": "Returns true if the state was changed on this frame.\\n ",\ "params": \[\],\ "returns": \[\ {\ "desc": "",\ "lua\_type": "boolean"\ }\ \],\ "function\_type": "method",\ "source": {\ "line": 191,\ "path": "lib/Internal.lua"\ }\ }\ \], "properties": \[\], "types": \[\ {\ "name": "State",\ "desc": "",\ "lua\_type": "{ ID: ID, value: T, get: (self) -> T, set: (self, newValue: T) -> T, onChange: (self, callback: (newValue: T) -> ()) -> (), ConnectedWidgets: { \[ID\]: Widget }, ConnectedFunctions: { (newValue: T) -> () } }",\ "source": {\ "line": 11,\ "path": "lib/WidgetTypes.lua"\ }\ }\ \], "name": "State", "desc": "This class wraps a value in getters and setters, its main purpose is to allow primatives to be passed as objects.\\nConstructors for this class are available in \[Iris\]\\n\\n\`\`\`lua\\nlocal state = Iris.State(0) -- we initialise the state with a value of 0\\n\\n-- these are equivalent. Ideally you should use \`:get()\` and ignore \`.value\`.\\nprint(state:get())\\nprint(state.value)\\n\\nstate:set(state:get() + 1) -- increments the state by getting the current value and adding 1.\\n\\nstate:onChange(function(newValue)\\n print(\`The value of the state is now: {newValue}\`)\\nend)\\n\`\`\`\\n\\n:::caution Caution: Callbacks\\nNever call \`:set()\` on a state when inside the \`:onChange()\` callback of the same state. This will cause a continous callback.\\n\\nNever chain states together so that each state changes the value of another state in a cyclic nature. This will cause a continous callback.\\n:::\\n ", "source": { "line": 121, "path": "lib/Internal.lua" } } * [Types](https://sirmallard.github.io/Iris/api/State#types) * [State](https://sirmallard.github.io/Iris/api/State#State%3CT%3E) * [Functions](https://sirmallard.github.io/Iris/api/State#functions) * [:changed](https://sirmallard.github.io/Iris/api/State#changed%3CT%3E) * [:get](https://sirmallard.github.io/Iris/api/State#get%3CT%3E) * [:onChange](https://sirmallard.github.io/Iris/api/State#onChange%3CT%3E) * [:set](https://sirmallard.github.io/Iris/api/State#set%3CT%3E) --- # Understanding Widgets | Iris [Skip to main content](https://sirmallard.github.io/Iris/docs/about/widgets#__docusaurus_skipToContent_fallback) On this page An Iris widget is simply a table (or struct) of data. At its most basic, a widget contains only its ID, type, tick, events, arguments, zindex, parent widget and gui instance. None of the functionality of a widget is contained in the widget object. Instead, Iris uses a factory pattern for a widget class whereby the changes are applied onto any widget passed to the function. Creating a Widget Class[​](https://sirmallard.github.io/Iris/docs/about/widgets#creating-a-widget-class "Direct link to Creating a Widget Class") -------------------------------------------------------------------------------------------------------------------------------------------------- To declare or construct a widget we create a 'widget class', that is, the functions which take in a widget and make changes to it. This widget class is where all the functionality of a a widget is added and therefore needs to be declared or constucted in advance. The class widget is itself a table of data and functions but conforming to a specification which includes the necessary functions for operation. To create a widget class, use the `WidgetConstructor: (type: string, widgetClass: WidgetClass) -> ()` function in `Iris.Internal`. This takes two arguments, a type for the widget, such as Text, InputVector2 or SameLine, and a widget class table, containing the functions. This WidgetClass is defined as: export type WidgetClass = { -- Required Generate: (thisWidget: Widget) -> GuiObject, Discard: (thisWidget: Widget) -> (), Update: (thisWidget: Widget, ...any) -> (), Args: { [string]: number }, Events: Events, hasChildren: boolean, hasState: boolean, -- Generated on construction ArgNames: { [number]: string }, -- Required for widgets with state GenerateState: (thisWidget: Widget) -> (), UpdateState: (thisWidget: Widget) -> (), -- Required for widgets with children ChildAdded: (thisWidget: Widget, thisChild: Widget) -> GuiObject, -- Optional for widgets with children ChildDiscarded: (thisWidget: Widget, thisChild: Widget) -> (),} Here, some of the functions are required for all widgets, which define what to do when the widget is first created, when it is destroyed or discarded because it is no longer called and when any arguments provided to it are updated. And others are only needed if the widget has state or has children. Understanding the Widget Lifecycle[​](https://sirmallard.github.io/Iris/docs/about/widgets#understanding-the-widget-lifecycle "Direct link to Understanding the Widget Lifecycle") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When a widget is called, Iris will try to find the widget from the preivous frame using a VDOM table and an ID dependent on the line it was called from. If the widget was called for the first time, then Iris must generate a new widget. It does this by firstly generating the widget structure, being a table with a few properties. It then generates the UI instances, by calling the `Generate` function of the widget class. Iris will then use the parent of the widget and call the `ChildAdded` function of the parent widget class which tells Iris where to parent the UI instances to. At this point, the new widget looks the same as a pre-existing one. Iris then checks the arguments provided to determine if they have changed. If they have, then Iris will call 'Update' from the widget class which handles any UI changes needed. At this point, the widget is ready, with a functioning UI and can be placed correctly. And that is the end of the call. At the end of the frame, if Iris finds any widgets which were not called in that frame, it will call the `Discard` function which is essentially designed to destroy the UI instances. Required[​](https://sirmallard.github.io/Iris/docs/about/widgets#required "Direct link to Required") ----------------------------------------------------------------------------------------------------- Every widget class must have a `Generate`, `Discard` and `Update` function, an `Args` and `Events` table and `hasChildren` and `hasState` value. Generally we define whether the widget will have children or have state first since this affects any other functions needed for the class. ### Args[​](https://sirmallard.github.io/Iris/docs/about/widgets#args "Direct link to Args") Args is a string-indexed table where each possible argument for a widget is given an index, which corresponds to the index when calling the widget. Therefore, we specify every argument, but do not give a type, or default value. An example for Window and Button are shown below: -- Button argumentsArgs = { ["Text"] = 1, ["Size"] = 2,} -- Window argumentsArgs = { ["Title"] = 1, ["NoTitleBar"] = 2, ["NoBackground"] = 3, ["NoCollapse"] = 4, ["NoClose"] = 5, ["NoMove"] = 6, ["NoScrollbar"] = 7, ["NoResize"] = 8, ["NoNav"] = 9, ["NoMenu"] = 10,} ### Events[​](https://sirmallard.github.io/Iris/docs/about/widgets#events "Direct link to Events") Events are used to query the current state of a widget. For a button, it might be the whether it has been clicked. For a checkbox, whether it is active or for a window whether it is open. All of these are defined to be custom in Iris and called like regular functions on a widget. To do this, we specify a table containing all of the possible events. Each event is a string index for a table conaining to functions: an `Init` function, to setup any prerequisites; and a `Get` function, which returns the value when the event is called. Because some events are so common, such as `hovered()` and `clicked()`, Iris provides shorthands for these, making them easier to add to any widget. If we look at the example Window widget events, we'll see the two common ways: Events = { ["closed"] = { ["Init"] = function(_thisWidget: Types.Window) end, ["Get"] = function(thisWidget: Types.Window) return thisWidget.lastClosedTick == Iris._cycleTick end, }, ["opened"] = { ["Init"] = function(_thisWidget: Types.Window) end, ["Get"] = function(thisWidget: Types.Window) return thisWidget.lastOpenedTick == Iris._cycleTick end, }, ["collapsed"] = { ["Init"] = function(_thisWidget: Types.Window) end, ["Get"] = function(thisWidget: Types.Window) return thisWidget.lastCollapsedTick == Iris._cycleTick end, }, ["uncollapsed"] = { ["Init"] = function(_thisWidget: Types.Window) end, ["Get"] = function(thisWidget: Types.Window) return thisWidget.lastUncollapsedTick == Iris._cycleTick end, }, ["hovered"] = widgets.EVENTS.hover(function(thisWidget: Types.Widget) local Window = thisWidget.Instance :: Frame return Window.WindowButton end),} The hovered event here used a macro utility, which takes a function that returns the Instance to check for hovering on. It then sets up the `MouseHover` events for us, and returns the two functions so that th event is setup correctly. This is the easiest way, since we only need to provide the UI Instance. The other events are added manually. They each work by checking whether an event has fired on this tick. Elsewhere in the code for the Window widget, these tick variables are set when an event happens. For example, in the code which checks for a click on the window collapse button, it will update the tick variable to the next cycle, ensuring that the event fires when all of the UI changes. Most of the time, you can the existing examples from other widgets. ### hasChildren[​](https://sirmallard.github.io/Iris/docs/about/widgets#haschildren "Direct link to hasChildren") If your widget is going to be a parent and therefore have other widgets placed within or under it, like a Window, Tree or SameLine widget, this must be true. If not, it must be specified as false. ### hasState[​](https://sirmallard.github.io/Iris/docs/about/widgets#hasstate "Direct link to hasState") If your widget will take in valuse and possibliy modify them in the widget and return them back, then the widget will use state objects and therefore must be set to true. Otherwise it must be sepcified as false. ### Generate[​](https://sirmallard.github.io/Iris/docs/about/widgets#generate "Direct link to Generate") The `Generate` function is called whenever a widget is first called and is responsible for creating the actual UI instances that make up the window. It handles all of the styling but does not use the widget arguments (this is hande=led in the `Update` function). Any widget interactivity such as events for clicks or hovers, which may also change the style, are setup in here. There area few rules which the generated UI instances follow: 1. The root instance should be named "Iris\_\[WIDGET\_TYPE\]". 2. The ZIndex and LayoutOrder of the root element are taken from the ZIndex property of the widget. 3. Returns the root instance. 4. Widgets are generally sized using AutomaticSize or the config over hard-coded numbers, and therefore scale better 5. The arguments are never used to modify any instances because if the arguments change then the widget should be able to handle the changes on existing UI rather than creating a new design. The code of a Button best demonstrates this: Generate = function(thisWidget: Types.Button) -- a TextButton is the best option here because it has the correct events local Button: TextButton = Instance.new("TextButton") -- we rely on auomatic size Button.Size = UDim2.fromOfset(0, 0) -- using the config values Button.BackgroundColor3 = Iris._config.ButtonColor Button.BackgroundTransparency = Iris._config.ButtonTransparency Button.AutoButtonColor = false Button.AutomaticSize = Enum.AutomaticSize.XY -- utility functions exist such as this one which correctly sets the text -- style for the widget widgets.applyTextStyle(Button) Button.TextXAlignment = Enum.TextXAlignment.Center -- another utility function which adds any borders or padding dependent -- on the config widgets.applyFrameStyle(Button) -- an utility event which uses clicks and hovers to colour the button -- when the mouse interacts with it: normal, hovered and clicked widgets.applyInteractionHighlights("Background", Button, Button, { Color = Iris._config.ButtonColor, Transparency = Iris._config.ButtonTransparency, HoveredColor = Iris._config.ButtonHoveredColor, HoveredTransparency = Iris._config.ButtonHoveredTransparency, ActiveColor = Iris._config.ButtonActiveColor, ActiveTransparency = Iris._config.ButtonActiveTransparency, }) -- set the correct layout order and zindex to ensure it stays in the -- correct order. Iris relies heavily on UIListLayouts to automatically -- position the UI, and therefore relies on the LayoutOrder property. Button.ZIndex = thisWidget.ZIndex Button.LayoutOrder = thisWidget.ZIndex -- we finally return the instance, which is correctly parented and -- Iris sets the widget.instance property to this root element return Buttonend, ### Discard[​](https://sirmallard.github.io/Iris/docs/about/widgets#discard "Direct link to Discard") Discard is called whenever the widget is about to be destroyed because it has not been called this frame. It hsould remove any instances used by the widget. Most of the time, it is possible to just destroy the root Instance of the widget, which will close any connections and remove all child instances. If a widget has any state objects, you will also need to call the `discardState()` function in the widget utility library, which removes any connected states from the widget, allowing the widget to be correctly cleaned up. ### Update[​](https://sirmallard.github.io/Iris/docs/about/widgets#update "Direct link to Update") Update is used to alter the widget dependent on the provided arguments. Since the arguments can change every frame, Iris will call `Update` whenever these arguments change, and when the widget is first created. Within Generate, all possible instances that are used by the widget are created. `Update` is used to determine which ones are visible and the style of them. For example, the Text argument of a widget can be updated dynamically, by simply changing the Text value for the UI Instance. State[​](https://sirmallard.github.io/Iris/docs/about/widgets#state "Direct link to State") -------------------------------------------------------------------------------------------- These functions are both required for any widget which has a state. ### GenerateState[​](https://sirmallard.github.io/Iris/docs/about/widgets#generatestate "Direct link to GenerateState") GenerateState will create all of the state objects used by that widget, if they are not provided by the user. It is called only once, when the widget is first created. Creating a new state is not just creating the object, but also linking it to the widget, so that when the state changes, it updates the widget. We can use an example to demonstrate the macro function that Iris provides to make this easier, as shown in the Checkbox widget: GenerateState = function(thisWidget: Types.Checkbox) if thisWidget.state.isChecked == nil then thisWidget.state.isChecked = Iris._widgetState(thisWidget, "checked", false) endend We first check whether the state already exists. If it doesn't we can use the `Iris._widgetState()` function which will construct a new state for this widget with a given name and default value. We can therefore give the states their default values here. Within `Iris._widgetState()`, we create a new state object and add this widget to its internal table of all connected widgets, and then return the new state. Since `GenerateState` is called only once, we can also use it to connect any widget states together using the `:onChange()` connection. ### UpdateState[​](https://sirmallard.github.io/Iris/docs/about/widgets#updatestate "Direct link to UpdateState") UpdateState is the equivalent to `Update`, but for state. If any state object connected to this widget is updated, then this will be called, which handles all of the UI changes. This is also called once at widget creation, to properly design the UI before it is first shown. note Any changes to UI due to state should be handled here, and not in the code which updates the state. For example, if you have a click event within `GenerateState`, such as for a checkbox, which changes the state, the code within `UpdateState` should change the UI, such as show a tick, rather than handling it in `GenerateState`. Children[​](https://sirmallard.github.io/Iris/docs/about/widgets#children "Direct link to Children") ----------------------------------------------------------------------------------------------------- These functions are used if a widget has children. Only `ChildAdded` is required. ### ChildAdded[​](https://sirmallard.github.io/Iris/docs/about/widgets#childadded "Direct link to ChildAdded") ChildAdded returns the UI instance which the child widget should be parented to. For most functions, it just returns this Instance. However, it is also possible to validate that the child widget is a certain type, such as only Menus under a MenuBar. You can also update any UI behaviour which may depend on the number of children, such as a container height. ### ChildDiscarded[​](https://sirmallard.github.io/Iris/docs/about/widgets#childdiscarded "Direct link to ChildDiscarded") ChildDiscarded is optional, and is only necessary when the removal of a child needs to update the parent widget in some way, such as changing the size. Calling a Widget[​](https://sirmallard.github.io/Iris/docs/about/widgets#calling-a-widget "Direct link to Calling a Widget") ----------------------------------------------------------------------------------------------------------------------------- We have constructed our widget class, but need to know how to call it. We use the `_Insert` API under `Iris.Internal`: `_Insert: (widgetType: string, arguments: WidgetArguments?, states: WidgetStates?) -> Widget`. We provide the widgetType, as specified in the constructor, and then arguments and states. For example, we can create a Text widget by calling: Iris.Internal._Insert("Text", { "Text label" }) We create an alias for these functions under `Iris` directly, which is why the user does not call this function directly. * [Creating a Widget Class](https://sirmallard.github.io/Iris/docs/about/widgets#creating-a-widget-class) * [Understanding the Widget Lifecycle](https://sirmallard.github.io/Iris/docs/about/widgets#understanding-the-widget-lifecycle) * [Required](https://sirmallard.github.io/Iris/docs/about/widgets#required) * [Args](https://sirmallard.github.io/Iris/docs/about/widgets#args) * [Events](https://sirmallard.github.io/Iris/docs/about/widgets#events) * [hasChildren](https://sirmallard.github.io/Iris/docs/about/widgets#haschildren) * [hasState](https://sirmallard.github.io/Iris/docs/about/widgets#hasstate) * [Generate](https://sirmallard.github.io/Iris/docs/about/widgets#generate) * [Discard](https://sirmallard.github.io/Iris/docs/about/widgets#discard) * [Update](https://sirmallard.github.io/Iris/docs/about/widgets#update) * [State](https://sirmallard.github.io/Iris/docs/about/widgets#state) * [GenerateState](https://sirmallard.github.io/Iris/docs/about/widgets#generatestate) * [UpdateState](https://sirmallard.github.io/Iris/docs/about/widgets#updatestate) * [Children](https://sirmallard.github.io/Iris/docs/about/widgets#children) * [ChildAdded](https://sirmallard.github.io/Iris/docs/about/widgets#childadded) * [ChildDiscarded](https://sirmallard.github.io/Iris/docs/about/widgets#childdiscarded) * [Calling a Widget](https://sirmallard.github.io/Iris/docs/about/widgets#calling-a-widget) --- # Tab | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Tab#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Tab#properties "Direct link to Properties") ------------------------------------------------------------------------------------------------ ### `TabBar`[​](https://sirmallard.github.io/Iris/api/Tab#TabBar "Direct link to TabBar") WidgetHasChildrenHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L825) `Tab.TabBar:` `Iris.TabBar` Creates a TabBar for putting tabs under. This does not create the tabs but just the container for them to be in. The index state is used to control the current tab and is based on an index starting from 1 rather than the text provided to a Tab. The TabBar will replicate the index to the Tab children . hasChildren: true hasState: true Arguments = {} Events = {} State = { index: State? -- whether the widget is collapsed. } ### `Tab`[​](https://sirmallard.github.io/Iris/api/Tab#Tab "Direct link to Tab") WidgetHasChildrenHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L861) `Tab.Tab:` `Iris.Tab` The tab item for use under a TabBar. The TabBar must be the parent and determines the index value. You cannot provide a state for this tab. The optional Hideable argument determines if a tab can be closed, which is controlled by the isOpened state. A tab will take up the full horizontal width of the parent and hide any other tabs in the TabBar. hasChildren: true hasState: true Arguments = { Text: string, Hideable: boolean? = nil -- determines whether a tab can be closed/hidden } Events = { clicked: () -> boolean, hovered: () -> boolean selected: () -> boolean unselected: () -> boolean active: () -> boolean opened: () -> boolean closed: () -> boolean } State = { isOpened: State? } Show raw api { "functions": \[\], "properties": \[\ {\ "name": "TabBar",\ "desc": "Creates a TabBar for putting tabs under. This does not create the tabs but just the container for them to be in.\\nThe index state is used to control the current tab and is based on an index starting from 1 rather than the\\ntext provided to a Tab. The TabBar will replicate the index to the Tab children .\\n\\n\`\`\`lua\\nhasChildren: true\\nhasState: true\\nArguments = {}\\nEvents = {}\\nState = {\\n index: State? -- whether the widget is collapsed.\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.TabBar",\ "tags": \[\ "Widget",\ "HasChildren",\ "HasState"\ \],\ "source": {\ "line": 825,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "Tab",\ "desc": "The tab item for use under a TabBar. The TabBar must be the parent and determines the index value. You cannot\\nprovide a state for this tab. The optional Hideable argument determines if a tab can be closed, which is\\ncontrolled by the isOpened state.\\n\\nA tab will take up the full horizontal width of the parent and hide any other tabs in the TabBar.\\n\\n\`\`\`lua\\nhasChildren: true\\nhasState: true\\nArguments = {\\n Text: string,\\n Hideable: boolean? = nil -- determines whether a tab can be closed/hidden\\n}\\nEvents = {\\n clicked: () -> boolean,\\n hovered: () -> boolean\\n selected: () -> boolean\\n unselected: () -> boolean\\n active: () -> boolean\\n opened: () -> boolean\\n closed: () -> boolean\\n}\\nState = {\\n isOpened: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Tab",\ "tags": \[\ "Widget",\ "HasChildren",\ "HasState"\ \],\ "source": {\ "line": 861,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Tab", "desc": "Tab Widget API\\n ", "source": { "line": 803, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Tab#properties) * [Tab](https://sirmallard.github.io/Iris/api/Tab#Tab) * [TabBar](https://sirmallard.github.io/Iris/api/Tab#TabBar) --- # Tree | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Tree#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Tree#properties "Direct link to Properties") ------------------------------------------------------------------------------------------------- ### `Tree`[​](https://sirmallard.github.io/Iris/api/Tree#Tree "Direct link to Tree") WidgetHasChildrenHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L764) `Tree.Tree:` `Iris.Tree` A collapsable container for other widgets, to organise and hide widgets when not needed. The state determines whether the child widgets are visible or not. Clicking on the widget will collapse or uncollapse it. hasChildren: true hasState: true Arguments = { Text: string, SpanAvailWidth: boolean? = false, -- the tree title will fill all horizontal space to the end its parent container. NoIndent: boolean? = false, -- the child widgets will not be indented underneath. DefaultOpen: boolean? = false -- initially opens the tree if no state is provided } Events = { collapsed: () -> boolean, uncollapsed: () -> boolean, hovered: () -> boolean } State = { isUncollapsed: State? -- whether the widget is collapsed. } ### `CollapsingHeader`[​](https://sirmallard.github.io/Iris/api/Tree#CollapsingHeader "Direct link to CollapsingHeader") WidgetHasChildrenHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L792) `Tree.CollapsingHeader:` `Iris.CollapsingHeader` The same as a Tree Widget, but with a larger title and clearer, used mainly for organsing widgets on the first level of a window. hasChildren: true hasState: true Arguments = { Text: string, DefaultOpen: boolean? = false -- initially opens the tree if no state is provided } Events = { collapsed: () -> boolean, uncollapsed: () -> boolean, hovered: () -> boolean } State = { isUncollapsed: State? -- whether the widget is collapsed. } Show raw api { "functions": \[\], "properties": \[\ {\ "name": "Tree",\ "desc": "A collapsable container for other widgets, to organise and hide widgets when not needed. The state determines whether the child widgets are visible or not. Clicking on the widget will collapse or uncollapse it.\\n\\n\`\`\`lua\\nhasChildren: true\\nhasState: true\\nArguments = {\\n Text: string,\\n SpanAvailWidth: boolean? = false, -- the tree title will fill all horizontal space to the end its parent container.\\n NoIndent: boolean? = false, -- the child widgets will not be indented underneath.\\n DefaultOpen: boolean? = false -- initially opens the tree if no state is provided\\n}\\nEvents = {\\n collapsed: () -> boolean,\\n uncollapsed: () -> boolean,\\n hovered: () -> boolean\\n}\\nState = {\\n isUncollapsed: State? -- whether the widget is collapsed.\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Tree",\ "tags": \[\ "Widget",\ "HasChildren",\ "HasState"\ \],\ "source": {\ "line": 764,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "CollapsingHeader",\ "desc": "The same as a Tree Widget, but with a larger title and clearer, used mainly for organsing widgets on the first level of a window.\\n\\n\`\`\`lua\\nhasChildren: true\\nhasState: true\\nArguments = {\\n Text: string,\\n DefaultOpen: boolean? = false -- initially opens the tree if no state is provided\\n}\\nEvents = {\\n collapsed: () -> boolean,\\n uncollapsed: () -> boolean,\\n hovered: () -> boolean\\n}\\nState = {\\n isUncollapsed: State? -- whether the widget is collapsed.\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.CollapsingHeader",\ "tags": \[\ "Widget",\ "HasChildren",\ "HasState"\ \],\ "source": {\ "line": 792,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Tree", "desc": "Tree Widget API\\n ", "source": { "line": 735, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Tree#properties) * [CollapsingHeader](https://sirmallard.github.io/Iris/api/Tree#CollapsingHeader) * [Tree](https://sirmallard.github.io/Iris/api/Tree#Tree) --- # Text | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Text#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Text#properties "Direct link to Properties") ------------------------------------------------------------------------------------------------- ### `Text`[​](https://sirmallard.github.io/Iris/api/Text#Text "Direct link to Text") Widget [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L419) `Text.Text:` `Iris.Text` A text label to display the text argument. The Wrapped argument will make the text wrap around if it is cut off by its parent. The Color argument will change the color of the text, by default it is defined in the configuration file. Iris.Window({"Text Demo"}) Iris.Text({"This is regular text"}) Iris.End() ![Example Text](https://sirmallard.github.io/Iris/assets/api/text/basicText.png) hasChildren = false hasState = false Arguments = { Text: string, Wrapped: boolean? = [CONFIG] = false, -- whether the text will wrap around inside the parent container. If not specified, then equal to the config Color: Color3? = Iris._config.TextColor, -- the colour of the text. RichText: boolean? = [CONFIG] = false -- enable RichText. If not specified, then equal to the config } Events = { hovered: () -> boolean } ### `SeparatorText`[​](https://sirmallard.github.io/Iris/api/Text#SeparatorText "Direct link to SeparatorText") Widget [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L499) `Text.SeparatorText:` `Iris.SeparatorText` Similar to [Iris.Separator](https://sirmallard.github.io/Iris/api/Format#Separator) but with a text label to be used as a header when an [Iris.Tree](https://sirmallard.github.io/Iris/api/Tree#Tree) or [Iris.CollapsingHeader](https://sirmallard.github.io/Iris/api/Tree#CollapsingHeader) is not appropriate. Visually a full width thin line with a text label clipping out part of the line. Iris.Window({"Separator Text Demo"}) Iris.Text({"Regular Text"}) Iris.SeparatorText({"This is a separator with text"}) Iris.Text({"More Regular Text"}) Iris.End() ![Example Separator Text](https://sirmallard.github.io/Iris/assets/api/text/basicSeparatorText.png) hasChildren = false hasState = false Arguments = { Text: string } ### `InputText`[​](https://sirmallard.github.io/Iris/api/Text#InputText "Direct link to InputText") WidgetHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L538) `Text.InputText:` `Iris.InputText` A field which allows the user to enter text. Iris.Window({"Input Text Demo"}) local inputtedText = Iris.State("") Iris.InputText({"Enter text here:"}, {text = inputtedText}) Iris.Text({"You entered: " .. inputtedText:get()}) Iris.End() ![Example Input Text](https://sirmallard.github.io/Iris/assets/api/text/basicInputText.gif) hasChildren = false hasState = true Arguments = { Text: string? = "InputText", TextHint: string? = "", -- a hint to display when the text box is empty. ReadOnly: boolean? = false, MultiLine: boolean? = false } Events = { textChanged: () -> boolean, -- whenever the textbox looses focus and a change was made. hovered: () -> boolean } States = { text: State? } ### `TextWrapped`[​](https://sirmallard.github.io/Iris/api/Text#TextWrapped "Direct link to TextWrapped") Widget deprecated in v2.0.0[](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L440) ##### This was deprecated in v2.0.0 Use 'Text' with the Wrapped argument or change the config. `Text.TextWrapped:` `Iris.Text` An alias for [Iris.Text](https://sirmallard.github.io/Iris/api/Text#Text) with the Wrapped argument set to true, and the text will wrap around if cut off by its parent. hasChildren = false hasState = false Arguments = { Text: string, } Events = { hovered: () -> boolean } ### `TextColored`[​](https://sirmallard.github.io/Iris/api/Text#TextColored "Direct link to TextColored") Widget deprecated in v2.0.0[](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L465) ##### This was deprecated in v2.0.0 Use 'Text' with the Color argument or change the config. `Text.TextColored:` `Iris.Text` An alias for [Iris.Text](https://sirmallard.github.io/Iris/api/Text#Text) with the color set by the Color argument. hasChildren = false hasState = false Arguments = { Text: string, Color: Color3 -- the colour of the text. } Events = { hovered: () -> boolean } Show raw api { "functions": \[\], "properties": \[\ {\ "name": "Text",\ "desc": "A text label to display the text argument.\\nThe Wrapped argument will make the text wrap around if it is cut off by its parent.\\nThe Color argument will change the color of the text, by default it is defined in the configuration file.\\n\\n\`\`\`lua\\nIris.Window({\\"Text Demo\\"})\\n Iris.Text({\\"This is regular text\\"})\\nIris.End()\\n\`\`\`\\n\\n!\[Example Text\](/Iris/assets/api/text/basicText.png)\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = false\\nArguments = {\\n Text: string,\\n Wrapped: boolean? = \[CONFIG\] = false, -- whether the text will wrap around inside the parent container. If not specified, then equal to the config\\n Color: Color3? = Iris.\_config.TextColor, -- the colour of the text.\\n RichText: boolean? = \[CONFIG\] = false -- enable RichText. If not specified, then equal to the config\\n}\\nEvents = {\\n hovered: () -> boolean\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Text",\ "tags": \[\ "Widget"\ \],\ "source": {\ "line": 419,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "TextWrapped",\ "desc": "An alias for \[Iris.Text\](Text#Text) with the Wrapped argument set to true, and the text will wrap around if cut off by its parent.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = false\\nArguments = {\\n Text: string,\\n}\\nEvents = {\\n hovered: () -> boolean\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Text",\ "tags": \[\ "Widget"\ \],\ "deprecated": {\ "version": "v2.0.0",\ "desc": "Use 'Text' with the Wrapped argument or change the config."\ },\ "source": {\ "line": 440,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "TextColored",\ "desc": "An alias for \[Iris.Text\](Text#Text) with the color set by the Color argument.\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = false\\nArguments = {\\n Text: string,\\n Color: Color3 -- the colour of the text.\\n}\\nEvents = {\\n hovered: () -> boolean\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Text",\ "tags": \[\ "Widget"\ \],\ "deprecated": {\ "version": "v2.0.0",\ "desc": "Use 'Text' with the Color argument or change the config."\ },\ "source": {\ "line": 465,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "SeparatorText",\ "desc": "Similar to \[Iris.Separator\](Format#Separator) but with a text label to be used as a header\\nwhen an \[Iris.Tree\](Tree#Tree) or \[Iris.CollapsingHeader\](Tree#CollapsingHeader) is not appropriate.\\n\\nVisually a full width thin line with a text label clipping out part of the line.\\n\\n\`\`\`lua\\nIris.Window({\\"Separator Text Demo\\"})\\n Iris.Text({\\"Regular Text\\"})\\n Iris.SeparatorText({\\"This is a separator with text\\"})\\n Iris.Text({\\"More Regular Text\\"})\\nIris.End()\\n\`\`\`\\n\\n!\[Example Separator Text\](/Iris/assets/api/text/basicSeparatorText.png)\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = false\\nArguments = {\\n Text: string\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.SeparatorText",\ "tags": \[\ "Widget"\ \],\ "source": {\ "line": 499,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "InputText",\ "desc": "A field which allows the user to enter text.\\n\\n\`\`\`lua\\nIris.Window({\\"Input Text Demo\\"})\\n local inputtedText = Iris.State(\\"\\")\\n\\n Iris.InputText({\\"Enter text here:\\"}, {text = inputtedText})\\n Iris.Text({\\"You entered: \\" .. inputtedText:get()})\\nIris.End()\\n\`\`\`\\n\\n!\[Example Input Text\](/Iris/assets/api/text/basicInputText.gif)\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = true\\nArguments = {\\n Text: string? = \\"InputText\\",\\n TextHint: string? = \\"\\", -- a hint to display when the text box is empty.\\n ReadOnly: boolean? = false,\\n MultiLine: boolean? = false\\n}\\nEvents = {\\n textChanged: () -> boolean, -- whenever the textbox looses focus and a change was made.\\n hovered: () -> boolean\\n}\\nStates = {\\n text: State?\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.InputText",\ "tags": \[\ "Widget",\ "HasState"\ \],\ "source": {\ "line": 538,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Text", "desc": "Text Widget API\\n ", "source": { "line": 387, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Text#properties) * [InputText](https://sirmallard.github.io/Iris/api/Text#InputText) * [SeparatorText](https://sirmallard.github.io/Iris/api/Text#SeparatorText) * [Text](https://sirmallard.github.io/Iris/api/Text#Text) * [TextColored](https://sirmallard.github.io/Iris/api/Text#TextColored) * [TextWrapped](https://sirmallard.github.io/Iris/api/Text#TextWrapped) --- # Table | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Table#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Table#properties "Direct link to Properties") -------------------------------------------------------------------------------------------------- ### `Table`[​](https://sirmallard.github.io/Iris/api/Table#Table "Direct link to Table") WidgetHasChildren [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1964) `Table.Table:` `Iris.Table` A layout widget which allows children to be displayed in configurable columns and rows. Highly configurable for many different options, with options for custom width columns as configured by the user, or automatically use the best size. When Resizable is enabled, the vertical columns can be dragged horizontally to increase or decrease space. This is linked to the widths state, which controls the width of each column. This is also dependent on whether the FixedWidth argument is enabled. By default, the columns will scale with the width of the table overall, therefore taking up a percentage, and the widths will be in the range of 0 to 1 as a float. If FixedWidth is enabled, then the widths will be in pixels and have a value of > 2 as an integer. ProportionalWidth determines whether each column has the same width, or individual. By default, each column will take up an equal proportion of the total table width. If true, then the columns will be allocated a width proportional to their total content size, meaning wider columns take up a greater share of the total available space. For a fixed width table, by default each column will take the max width of all the columns. When true, each column width will the minimum to fit the children within. LimitTableWidth is used when FixedWidth is true. It will cut off the table horizontally after the last column. ##### INFO Once the NumColumns is set, it is not possible to change it without some extra code. The best way to do this is by using `Iris.PushConfig()` and `Iris.PopConfig()` which will automatically redraw the widget when the columns change. local numColumns = 4 Iris.PushConfig({ columns = numColumns }) Iris.Table({ numColumns, ...}) do ... end Iris.End() Iris.PopConfig() :::danger Error: nil Always ensure that the number of elements in the widths state is greater or equal to the new number of columns when changing the number of columns. ::: hasChildren = true hasState = false Arguments = { NumColumns: number, -- number of columns in the table, cannot be changed Header: boolean? = false, -- display a header row for each column RowBackground: boolean? = false, -- alternating row background colours OuterBorders: boolean? = false, -- outer border on the entire table InnerBorders: boolean? = false, -- inner bordres on the entire table Resizable: boolean? = false, -- the columns can be resized by dragging or state FixedWidth: boolean? = false, -- columns takes up a fixed pixel width, rather than a proportion of the total available ProportionalWidth: boolean? = false, -- minimises the width of each column individually LimitTableWidth: boolean? = false, -- when a fixed width, cut of any unused space } Events = { hovered: () -> boolean } States = { widths: State<{ number }>? -- the widths of each column if Resizable } Functions[​](https://sirmallard.github.io/Iris/api/Table#functions "Direct link to Functions") ----------------------------------------------------------------------------------------------- ### `NextColumn`[​](https://sirmallard.github.io/Iris/api/Table#NextColumn "Direct link to NextColumn") [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1973) `Table.``NextColumn``(``) →` `(``)` In a table, moves to the next available cell. If the current cell is in the last column, then moves to the cell in the first column of the next row. ### `NextRow`[​](https://sirmallard.github.io/Iris/api/Table#NextRow "Direct link to NextRow") [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L1993) `Table.``NextRow``(``) →` `(``)` In a table, moves to the cell in the first column of the next row. ### `SetColumnIndex`[​](https://sirmallard.github.io/Iris/api/Table#SetColumnIndex "Direct link to SetColumnIndex") [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L2010) `Table.``SetColumnIndex``(``index:` `number``) →` `(``)` In a table, moves to the cell in the given column in the same previous row. Will erorr if the given index is not in the range of 1 to NumColumns. ### `SetRowIndex`[​](https://sirmallard.github.io/Iris/api/Table#SetRowIndex "Direct link to SetRowIndex") [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L2024) `Table.``SetRowIndex``(``index:` `number``) →` `(``)` In a table, moves to the cell in the given row with the same previous column. ### `NextHeaderColumn`[​](https://sirmallard.github.io/Iris/api/Table#NextHeaderColumn "Direct link to NextHeaderColumn") [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L2038) `Table.``NextHeaderColumn``(``) →` `(``)` In a table, moves to the cell in the next column in the header row (row index 0). Will loop around from the last column to the first. ### `SetHeaderColumnIndex`[​](https://sirmallard.github.io/Iris/api/Table#SetHeaderColumnIndex "Direct link to SetHeaderColumnIndex") [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L2057) `Table.``SetHeaderColumnIndex``(``index:` `number``) →` `(``)` In a table, moves to the cell in the given column in the header row (row index 0). Will erorr if the given index is not in the range of 1 to NumColumns. ### `SetColumnWidth`[​](https://sirmallard.github.io/Iris/api/Table#SetColumnWidth "Direct link to SetColumnWidth") [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L2078) `Table.``SetColumnWidth``(` `index:` `number``,` `width:` `number` `) →` `(``)` In a table, sets the width of the given column to the given value by changing the Table's widths state. When the FixedWidth argument is true, the width should be in pixels >2, otherwise as a float between 0 and 1. Will erorr if the given index is not in the range of 1 to NumColumns. Show raw api { "functions": \[\ {\ "name": "NextColumn",\ "desc": "In a table, moves to the next available cell. If the current cell is in the last column,\\nthen moves to the cell in the first column of the next row.\\n ",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 1973,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "NextRow",\ "desc": "In a table, moves to the cell in the first column of the next row.\\n ",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 1993,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "SetColumnIndex",\ "desc": "In a table, moves to the cell in the given column in the same previous row.\\n\\nWill erorr if the given index is not in the range of 1 to NumColumns.\\n ",\ "params": \[\ {\ "name": "index",\ "desc": "",\ "lua\_type": "number"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 2010,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "SetRowIndex",\ "desc": "In a table, moves to the cell in the given row with the same previous column.\\n ",\ "params": \[\ {\ "name": "index",\ "desc": "",\ "lua\_type": "number"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 2024,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "NextHeaderColumn",\ "desc": "In a table, moves to the cell in the next column in the header row (row index 0). Will loop around\\nfrom the last column to the first.\\n ",\ "params": \[\],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 2038,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "SetHeaderColumnIndex",\ "desc": "In a table, moves to the cell in the given column in the header row (row index 0).\\n\\nWill erorr if the given index is not in the range of 1 to NumColumns.\\n ",\ "params": \[\ {\ "name": "index",\ "desc": "",\ "lua\_type": "number"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 2057,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "SetColumnWidth",\ "desc": "In a table, sets the width of the given column to the given value by changing the\\nTable's widths state. When the FixedWidth argument is true, the width should be in\\npixels >2, otherwise as a float between 0 and 1.\\n\\nWill erorr if the given index is not in the range of 1 to NumColumns.\\n ",\ "params": \[\ {\ "name": "index",\ "desc": "",\ "lua\_type": "number"\ },\ {\ "name": "width",\ "desc": "",\ "lua\_type": "number"\ }\ \],\ "returns": \[\],\ "function\_type": "static",\ "source": {\ "line": 2078,\ "path": "lib/API.lua"\ }\ }\ \], "properties": \[\ {\ "name": "Table",\ "desc": "A layout widget which allows children to be displayed in configurable columns and rows. Highly configurable for many different\\noptions, with options for custom width columns as configured by the user, or automatically use the best size.\\n\\nWhen Resizable is enabled, the vertical columns can be dragged horizontally to increase or decrease space. This is linked to\\nthe widths state, which controls the width of each column. This is also dependent on whether the FixedWidth argument is enabled.\\nBy default, the columns will scale with the width of the table overall, therefore taking up a percentage, and the widths will be\\nin the range of 0 to 1 as a float. If FixedWidth is enabled, then the widths will be in pixels and have a value of > 2 as an\\ninteger.\\n\\nProportionalWidth determines whether each column has the same width, or individual. By default, each column will take up an equal\\nproportion of the total table width. If true, then the columns will be allocated a width proportional to their total content size,\\nmeaning wider columns take up a greater share of the total available space. For a fixed width table, by default each column will\\ntake the max width of all the columns. When true, each column width will the minimum to fit the children within.\\n\\nLimitTableWidth is used when FixedWidth is true. It will cut off the table horizontally after the last column.\\n\\n:::info\\nOnce the NumColumns is set, it is not possible to change it without some extra code. The best way to do this is by using\\n\`Iris.PushConfig()\` and \`Iris.PopConfig()\` which will automatically redraw the widget when the columns change.\\n\\n\`\`\`lua\\nlocal numColumns = 4\\nIris.PushConfig({ columns = numColumns })\\nIris.Table({ numColumns, ...})\\ndo\\n ...\\nend\\nIris.End()\\nIris.PopConfig()\\n\`\`\`\\n\\n:::danger Error: nil\\nAlways ensure that the number of elements in the widths state is greater or equal to the\\nnew number of columns when changing the number of columns.\\n:::\\n:::\\n\\n\`\`\`lua\\nhasChildren = true\\nhasState = false\\nArguments = {\\n NumColumns: number, -- number of columns in the table, cannot be changed\\n Header: boolean? = false, -- display a header row for each column\\n RowBackground: boolean? = false, -- alternating row background colours\\n OuterBorders: boolean? = false, -- outer border on the entire table\\n InnerBorders: boolean? = false, -- inner bordres on the entire table\\n Resizable: boolean? = false, -- the columns can be resized by dragging or state\\n FixedWidth: boolean? = false, -- columns takes up a fixed pixel width, rather than a proportion of the total available\\n ProportionalWidth: boolean? = false, -- minimises the width of each column individually\\n LimitTableWidth: boolean? = false, -- when a fixed width, cut of any unused space\\n}\\nEvents = {\\n hovered: () -> boolean\\n}\\nStates = {\\n widths: State<{ number }>? -- the widths of each column if Resizable\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Table",\ "tags": \[\ "Widget",\ "HasChildren"\ \],\ "source": {\ "line": 1964,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Table", "desc": "Table Widget API\\n\\nExample usage for creating a simple table:\\n\`\`\`lua\\nIris.Table({ 4, true })\\ndo\\n Iris.SetHeaderColumnIndex(1)\\n\\n -- for each row\\n for i = 0, 10 do\\n\\n -- for each column\\n for j = 1, 4 do\\n if i == 0 then\\n -- \\n Iris.Text({ \`H: {j}\` })\\n else\\n Iris.Text({ \`R: {i}, C: {j}\` })\\n end\\n\\n -- move the next column (and row when necessary)\\n Iris.NextColumn()\\n end\\n end\\n\`\`\`\\n ", "source": { "line": 1898, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Table#properties) * [Table](https://sirmallard.github.io/Iris/api/Table#Table) * [Functions](https://sirmallard.github.io/Iris/api/Table#functions) * [.NextColumn](https://sirmallard.github.io/Iris/api/Table#NextColumn) * [.NextHeaderColumn](https://sirmallard.github.io/Iris/api/Table#NextHeaderColumn) * [.NextRow](https://sirmallard.github.io/Iris/api/Table#NextRow) * [.SetColumnIndex](https://sirmallard.github.io/Iris/api/Table#SetColumnIndex) * [.SetColumnWidth](https://sirmallard.github.io/Iris/api/Table#SetColumnWidth) * [.SetHeaderColumnIndex](https://sirmallard.github.io/Iris/api/Table#SetHeaderColumnIndex) * [.SetRowIndex](https://sirmallard.github.io/Iris/api/Table#SetRowIndex) --- # Window | Iris [Skip to main content](https://sirmallard.github.io/Iris/api/Window#__docusaurus_skipToContent_fallback) On this page Properties[​](https://sirmallard.github.io/Iris/api/Window#properties "Direct link to Properties") --------------------------------------------------------------------------------------------------- ### `Window`[​](https://sirmallard.github.io/Iris/api/Window#Window "Direct link to Window") WidgetHasChildrenHasState [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L82) `Window.Window:` `Iris.Window` The top-level container for all other widgets to be created within. Can be moved and resized across the screen. Cannot contain embedded windows. Menus can be appended to windows creating a menubar. hasChildren = true hasState = true Arguments = { Title: string, NoTitleBar: boolean? = false, NoBackground: boolean? = false, -- the background behind the widget container. NoCollapse: boolean? = false, NoClose: boolean? = false, NoMove: boolean? = false, NoScrollbar: boolean? = false, -- the scrollbar if the window is too short for all widgets. NoResize: boolean? = false, NoNav: boolean? = false, -- unimplemented. NoMenu: boolean? = false -- whether the menubar will show if created. } Events = { opened: () -> boolean, -- once when opened. closed: () -> boolean, -- once when closed. collapsed: () -> boolean, -- once when collapsed. uncollapsed: () -> boolean, -- once when uncollapsed. hovered: () -> boolean -- fires when the mouse hovers over any of the window. } States = { size: State? = Vector2.new(400, 300), position: State?, isUncollapsed: State? = true, isOpened: State? = true, scrollDistance: State? -- vertical scroll distance, if too short. } ### `Tooltip`[​](https://sirmallard.github.io/Iris/api/Window#Tooltip "Direct link to Tooltip") Widget [](https://github.com/SirMallard/Iris/blob/main/lib/API.lua#L114) `Window.Tooltip:` `Iris.Tooltip` Displays a text label next to the cursor Iris.Tooltip({"My custom tooltip"}) ![Basic tooltip example](https://sirmallard.github.io/Iris/assets/api/window/basicTooltip.png) hasChildren = false hasState = false Arguments = { Text: string } Show raw api { "functions": \[\], "properties": \[\ {\ "name": "Window",\ "desc": "The top-level container for all other widgets to be created within.\\nCan be moved and resized across the screen. Cannot contain embedded windows.\\nMenus can be appended to windows creating a menubar.\\n\\n\`\`\`lua\\nhasChildren = true\\nhasState = true\\nArguments = {\\n Title: string,\\n NoTitleBar: boolean? = false,\\n NoBackground: boolean? = false, -- the background behind the widget container.\\n NoCollapse: boolean? = false,\\n NoClose: boolean? = false,\\n NoMove: boolean? = false,\\n NoScrollbar: boolean? = false, -- the scrollbar if the window is too short for all widgets.\\n NoResize: boolean? = false,\\n NoNav: boolean? = false, -- unimplemented.\\n NoMenu: boolean? = false -- whether the menubar will show if created.\\n}\\nEvents = {\\n opened: () -> boolean, -- once when opened.\\n closed: () -> boolean, -- once when closed.\\n collapsed: () -> boolean, -- once when collapsed.\\n uncollapsed: () -> boolean, -- once when uncollapsed.\\n hovered: () -> boolean -- fires when the mouse hovers over any of the window.\\n}\\nStates = {\\n size: State? = Vector2.new(400, 300),\\n position: State?,\\n isUncollapsed: State? = true,\\n isOpened: State? = true,\\n scrollDistance: State? -- vertical scroll distance, if too short.\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Window",\ "tags": \[\ "Widget",\ "HasChildren",\ "HasState"\ \],\ "source": {\ "line": 82,\ "path": "lib/API.lua"\ }\ },\ {\ "name": "Tooltip",\ "desc": "Displays a text label next to the cursor\\n\\n\`\`\`lua\\nIris.Tooltip({\\"My custom tooltip\\"})\\n\`\`\`\\n\\n!\[Basic tooltip example\](/Iris/assets/api/window/basicTooltip.png)\\n\\n\`\`\`lua\\nhasChildren = false\\nhasState = false\\nArguments = {\\n Text: string\\n}\\n\`\`\`\\n ",\ "lua\_type": "Iris.Tooltip",\ "tags": \[\ "Widget"\ \],\ "source": {\ "line": 114,\ "path": "lib/API.lua"\ }\ }\ \], "types": \[\], "name": "Window", "desc": "Windows are the fundamental widget for Iris. Every other widget must be a descendant of a window.\\n\\n\`\`\`lua\\nIris.Window({ \\"Example Window\\" })\\n Iris.Text({ \\"This is an example window!\\" })\\nIris.End()\\n\`\`\`\\n\\n!\[Example window\](/Iris/assets/api/window/basicWindow.png)\\n\\nIf you do not want the code inside a window to run unless it is open then you can use the following:\\n\`\`\`lua\\nlocal window = Iris.Window({ \\"Many Widgets Window\\" })\\n\\nif window.state.isOpened.value and window.state.isUncollapsed.value then\\n Iris.Text({ \\"I will only be created when the window is open.\\" })\\nend\\nIris.End() -- must always call Iris.End(), regardless of whether the window is open or not.\\n\`\`\`\\n ", "source": { "line": 39, "path": "lib/API.lua" } } * [Properties](https://sirmallard.github.io/Iris/api/Window#properties) * [Tooltip](https://sirmallard.github.io/Iris/api/Window#Tooltip) * [Window](https://sirmallard.github.io/Iris/api/Window#Window) --- # Common Issues | Iris [Skip to main content](https://sirmallard.github.io/Iris/docs/common_issues#__docusaurus_skipToContent_fallback) On this page When using Iris you may run into different issues. The most common ones are explained below and explain why the issue arises and how to fix it. Iris.Init() can only be called once.[​](https://sirmallard.github.io/Iris/docs/common_issues#irisinit-can-only-be-called-once "Direct link to Iris.Init() can only be called once.") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Error `Iris.Init() can only be called once.` Iris can only be initialised once per client. The best way to initialise Iris then is to place it at the start of one of your first running script. For example you may have: ------------------------------------- ReplicatedFirst/client.lua or StarterPlayer/StarterPlayerScripts/client.lua---------------------------------- 1| -- code in ReplicatedFirst will execute before other code, so it is best practice 2| -- to initialise Iris here even if you are not going to use it. 3| reqire(game.ReplicatedStorage.Iris).Init() 4| 5| ...------------------------------------------- StarterPlayer/StarterPlayerScripts/raycast.lua---------------------------------------- 1| -- therefore, when you require it any scripts elsewhere it is already initialised 2| -- and ready to go and you do not need to worry about where to init 3| local Iris = require(game.ReplicatedStorage.Iris) 4| 5| -- wrong, you have initialised it twice here 6| local Iris = require(game.ReplicatedStorage.Iris).Init() 7| 8| ... This becomes more difficult if you have many local scripts which could all execute at the same time. This is why most games will only use a few local scripts and rely on modules for the rest, which ensures that code runs in an expected and deterministic order and therefore any client-wide initialisation can happen before anything that relies on it does. Iris:Connect() was called before calling Iris.Init(); always initialise Iris first.[​](https://sirmallard.github.io/Iris/docs/common_issues#iris-was-called-before-calling-irisinit-always-initialise-iris-first "Direct link to iris-was-called-before-calling-irisinit-always-initialise-iris-first") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Warn `Iris:Connect() was called before calling Iris.Init(); always initialise Iris first.` Iris should always be initialised before attempting to use 'Connect()'. This is just a warning to make sure that you are initialising Iris in the first place. If you connect and then initialise, your code will still run normally and Iris functions fine. However, as mentioned in the `Iris.Init() can only be called once.` issue, it is better practice to initalise Iris before any other Iris code runs and therefore you can ensure consistent ordering. Iris cycleCoroutine took to long to yield. Connected functions should not yield.[​](https://sirmallard.github.io/Iris/docs/common_issues#iris-cyclecoroutine-took-to-long-to-yield-connected-functions-should-not-yield "Direct link to Iris cycleCoroutine took to long to yield. Connected functions should not yield.") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Error `Iris cycleCoroutine took to long to yield. Connected functions should not yield.` Iris does not support yielding statements becaues it needs to run and finish every frame. Therefore if you have code which needs to yield and wait, you should either handle it outside of an Iris widget, or spawn a new thread. The example below demonstrates the issue: -------------------------- bad_example.lua----------------------- 4| Iris.Window({"Async Window"}) 5| -- this code yeilds which will prevent Iris from finishing before the next frame 6| local response = httpService:GetAsync(...) 7| Iris.Text(response) 8| Iris.End()--------------------------- good_example.lua ------------------------ 4| local response = "NONE" 5| 6| Iris.Window({"Async Window"}) 7| -- we use another thread to ensure the thread Iris is in will finish before the next frame 8| task.spawn(function() 9| response = httpService:GetAsync(...)10| end)11| Iris.Text(response)12| Iris.End() These examples are fairly simple, but when you are integrating Iris directly into your codebase it should become much clearer. Too few calls to Iris.End()., Too many calls to Iris.End().[​](https://sirmallard.github.io/Iris/docs/common_issues#too-few-calls-to-irisend-too-many-calls-to-irisend "Direct link to Too few calls to Iris.End()., Too many calls to Iris.End().") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Error `Too few calls to Iris.End().`, `Too many calls to Iris.End().` These issues are caused respectively by have too few or too many calls to `Iris.End()`. Every widget that has children, from Windows and Trees to MenuBars and Combos to SameLine and Indent must have an `Iris.End()` statement to say that you are done appending to that parent. To ensure this does not happen, it is best to use do-end blocks to indent out parent widgets from their children and make it clearer to see where an `Iris.End()` statement must go. For example: 4| Iris.Window({ "Do-End Block" }) 5| do 6| Iris.Text({ "Text goes here." }) 7| end 8| Iris.End() This makes it clear that an `Iris.End()` statement should always go after an `end` block. This issue may also arise if some of your code either yields or errors and therefore not all the `Iris.End()` calls happen. For example: 4| Iris.Window({ "Valid Code with Error" }) 5| error("Something has gone wrong. :(") -- errors within Iris 6| Iris.End() 7| Iris.Window({ "Asynchronous Code" }) 8| task.wait(1) -- yeilds within Iris 9| Iris.End() Although all the `Iris.End()` statements are there and in the right space, the error has prevented it from running and therefore we will get this error. * [Iris.Init() can only be called once.](https://sirmallard.github.io/Iris/docs/common_issues#irisinit-can-only-be-called-once) * [Iris() was called before calling Iris.Init(); always initialise Iris first.](https://sirmallard.github.io/Iris/docs/common_issues#iris-was-called-before-calling-irisinit-always-initialise-iris-first) * [Iris cycleCoroutine took to long to yield. Connected functions should not yield.](https://sirmallard.github.io/Iris/docs/common_issues#iris-cyclecoroutine-took-to-long-to-yield-connected-functions-should-not-yield) * [Too few calls to Iris.End()., Too many calls to Iris.End().](https://sirmallard.github.io/Iris/docs/common_issues#too-few-calls-to-irisend-too-many-calls-to-irisend) --- # Showcases | Iris [Skip to main content](https://sirmallard.github.io/Iris/docs/showcase#__docusaurus_skipToContent_fallback) On this page Iris is already being used across Roblox. A few examples of what people have publicly posted and what they are saying about Iris are shown here. Over time, this page will be updated. If you are using Iris or see Iris being used somewhere, reach out to us so we can add it here. Quotes[​](https://sirmallard.github.io/Iris/docs/showcase#quotes "Direct link to Quotes") ------------------------------------------------------------------------------------------ > "Iris \[...\] is probably the best thing that ever happened to development tooling." - [MaximumADHD](https://x.com/MaximumADHD/status/1763048015936225326) > "This is all made easy thanks to Iris!" - [TylerAtStarboardGames](https://medium.com/@tyleratstarboardgames/using-iris-to-clean-up-my-plugin-workflow-e66a2886498f) > "Made a \[...\] debugging UI with Iris. Gonna be a whole lot easier \[...\] from now on" - [Drainhp](https://x.com/drainhitpoints/status/1878577315359400253) Images[​](https://sirmallard.github.io/Iris/docs/showcase#images "Direct link to Images") ------------------------------------------------------------------------------------------ Follow the links to see various posts and blogs which demonstrate Iris. * [@MaximumADHD](https://x.com/MaximumADHD/status/1763048015936225326) * [@Boogle](https://x.com/LeBoogle/status/1772384187426709879) * [tyridge77](https://devforum.roblox.com/t/pathfinding-in-large-rpg-games-discussion-about-the-best-pathfinding-methods-for-roblox/3084075/29) * [TylerAtStarboardGames](https://medium.com/@tyleratstarboardgames/using-iris-to-clean-up-my-plugin-workflow-e66a2886498f) * [Drainhp](https://x.com/matelgaard/status/1878577315359400253) * [Quotes](https://sirmallard.github.io/Iris/docs/showcase#quotes) * [Images](https://sirmallard.github.io/Iris/docs/showcase#images) --- # Iris | Iris [Skip to main content](https://sirmallard.github.io/Iris/docs/intro#__docusaurus_skipToContent_fallback) On this page Iris is an Immediate mode GUI Library for Roblox, based on Dear ImGui, designed for building the UI for debug / visualisation and content-creation tools. Iris does this by requiring the developer to only describe what they want and not how they want it to be done, and Iris will handle all of the 'how'. This allows quick iterations from simple and minimal code to produce the tools you need anywhere in your game. Iris makes it faster and more convenient for developers to use a wide range of powerful widgets to build their UI systems. Iris is aimed at the developers who need to quickly check and alter code in development rather than an end UI solution, but how you use it is up to you. Iris uses an immediate mode UI paradigm, which is different from other conventional UI libraries designed for Roblox. Instead of keeping a reference to every UI element, with Iris you declare the UI you want to appear every frame and it will show you what you asked for. Iris also manages the layout and arrangment of systems whilst also giving control to you making it simple to construct a fully suite of UI debugging tools without worrying about where the UI is going to be positioned. Demonstration[​](https://sirmallard.github.io/Iris/docs/intro#demonstration "Direct link to Demonstration") ------------------------------------------------------------------------------------------------------------ ### Simple Example[​](https://sirmallard.github.io/Iris/docs/intro#simple-example "Direct link to Simple Example") With just 8 lines of code, you can create a basic window and widgets, with instant functionality: local StarterPlayerScripts = game.StarterPlayer.StarterPlayerScriptslocal Iris = require(StarterPlayerScripts.Client.Iris).Init()Iris:Connect(function() Iris.Window({"My First Window!"}) Iris.Text({"Hello, World"}) Iris.Button({"Save"}) Iris.InputNum({"Input"}) Iris.End()end) ![](https://sirmallard.github.io/Iris/assets/docs/simpleExample1.png) We can break this code down to explain Iris better: local StarterPlayerScripts = game.StarterPlayer.StarterPlayerScripts-- We first need to initialise Iris once before it is used anywhere. `Init()` will-- begin the main loop and set up the root widgets. Init can only be called once per-- client and returns Iris when called.local Iris = require(StarterPlayerScripts.Client.Iris).Init()-- 'Connect()' will run the provided function every frame. Iris code will need to run-- every frame to appear but you can use any other event and place your code anywhereIris:Connect(function() -- We create a window and give it a title of 'My First Window!'. All widgets will -- be descended from a window which can be moved and scaled around the screen. Iris.Window({"My First Window!"}) -- A text widget can show any text we want, including support for RichText. Iris.Text({"Hello, World"}) -- A button has a clicked event which we can use to detech when the user -- activates it and handle that any way we want. Iris.Button({"Save"}) -- Iris has input, slider and drag widgets for each of the core datatype -- with support for min, max and increments. Iris.InputNum({"Input"}) -- Any widget which has children must end with an 'End()'. This includes -- windows, trees, tables and a few others. To make it easier to see, we can use -- a do-end loop wrapped around every parent widget. Iris.End()end) ### More Complex Example[​](https://sirmallard.github.io/Iris/docs/intro#more-complex-example "Direct link to More Complex Example") We can also then make a more complicated example: local StarterPlayerScripts = game.StarterPlayer.StarterPlayerScriptslocal Iris = require(StarterPlayerScripts.Client.Iris).Init()Iris:Connect(function() local windowSize = Iris.State(Vector2.new(300, 400)) Iris.Window({"My Second Window"}, {size = windowSize}) Iris.Text({"The current time is: " .. time()}) Iris.InputText({"Enter Text"}) if Iris.Button({"Click me"}).clicked() then print("button was clicked") end Iris.InputColor4() Iris.Tree() for i = 1,8 do Iris.Text({"Text in a loop: " .. i}) end Iris.End() Iris.End()end) ![](https://sirmallard.github.io/Iris/assets/docs/simpleExample2.png) This example has introduced the state object which allows us to control the state or value of Iris widgets and use these values in actual code. This is the bridge between your variables and being able to modify them in Iris. We also demonstrate the tree node which is useful for helping organise your UI tools. Adding to your Game[​](https://sirmallard.github.io/Iris/docs/intro#adding-to-your-game "Direct link to Adding to your Game") ------------------------------------------------------------------------------------------------------------------------------ So far we've seen how Iris works in a simple environment, but Iris is most helpful when you are using it alongside your main code. In order to showcase this, we have taken 'The Mystery of Duval Drive' and added Iris which allows us to test and modify the game state when testing the game. For more examples of Iris being used in actual games as either debug and visualisation tools or for content creation tooling, checkout the [Showcases](https://sirmallard.github.io/Iris/docs/showcase) page. * [Demonstration](https://sirmallard.github.io/Iris/docs/intro#demonstration) * [Simple Example](https://sirmallard.github.io/Iris/docs/intro#simple-example) * [More Complex Example](https://sirmallard.github.io/Iris/docs/intro#more-complex-example) * [Adding to your Game](https://sirmallard.github.io/Iris/docs/intro#adding-to-your-game) --- # Getting Started | Iris [Skip to main content](https://sirmallard.github.io/Iris/docs/getting_started#__docusaurus_skipToContent_fallback) On this page Installing Iris[​](https://sirmallard.github.io/Iris/docs/getting_started#installing-iris "Direct link to Installing Iris") ---------------------------------------------------------------------------------------------------------------------------- Iris is available to download using Wally, use the release from GitHub, or build yourself. It is best to place Iris somewhere on the client, such as under `StarterPlayerScripts` or `ReplicatedStorage`. Once Iris is installed, you can `require(path.to.Iris)` the module from any client script. Iris also has a public types system, which you can access from `require(path.to.Iris.PubTypes)`. To start Iris, you will need to run `Iris.Init()` before using Iris anywhere else. This can be difficult when you have multiple scripts running at the same time, so it is best to organise your code with a single entry point to initialise Iris from. Checking Iris Works =================== We can first test Iris works properly by using the DemoWindow, to display all the widgets in Iris. First we'll create a client script under `StarterPlayer.StarterPlayerScipts`, and put this into it: local Iris = require(path.to.Iris)Iris.Init()Iris:Connect(Iris.ShowDemoWindow) If we then run the game, we should see the Iris Demo Window appear on the screen. This shows that Iris is working properly and we can start writing our own code. Check [here](https://sirmallard.github.io/Iris/docs/intro) for some example code, read through the [`demoWindow.lua`](https://github.com/SirMallard/Iris/blob/main/lib/demoWindow.lua) file to see how the demo window works, or check the rest of the documentation for each widget. Understanding the API[​](https://sirmallard.github.io/Iris/docs/getting_started#understanding-the-api "Direct link to Understanding the API") ---------------------------------------------------------------------------------------------------------------------------------------------- The Iris API is fairly unique and can be difficult to understand initially. However, once understood, it becomes much clearer and is consistent between all widgets. We will use a Window as an example because it best demonstrates the API and is used in every Iris project. The API documentation for a window is as follows and contains all the information we need: hasChildren = truehasState = trueArguments = { Title: string, NoTitleBar: boolean? = false, NoBackground: boolean? = false, -- the background behind the widget container. NoCollapse: boolean? = false, NoClose: boolean? = false, NoMove: boolean? = false, NoScrollbar: boolean? = false, -- the scrollbar if the window is too short for all widgets. NoResize: boolean? = false, NoNav: boolean? = false, -- unimplemented. NoMenu: boolean? = false -- whether the menubar will show if created.}Events = { opened: () -> boolean, -- once when opened. closed: () -> boolean, -- once when closed. collapsed: () -> boolean, -- once when collapsed. uncollapsed: () -> boolean, -- once when uncollapsed. hovered: () -> boolean -- fires when the mouse hovers over any of the window.}States = { size = State? = Vector2.new(400, 300), position = State?, isUncollapsed = State? = true, isOpened = State? = true, scrollDistance = State? -- vertical scroll distance, if too short.} The first documentation says that a Window has children, and therefore, we know that calling `Iris.Windw()` must always be followed eventually by `Iris.End()` to exit out of the window. We are then told that a window has state, and the different states, their types and default values are shown in the State table. We are also told that they are all optional, and will be created if not provided. ### Using Arguments[​](https://sirmallard.github.io/Iris/docs/getting_started#using-arguments "Direct link to Using Arguments") The next information is the Arguments table. This contains the ordered list of all arguments, the type and default value if optional. For a Window, the Title is a required string, whereas the other arguments are all optional booleans defaulting to false. We will thus need to provide a string as the first argument for any window. info THe arguments provided to a widget are sent as an array with index 1 as the first argument, index 2 as the second and so on. This means it is possible to provide the arguments in a different order, such as `{ [1] = "Title", [6] = true}` which provides the title and also sets `NoMove` to true. We therefore do not have to provide We will ignore the Events table for now, since they are not required for calling a widget. The window API prototype looks like this: `(arguments: { any }, states: { [string]: State }?) -> Window`. Each widget is a function which takes two parameters, an array of arguments and a string dictionary of States. Notice how the arguments array is required but the state dictionary is optional, because none of the states is optional. If the arguments were all optional, then the arguments array would itself also be optional. Using this, we can now assemble our API call for a window. The arguments for this will be the `TItle`, `NoClose` and `NoResize`. We will not provide any states, instead Iris will generate them for us. Our final function looks like this: local Iris = require(Iris)-- These are all equivalent:Iris.Window({"Title", nil, nil, nil, true, nil, nil, true})Iris.Window({ [1] = "Title", [5] = true, [8] = true })Iris.Window({ [Iris.Args.Window.Title] = "Title", [Iris.Args.Window.NoClose] = true, [Iris.Args.Window.NoResize] = true }) For the last two, the order no longer matters and the arguments can be placed in any order. The last one uses `Iris.Args.[WIDGET].[ARGUMENT]` which contains the index or number for each argument position. It makes it clearer which arguments you are using, but at the cost of longer function calls. This is generally only used for widgets with rarely used arguments. info These are what the values actually are. `Iris.Args.Window.Title` = 1 `Iris.Args.Window.NoClose` = 5 `Iris.Args.Window.NoResize` = 8 These are just shorthands, making it easier for you, if you choose to use them. Providing `{Title = "Title"}` or any variation of this with a string index will not work and will error. Iris is designed to mainly use the first example, because it is very similar to Dear ImGui and acts the same way as if providing the arguments directly to a function, where the order matters. However, because widgets have both arguments and state, the separation into two tables is required and we cannot use a regular function. ### Using State[​](https://sirmallard.github.io/Iris/docs/getting_started#using-state "Direct link to Using State") If we decided that we wanted to provide a state to the widget, we can use the state table to determine the correct name and type for each widget. The state is what controls any properties which the user can both send and receive data from a widget, which may be updated by either the user or by an interaction with the widget. For example, moving a window around will change the position state. And if the user sets the position state somewhere in the code, the window will be moved to that position. info States in Iris take the place of pointers in C++ that Dear ImGui uses. If we have a number and then provide it as an parameter to a function, the value will be copied over in memory for the function and therefore updating the number in the function would not update it outside the function. If Lua had pointers, this would work, but instead we use states which are tables to store all the changes. Providing a state in Iris is very easy, we first create it and then provide it with the string name to the widget: local positionState = Iris.State(Vector2.new(100, 100))Iris.Window({ "Positioned Window" }, { position = positionState }) We now have access to the window position state which we can set or read from anywhere else in our code. When first created, the window will be positioned at (100, 100) on the screen, but can still be moved around. Notice how we provide the state number rather than an index for the state table. We do not need to provide the state to use the widget, we can just grab it from the created widget: local window = Iris.Window({ "Positioned Window" })local positionState = window.state.position ### Using Events[​](https://sirmallard.github.io/Iris/docs/getting_started#using-events "Direct link to Using Events") We've covered children, arguments and state but not yet events. Events are what make widgets interactive and allow us run code when we use a widget. Each widget has a set of predefined events which we can check for every frame. To listen to any event, we can just call the function on the widget like this: local window = Iris.Window({"Window"})-- the window has opened and uncollapsed events, which return booleansif window.opened() and window.uncollapsed() then -- run the window code only if the window is actually open and uncollapsed, -- which is more efficient. -- the button has a clicked event, returning true when it is pressed if Iris.Button({"Click me"}).clicked() then -- run code if we click the button endendIris.End() Here, we are listening to events which are just functions that return a boolean if the condition is true. We can refer to the API to find all the events, and they should be fairly self-explanatory in what they do. Some events will only happen once when the user interacts with the widget, others will depend on the state of the widget, such as if it is open. * [Installing Iris](https://sirmallard.github.io/Iris/docs/getting_started#installing-iris) * [Understanding the API](https://sirmallard.github.io/Iris/docs/getting_started#understanding-the-api) * [Using Arguments](https://sirmallard.github.io/Iris/docs/getting_started#using-arguments) * [Using State](https://sirmallard.github.io/Iris/docs/getting_started#using-state) * [Using Events](https://sirmallard.github.io/Iris/docs/getting_started#using-events) --- # Understanding the Lifecycle | Iris [Skip to main content](https://sirmallard.github.io/Iris/docs/about/cycle#__docusaurus_skipToContent_fallback) On this page General Game Lifecycle[​](https://sirmallard.github.io/Iris/docs/about/cycle#general-game-lifecycle "Direct link to General Game Lifecycle") --------------------------------------------------------------------------------------------------------------------------------------------- Iris is designed for games with a core 'game loop' which is the structure that controls what part of the game process happens when. A typical game loop make look very similar to this: while(not_closed) { poll_input(); update_game_state(); step_physics(); render_content(); wait(); // for a 60 fps limit} Here we start firstly with polling for any input changes, since these affect the game state for that frame. We then update the game state which generally includes the majority of a game engine, since it would control any user updates, world changes, UI updates and others. We may also then choose to step our physics engine, assuming we are using a constant frame rate. Finally we render out everything to our GPU and wait until the appropriate time to start processing the next frame. Roblox takes most of this away from developers, and instead chooses to rely on an event-driven loop, where we hook onto a part of the engine allowing something else to happen. This makes it more difficult to use Iris, since not every place we want it will run every frame. However, Roblox provides access to RunService events, allowing us to execute code every frame, which is seen below: while not_closed do update(UserInputService) update(ContextActionService) event(RunService.BindToRenderStepped) event(RunService.RenderStepped) render() event(wait) event(RunService.Stepped) update(PhysicsService) event(RunService.Heartbeat) update(ReplicationService) delay() -- for a 60 fps limitend This is taken from the [Task Scheduler Documentation](https://create.roblox.com/docs/studio/microprofiler/task-scheduler) which goes into more detail about this. Iris Lifecycle[​](https://sirmallard.github.io/Iris/docs/about/cycle#iris-lifecycle "Direct link to Iris Lifecycle") --------------------------------------------------------------------------------------------------------------------- Iris needs to run every frame, called the cycle, in order to update global variables and to clean any unused widgets. This is equivalent to calling `ImGui::EndFrame()` for Dear ImGui, which would then process the frame buffers ready for use. This order is important for Iris, which by default uses the `RunService.Heartbeat` event to process this all on. Therefore, for each frame, any Iris code must run before this event. It is possible to change the event Iris runs on when initialising, but for most cases, `RunService.Heartbeat` is ideal. Understanding this is the key to most effectively using Iris. The library provides a handy `Iris:Connect()` function which will run any code in the function every frame before the cycle. This makes it the most convenient. However, any functions provided here will also run on the initialised event, `RunService.Heartbeat` here, so will run after physics and animations are calculated. Thankfully, Iris does not constrain you to use only `Iris:Connect()`. You are able to run Iris code anywhere, in any event, at any time. As long as it is consistent on every frame, and before the cycle event, it will work properly. Therefore, it is very possible to put Iris directly into your core game loops. Demonstration[​](https://sirmallard.github.io/Iris/docs/about/cycle#demonstration "Direct link to Demonstration") ------------------------------------------------------------------------------------------------------------------ Say you have a weapon class which is used by every weapon and then also a weapon handler/serivce/system/controller for handling all weapons on the client. Integrating Iris may look something similar to this: --------------------------------------------------------------------------- game.ReplicatedStorage.Modules.Client.Weaopns.WeaponsService.lua------------------------------------------------------------------------local WeaponsService = { maxWeapons = 10, activeWeapon = nil, weapons = {}}function WeaponsService.init()end-- called every frame to update all weaponsfunction WeaponsService.update(deltaTime: number) Iris.Window({ "Weapons Service" }) WeaponsService.doSomething() Iris.CollapsingHeader({ "Global Variables" }) Iris.DragNum({ "Max Weapons", 1, 0 }, { number = Iris.TableState(WeaponsService.maxWeapons) }) Iris.End() Iris.CollapsingHeader({ "Weapons" }) Iris.Tree({ `Active Weapon: {WeaponsService.activeWeapon.name}` }) WeaponsService.activeWeapon:update() Iris.End() Iris.SeparatorText({ "All Weapons" }) for _, weapon: weapon in WeaponsService.weapons do Iris.Tree({ weapon.name }) weapon:update() Iris.End() end Iris.End() WeaponsService.doSomethingElse() Iris.End()endfunction WeaponsService.terminate()endreturn WeaponsService--------------------------------------------------------------------------- game.ReplicatedStorage.Modules.Client.Weaopns.Weapon.lua------------------------------------------------------------------------local Weapon = {}Weapon.__index = Weaponfunction Weapon.new(...)endfunction Weapon.update(self, deltaTime: number) Iris.Text({ `ID: {self.id}` }) Iris.Text({ `Bullets: {self.bullets}/{self.capacity}" }) Iris.Checkbox({ "No reload" }, { isChecked = Iris.TableState(self.noreload) }) ... self:updateInputs() self:updateTransforms() ...endfunction Weapon.destroy(self)end Although this is very bare bones code, we are not using any `Iris:Connect()` methods and instead place our Iris code directly in our update events which we know will run every frame. Another practice this shows is starting a window somewhere and keeping it open through all weapons before closing it and the end of the update. Therefore, we can place lots of different widgets in one window and keep everything organised. The showcase by [@Boogle](https://x.com/LeBoogle/status/1772384187426709879) shows off Iris used exactly like this, but with an actual working system. * [General Game Lifecycle](https://sirmallard.github.io/Iris/docs/about/cycle#general-game-lifecycle) * [Iris Lifecycle](https://sirmallard.github.io/Iris/docs/about/cycle#iris-lifecycle) * [Demonstration](https://sirmallard.github.io/Iris/docs/about/cycle#demonstration) --- # Understanding the Configuration | Iris [Skip to main content](https://sirmallard.github.io/Iris/docs/about/config#__docusaurus_skipToContent_fallback) On this page Each widget has a range of styling options to change its visual appearances, whether that be the colours or sizing. These can either be configured for all widgets as a global style, or on a per-widget basis. There are also some global properties which may need to be changed before Iris is initialised, because they affect the entire UI. The config is kept as a key-value pairs in a global table, viewable under `Iris.Internal._config`. The file `config.lua` contains a few different configurations (light, dark, big, small), of which some are loaded by default when first requiring Iris. You can use this file to refer to the default configuration, which are under 'colorDark', 'sizeDefault' and 'utilityDefault' (these 'categories' are purely to make the organisation clearer). Global[​](https://sirmallard.github.io/Iris/docs/about/config#global "Direct link to Global") ---------------------------------------------------------------------------------------------- To change the global configuration, you can use `Iris.UpdateGlobalConfig()` with a key-value pair table containing a set of configuration names and values which you would like to change. You do not need to change all the values, since everything already has a default one. If you would like to use an existing configuration (such as light mode), you can refer to `Iris.TemplateConfig` which is the `config.lua` file. Iris.UpdateGlobalConfig(Iris.TemplateConfig.colorLight) -- change to the template light modeIris.UpdateGlobalConfig({ RichText = true, IgnoreGuiInset = true, ScreenInsets = Enum.ScreenInsets.None, TextColor = Color3.fromRGB(85, 49, 218), TextSize = 16, FramePadding = Vector2.new(2, 1),}) -- specify the specific properties to change-- this can be specified before Iris is even initialisedIris.Init() Warn `Iris.UpdateGlobalConfig()` should be called sparingly, normally when Iris is first initialised, or when a specific configuration is manually made and never every frame, since it requires redrawing every widget, which involves destroying and then creating every instance. Per-Widget[​](https://sirmallard.github.io/Iris/docs/about/config#per-widget "Direct link to Per-Widget") ---------------------------------------------------------------------------------------------------------- To change the config for a specific widget, you can use `Iris.PushConfig()` and `Iris.PopConfig()` around the widget. Internally, this updates the config with anything you pushed and then removes it once you pop. This also stacks, so child widgets can be entirely different to their parent. Iris.PushConfig({ TextWrapped = true, ContentWidth = UDim.new(0.8, 0), FrameBgColor = Color3.fromRGB(41, 74, 122), FrameBgHoveredColor = Color3.fromRGB(66, 150, 250), FrameBgActiveColor = Color3.fromRGB(66, 150, 250),})do -- create any widgets with this configendIris.PopConfig() Warn When a widget's config is changed between frames, Iris has to destroy and then create the widget from scratch, so constantly changing the configuration on lots of widgets may decrease performance significantly. However, if this the config stays the same, Iris does not require a redraw. Configuration[​](https://sirmallard.github.io/Iris/docs/about/config#configuration "Direct link to Configuration") ------------------------------------------------------------------------------------------------------------------- ### Colours[​](https://sirmallard.github.io/Iris/docs/about/config#colours "Direct link to Colours") Every config option has both a colour and a transparency. The colour will always end with `Color` and the transparency will always end with `Transparency`, where `0` is fully opaque and `1` is fully transparent. Many colours will be in pairs or trios, as the normal, the `Hovered` and the `Active`. Below the columns have been combined to put colour and transparency in the same row, and just the suffix of the key. To change a value, append the key with either `Color` or `Transparency`, ie. the colour of a hovering button would be `ButtonHovered` .. `Color` is `ButtonHoveredColor`. | Key | Color | Transparency | Notes | | --- | --- | --- | --- | | Text | `Color3.fromRGB(255, 255, 255)` | `0` | | | TextDisabled | `Color3.fromRGB(128, 128, 128)` | `0` | InputText placeholder and Menu shortcuts | | BorderColor | `Color3.fromRGB(110, 110, 125)` | `0.5` | Any Window or widget border | | BorderActive | `Color3.fromRGB(160, 160, 175)` | `0.3` | Active Window or Tooltip borders | | WindowBg | `Color3.fromRGB(15, 15, 15)` | `0.06` | | | PopupBg | `Color3.fromRGB(20, 20, 20)` | `0.06` | | | ScrollbarGrab | `Color3.fromRGB(79, 79, 79)` | `0` | | | TitleBg | `Color3.fromRGB(10, 10, 10)` | `0` | Title bar of non-active Windows | | TitleBgActive | `Color3.fromRGB(41, 74, 122)` | `0` | Title bar of active Window | | TitleBgCollapsed | `Color3.fromRGB(0, 0, 0)` | `0.5` | Title bar of collapsed Window | | MenubarBg | `Color3.fromRGB(36, 36, 36)` | `0` | | | FrameBg | `Color3.fromRGB(41, 74, 122)` | `0.46` | Many widgets | | FrameBgHovered | `Color3.fromRGB(66, 150, 250)` | `0.46` | | | FrameBgActive | `Color3.fromRGB(66, 150, 250)` | `0.33` | | | Button | `Color3.fromRGB(66, 150, 250)` | `0.6` | Any buttons | | ButtonHovered | `Color3.fromRGB(66, 150, 250)` | `0` | | | ButtonActive | `Color3.fromRGB(15, 135, 250)` | `0` | | | Image | `Color3.fromRGB(255, 255, 255)` | `0` | Image tint colour, white for normal | | SliderGrab | `Color3.fromRGB(66, 150, 250)` | `0` | Slider widgets | | SliderGrabActive | `Color3.fromRGB(117, 138, 204)` | `0` | | | Header | `Color3.fromRGB(66, 150, 250)` | `0.69` | Selectable, Trees and Menus | | HeaderHovered | `Color3.fromRGB(66, 150, 250)` | `0.2` | | | HeaderActive | `Color3.fromRGB(66, 150, 250)` | `0` | | | Tab | `Color3.fromRGB(46, 89, 148)` | `0.14` | TabBar widget | | TabHovered | `Color3.fromRGB(66, 150, 250)` | `0.2` | | | TabActive | `Color3.fromRGB(51, 105, 173)` | `0` | | | SelectionImageObject | `Color3.fromRGB(255, 255, 255)` | `0.8` | Internal | | SelectionImageObjectBorder | `Color3.fromRGB(255, 255, 255)` | `0` | | | TableBorderStrong | `Color3.fromRGB(79, 79, 89)` | `0` | Table outside border | | TableBorderLight | `Color3.fromRGB(59, 59, 64)` | `0` | Table insider border | | TableRowBg | `Color3.fromRGB(0, 0, 0)` | `1` | Row background | | TableRowBgAlt | `Color3.fromRGB(255, 255, 255)` | `0.94` | Alternating row background | | NavWindowingHighlight | `Color3.fromRGB(255, 255, 255)` | `0.3` | Unused | | NavWindowingDimBg | `Color3.fromRGB(204, 204, 204)` | `0.65` | Unused | | Separator | `Color3.fromRGB(110, 110, 128)` | `0.5` | | | CheckMark | `Color3.fromRGB(66, 150, 250)` | `0` | Checkbox and RadioButton | | PlotLines | `Color3.fromRGB(156, 156, 156)` | `0` | | | PlotLinesHovered | `Color3.fromRGB(255, 110, 89)` | `0` | | | PlotHistogram | `Color3.fromRGB(230, 179, 0)` | `0` | | | PlotHistogramHovered | `Color3.fromRGB(255, 153, 0)` | `0` | | | ResizeGrip | `Color3.fromRGB(66, 150, 250)` | `0.8` | Window resize grips | | ResizeGripHovered | `Color3.fromRGB(66, 150, 250)` | `0.33` | | | ResizeGripActive | `Color3.fromRGB(66, 150, 250)` | `0.05` | | | Hover | `Color3.fromRGB(255, 255, 0)` | `0.1` | Unused | ### Sizing[​](https://sirmallard.github.io/Iris/docs/about/config#sizing "Direct link to Sizing") Sizing is either handled in pixel terms, as a number or Vector2, or as a UDim for both scale and pixels. ContentWidth is seen most notably on any widget which does not have a fixed widget, but instead a scaling item on the left and then the text on the right, such as for Input widgets. By default, the 'boxes' on the left will take up 65% of the total width, leaving 35% for the text. This can be configured for the 'boxes' to take up the entire width. | Key | Value | Notes | | --- | --- | --- | | ItemWidth | `UDim.new(1, 0)` | Width of any widget which does not have a fixed size such as Plots, Table, Trees, Inputs | | ContentWidth | `UDim.new(0.65, 0)` | Proportion of a full-width widget to be taken up by the content against text, such as Inputs, Plots, Combos | | ContentHeight | `UDim.new(0, 0)` | Minimum height of widgets | | WindowPadding | `Vector2.new(8, 8)` | Padding between Window border and content | | WindowResizePadding | `Vector2.new(6, 6)` | Sizes of window resize corners and edges | | FramePadding | `Vector2.new(4, 3)` | Padding between a frame edge and content | | ItemSpacing | `Vector2.new(8, 4)` | Spacing between sequential items, such as vertical space within a Window or Tree | | ItemInnerSpacing | `Vector2.new(4, 4)` | Spacing between parts of the same widget, such as horizontal space between boxes in Input widgets | | CellPadding | `Vector2.new(4, 2)` | Table cell padding | | DisplaySafeAreaPadding | `Vector2.new(0, 0)` | Padding around a window when moving | | SeparatorTextPadding | `Vector2.new(20, 3)` | | | IndentSpacing | `21` | | | TextFont | `Font.fromEnum(Enum.Font.Code)` | | | TextSize | `13` | | | FrameBorderSize | `0` | | | FrameRounding | `0` | | | GrabRounding | `0` | | | WindowRounding | `0` | Not implemented | | WindowBorderSize | `1` | | | WindowTitleAlign | `Enum.LeftRight.Left` | | | PopupBorderSize | `1` | | | PopupRounding | `0` | | | ScrollbarSize | `7` | | | GrabMinSize | `10` | Min pixel width of a grab bar | | SeparatorTextBorderSize | `3` | | | ImageBorderSize | `2` | | ### Others[​](https://sirmallard.github.io/Iris/docs/about/config#others "Direct link to Others") Other config options available, some of which should be defined before initialisation and then left unchanged. The RichText option will allow any text instance to support rich text. Equivalent with TextWrapped and these both rely on Roblox to handle support for this. UseScreenGUIs will determine whether the root UI instances are ScreenGUIs or Frames. This is useful for when Iris is put inside existing UI, such as plugins or stories. ScreenInsets is applied first, so make sure that IgnoreGuiInset agrees with the value (false when CoreUISafeInsets, true otherwise). | Key | Value | Notes | | --- | --- | --- | | UseScreenGUIs | `true` | Whether to use ScreenGUIs as the top level widget, or Frames instead. | | ScreenInsets | `Enum.ScreenInsets.CoreUISafeInsets` | Type of screenInset for ScreenGUIs, useful for mobile. | | IgnoreGuiInset | `false` | If using ScreenGUIs | | Parent | `nil` | Overrides the parent of the next widget, when creating | | RichText | `false` | Text instances support RichText | | TextWrapped | `false` | Text instances will wrap text | | DisplayOrderOffset | `127` | Root widget offset, to draw over other UI | | ZIndexOffset | `0` | Unused | | MouseDoubleClickTime | `0.30` | Time for a double-click, in seconds | | MouseDoubleClickMaxDist | `6.0` | Distance threshold to stay in to validate a double-click, in pixels | * [Global](https://sirmallard.github.io/Iris/docs/about/config#global) * [Per-Widget](https://sirmallard.github.io/Iris/docs/about/config#per-widget) * [Configuration](https://sirmallard.github.io/Iris/docs/about/config#configuration) * [Colours](https://sirmallard.github.io/Iris/docs/about/config#colours) * [Sizing](https://sirmallard.github.io/Iris/docs/about/config#sizing) * [Others](https://sirmallard.github.io/Iris/docs/about/config#others) --- # Understanding State | Iris [Skip to main content](https://sirmallard.github.io/Iris/docs/about/states#__docusaurus_skipToContent_fallback) On this page An Iris State object is simply a table containg a value, and an array of connected widgets. It provides functions to get or set the value, the latter of which will update any widgets UI that are dependent on that state. Functions can also be connected which will be fired whenever the value changes. A state object ultimately attempts to copy the behaviour that a pointer would do in other languages, but is not possible in native Luau. A Luau table is the best option, because it is passed by reference. Types of State[​](https://sirmallard.github.io/Iris/docs/about/states#types-of-state "Direct link to Types of State") ---------------------------------------------------------------------------------------------------------------------- Iris provides multiple different types of State objects, suited for different needs. ### State[​](https://sirmallard.github.io/Iris/docs/about/states#state "Direct link to State") The base and most common state type, which implements the basically functionality of any state object. ### WeakState[​](https://sirmallard.github.io/Iris/docs/about/states#weakstate "Direct link to WeakState") A WeakState is very similar to State, except that every time it is called by ID, using `Iris.WeakState()`, all connected widgets and functions are removed, whilst keeping the value. This is useful if you need to disconnect any widgets from a state, so that they no longer update, whilst also keeping the existing value. ### VariableState[​](https://sirmallard.github.io/Iris/docs/about/states#variablestate "Direct link to VariableState") A VariableState takes both a value, and a function which gives the new value of the state whenever it is changed. This is designed for when you have a variable within a file, and want to link it to a state object. By default, when the function is called, if the variable and state are different, it will choose the local variable value. But if the state is changed, it will use the callback which is designed to update the local variable. This is best shown with an example: local myNumber = 5local state = Iris.VariableState(myNumber, function(value) myNumber = valueend)Iris.DragNum({ "My number" }, { number = state }) Here we create a state for a DragNum. If we update the value of `myNumber` within the code earlier, it will update the state value. And if we drag the widget, and update the state, it will call our callback, where we update the value of `myNumber`. ### TableState[​](https://sirmallard.github.io/Iris/docs/about/states#tablestate "Direct link to TableState") A TableState acts like VariableState, but takes a table and index so that whenever the table value changes, the state changes and vice versa. Because tables are shared, we do not need to provide a function to update the table value, and is instead handled internally. We can see this with an example: local data = { myNumber = 5}local state = Iris.TableState(data, "myNumber")Iris.DragNum({ "My number" }, { number = state }) A third argment provides extra functionality, allowing us to call a function before updating the table value, which can be used when we need to change some other values, for example when enabling or disabling a class. ### ComputedState[​](https://sirmallard.github.io/Iris/docs/about/states#computedstate "Direct link to ComputedState") ComputedState takes an existing state and a function which will convert the value of one state to a new one. We can use this to ensure that a state always stays dependent on another state. * [Types of State](https://sirmallard.github.io/Iris/docs/about/states#types-of-state) * [State](https://sirmallard.github.io/Iris/docs/about/states#state) * [WeakState](https://sirmallard.github.io/Iris/docs/about/states#weakstate) * [VariableState](https://sirmallard.github.io/Iris/docs/about/states#variablestate) * [TableState](https://sirmallard.github.io/Iris/docs/about/states#tablestate) * [ComputedState](https://sirmallard.github.io/Iris/docs/about/states#computedstate) --- # Understanding Events | Iris [Skip to main content](https://sirmallard.github.io/Iris/docs/about/events#__docusaurus_skipToContent_fallback) Each widget has a number of events connected to it. You can see these events on the [API page](https://sirmallard.github.io/Iris/docs/about/api/Iris) . Certain events will happen once, such as a window being collapsed or a button being clicked. Other events can be continuous, such as a widget being hovered. Each event is a function which returns a boolean value for whether the event has happened that frame or not. To listen to an event, use the following: local button = Iris.Button({ "Please click me!" })if button.clicked() then print("The button was clicked!")end Events will fire the frame after the initial action happened. This is so that any changes caused by that event can propogate visually. For example on a checkbox: * \[Frames 1 - 60\] The mouse is elsewhere. * \[Frames 61 - 80\] The user is moving their moues towards the checkbox. * \[Frame 81 - 100\] The mouse enters the checkbox. The .hovered() event fires because this event will fire on the frame. * \[Frame 101\] The user presses MouseButton1 down on the checkbox. * \[Frame 102\] The user releases the MouseButton1. * \[Frame 103\] The checkbox tick appears. The .checked() event fires. ---