Welcome to the Isotope Docs.
This is the official documentation for the Isotope UI Library, a Roblox Lua UI framework. It gives you a full set of UI elements for building script interfaces fast, without boilerplate.
The library handles everything: window creation, tabs, elements, notifications, keybind tracking, a radial menu, a topbar, config saving, startup animations, a watermark, and more. Every element returns an object you can call :Set() on to update it at runtime.
Note: The library uses writefile, readfile, isfile, and makefolder for config saving. These are optional, all other features work without them.
Installation
Load the library with loadstring and game:HttpGet in your executor.
local Isotope = loadstring(game:HttpGet("https://raw.githubusercontent.com/GetIsotope/GetIsotope.github.io/refs/heads/main/Isotope.lua"))()
Legacy
If you encounter issues with the current release, load the previous stable version instead.
local Isotope = loadstring(game:HttpGet("https://raw.githubusercontent.com/GetIsotope/GetIsotope.github.io/refs/heads/main/IsotopeLegacy.lua"))()
Script order matters. Always follow this structure.
local Isotope = loadstring(game:HttpGet("https://raw.githubusercontent.com/Isotope/Isotope.github.io/refs/heads/main/Isotope.lua"))()
Isotope.ShowTopbar = true
Isotope.ShowRadial = true
Isotope.RadialHotkey = Enum.KeyCode.Z
Isotope.RadialMode = "hold"
Isotope.ShowKeybindList = true
local Window = Isotope:Window({
Name = "My Script"
})
local wm = Isotope:Watermark("My Script")
wm:Field("Map", function() return game:GetService("Players").LocalPlayer:GetAttribute("Map") or "Lobby" end)
local Tab = Window:Tab({
Name = "Main",
Icon = "rbxassetid://4483345998"
})
Tab:Toggle({
Name = "Infinite Jump",
Default = false,
Callback = function(state) print(state) end
})
Isotope:Init()
Important: Isotope.ShowTopbar, Isotope.ShowRadial, and other feature flags must be set before Isotope:Window(). The library auto-calls Isotope:Init() via task.defer, but calling it explicitly at the end is fine.
Theming
Five built-in themes ship with the library. Custom themes can be registered before the window is created.
Built-in Themes
Available names: Dark, Light, Midnight, Crimson, Forest.
local Window = Isotope:Window({
Name = "My Script",
Theme = "Midnight"
})
Custom Themes
Register with Isotope.Themes:Add() before Isotope:Window(). Any keys you omit fall back to Dark theme defaults.
Isotope.Themes:Add("Neon", {
Main = Color3.fromRGB(5, 5, 10),
Second = Color3.fromRGB(10, 10, 20),
Stroke = Color3.fromRGB(0, 255, 180),
Divider = Color3.fromRGB(0, 255, 180),
Text = Color3.fromRGB(200, 255, 240),
TextDark = Color3.fromRGB(80, 180, 150),
Accent = Color3.fromRGB(0, 255, 180),
})
local Window = Isotope:Window({
Name = "My Script",
Theme = "Neon"
})
Switch Theme at Runtime
Window:SetTheme("Light")
Note: Isotope:SetTheme() does not exist. Always call it on the window object: Window:SetTheme(name).
Window
The window is the root container for your entire UI. Create it with Isotope:Window() after setting any feature flags.
local Window = Isotope:Window({
Name = "My Script",
Theme = "Dark",
Startup = true,
StartupAnim = "Blob",
StartupText = "Loading...",
StartupIcon = "rbxassetid://...",
CloseAnim = "Blob",
MinimizeAnim = "Blob",
ReopenKey = Enum.KeyCode.RightShift,
CloseCallback = function() print("closed") end,
SaveConfig = true,
ConfigFolder = "MyScript",
Config = tostring(game.GameId),
ScriptKey = "my-unique-key-2025",
ShowDisplayName = true,
ShowUsername = true,
KeySystem = true,
Key = "my-secret-key",
KeyLink = "https://example.com/getkey",
KeyDeniedCallback = function()
print("wrong key")
end
})
Window Options
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "IsotopeUI" | Title shown in the top bar |
| Theme | string | "Dark" | Theme name |
| SaveConfig | boolean | false | Enable auto-save and load of flagged values |
| ConfigFolder | string | Window Name | Folder name for config files |
| Config | string | game.GameId | Config filename without .json |
| ScriptKey | string | "" | Unique key stamped into saved configs to prevent cross-script loading |
| Startup | boolean | false | Play a startup animation on open |
| StartupAnim | string | "Fade" | Blob, Fade, Typewriter, Bounce, Unfold |
| StartupText | string | "" | Text shown during Typewriter animation |
| StartupIcon | string | "" | Asset ID shown during startup animation |
| CloseAnim | string | "Shrink" | Animation when X is clicked: Shrink or Blob |
| MinimizeAnim | string | "Slide" | Animation when minimizing: Slide or Blob |
| ReopenKey | KeyCode | RightShift | Key to reopen after closing or minimizing |
| CloseCallback | function | nil | Called when the X button is pressed |
| ShowDisplayName | boolean | false | Show player display name in sidebar footer |
| ShowUsername | boolean | false | Show @username in sidebar footer |
| KeySystem | boolean | false | Gate the window behind a key prompt. → docs |
| Key | string | "" | The correct key string the user must enter. |
| KeyLink | string | nil | URL copied to clipboard when "Get Key" is clicked |
| KeyDeniedCallback | function | nil | Fired when the user closes the key prompt without the correct key |
Window Methods
| Method | Description |
|---|---|
| Window:Tab(config) | Create a new tab. Returns a tab object. |
| Window:TabSection(name) | Insert a collapsible label group in the sidebar. → docs |
| Window:SetTheme(name) | Switch theme by name at runtime. |
| Window:SetAccentColor(color) | Change the accent Color3 at runtime. |
| Window:SetTitle(text) | Update the window title label. → docs |
| Window:Toast(text, icon?) | Show a floating pill toast. → docs |
| Window:Lock(message?) | Overlay the UI with a blocker. → docs |
| Window:Unlock() | Remove the lock overlay. |
| Window:Flash(color?) | Pulse the window border. → docs |
| Window:SetReopenKey(key) | Change the reopen key at runtime. |
| Window:SetCloseAnim(anim) | Change close animation at runtime. |
| Window:SetMinimizeAnim(anim) | Change minimize animation at runtime. |
| Window:SetDisplayName(text) | Override the display name label. |
| Window:SetUsername(text) | Override the username label. |
| Window:SetAvatarText(text) | Set a small sub-label below the avatar. |
| Window:OpenProfileView(btns) | Open the fullscreen profile panel. |
| Window:SetUserSectionEnabled(bool) | Show or hide the user section at runtime. |
| Window:SetAvatarMenuEnabled(bool) | Enable right-click on avatar to open profile. |
| Window:AddAvatarMenuItem(name, cb, icon?) | Add an item to the avatar right-click profile menu. |
| Window:ClearAvatarMenu() | Remove all avatar menu items. |
| Window:GetAvatarFrame() | Returns the avatar instance for custom styling. |
| Window:GetUserSectionContainer() | Returns the user section Frame for advanced layout. |
Button
A clickable row that fires a callback. The returned object has a :Set() method to change the label text at runtime.
local btn = Tab:Button({
Name = "Teleport to Spawn",
Callback = function()
game.Players.LocalPlayer.Character:SetPrimaryPartCFrame(CFrame.new(0, 5, 0))
end
})
btn:Set("New Label")
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Button" | Label shown on the row |
| Callback | function | nil | Called when clicked. Runs in a task.spawn. |
Toggle
A checkbox element with a boolean value. Fires a callback with the new value on change.
local toggle = Tab:Toggle({
Name = "Infinite Jump",
Default = false,
Flag = "InfiniteJump",
Save = true,
Color = Color3.fromRGB(0, 170, 255),
Confirm = false,
Locked = false,
Callback = function(value) print("Infinite Jump:", value) end
})
toggle:Set(true)
toggle:Lock()
toggle:Unlock()
print(toggle.Value)
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Toggle" | Label shown on the row |
| Default | boolean | false | Initial state |
| Flag | string | nil | Key in Isotope.Flags |
| Save | boolean | false | Include in config save |
| Color | Color3 | theme Accent | Checkbox accent color when enabled |
| Confirm | boolean | false | Show inline confirmation before firing. → docs |
| Locked | boolean | false | Start in locked state. → docs |
| Callback | function | nil | Called with new boolean value on change |
Slider
A draggable range input. Supports min, max, default, increment, and an optional value label suffix. Double-click the track to type a value directly.
local slider = Tab:Slider({
Name = "Walk Speed",
Min = 16,
Max = 250,
Default = 16,
Increment = 1,
ValueName = "studs/s",
Flag = "WalkSpeed",
Save = true,
Color = Color3.fromRGB(9, 149, 98),
Callback = function(value)
game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = value
end
})
slider:Set(50)
print(slider.Value)
Tip: Double-clicking the slider track opens an inline text input so you can type an exact value instead of dragging.
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Slider" | Label shown above the track |
| Min | number | 0 | Minimum value |
| Max | number | 100 | Maximum value |
| Default | number | 50 | Starting value |
| Increment | number | 1 | Snapping increment |
| ValueName | string | "" | Suffix appended to the displayed number |
| Flag | string | nil | Key in Isotope.Flags |
| Save | boolean | false | Include in config save |
| Color | Color3 | theme Accent | Fill and border color of the track |
| Callback | function | nil | Called with the new number on drag |
Dropdown
A collapsible list of options. Click to expand, click an option to select. Shows up to 5 options before scrolling.
local dropdown = Tab:Dropdown({
Name = "Select Game Mode",
Options = { "Normal", "Hard", "Insane" },
Default = "Normal",
Flag = "GameMode",
Save = true,
Callback = function(value)
print("Selected:", value)
end
})
dropdown:Set("Hard")
dropdown:Refresh({ "Easy", "Normal", "Hard" }, true)
print(dropdown.Value)
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Dropdown" | Label shown in the header |
| Options | table | {} | Array of string options |
| Default | string | "" | Initially selected option |
| Flag | string | nil | Key in Isotope.Flags |
| Save | boolean | false | Include in config save |
| Callback | function | nil | Called with selected string on change |
MultiDropdown
A collapsible list where multiple options can be selected simultaneously. The header shows a count when more than two are selected.
local multi = Tab:MultiDropdown({
Name = "Active Effects",
Options = { "Speed", "Jump", "Fly", "NoClip" },
Default = { "Speed" },
Flag = "ActiveEffects",
Save = true,
Callback = function(values)
print(table.concat(values, ", "))
end
})
multi:Set({ "Speed", "Fly" })
print(multi.Value)
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Multi Dropdown" | Label shown in the header |
| Options | table | {} | Array of string options |
| Default | table | {} | Array of initially selected strings |
| Flag | string | nil | Key in Isotope.Flags |
| Save | boolean | false | Include in config save |
| Callback | function | nil | Called with the full selected values table on any change |
TextBox
A text input field. Clicking the row opens it for typing. The callback fires when focus is lost.
Tab:TextBox({
Name = "Set Player Name",
Default = "",
TextDisappear = true,
Callback = function(text) print("Submitted:", text) end
})
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Input" | Label on the left side of the row |
| Default | string | "" | Pre-filled text value |
| TextDisappear | boolean | false | Clears the box after focus is lost |
| Callback | function | nil | Called with the text string on focus lost |
Bind
A keybind element. Click the row to enter binding mode, then press any key. Supports modifier keys and hold mode.
local bind = Tab:Bind({
Name = "Toggle UI",
Default = Enum.KeyCode.E,
Hold = false,
Modifier = Enum.KeyCode.LeftControl,
Flag = "ToggleUIBind",
Save = true,
Callback = function() print("Bind fired!") end
})
bind:Set(Enum.KeyCode.F)
print(bind.Value)
Hold Mode: When Hold = true, the callback fires with true on key down and false on release.
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Bind" | Label shown on the row |
| Default | KeyCode | KeyCode.Unknown | Default key to bind |
| Hold | boolean | false | Fire on hold and release instead of single press |
| Modifier | KeyCode / table | nil | Required modifier key(s) held alongside the bind |
| Flag | string | nil | Key in Isotope.Flags |
| Save | boolean | false | Include in config save |
| Callback | function | nil | Fires when the bind is triggered |
Colorpicker
A collapsible HSV color picker with a saturation/value field and a hue strip.
local cp = Tab:Colorpicker({
Name = "Trail Color",
Default = Color3.fromRGB(0, 170, 255),
Flag = "TrailColor",
Save = true,
Callback = function(color) print("Color:", color) end
})
cp:Set(Color3.fromRGB(255, 0, 100))
print(cp.Value)
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Colorpicker" | Label shown in the header |
| Default | Color3 | RGB(255,255,255) | Initial color |
| Flag | string | nil | Key in Isotope.Flags |
| Save | boolean | false | Include in config save |
| Callback | function | nil | Called with Color3 on change |
Stepper
A discrete option selector with previous and next arrow buttons. Arrows dim at the first or last option.
local stepper = Tab:Stepper({
Name = "Quality",
Options = { "Low", "Medium", "High", "Ultra" },
Default = "Medium",
Flag = "Quality",
Save = true,
Callback = function(value) print("Quality:", value) end
})
stepper:Set(4)
print(stepper.Value)
Note: :Set() takes a 1-based index into the Options table, not the value string itself.
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Stepper" | Label on the left |
| Options | table | {} | Ordered array of string options |
| Default | string | Options[1] | Initially selected option value string |
| Flag | string | nil | Key in Isotope.Flags |
| Save | boolean | false | Include in config save |
| Callback | function | nil | Called with the selected value string on change |
Label
A static text row. Update the text at runtime with :Set(). Automatically wraps and resizes.
local lbl = Tab:Label("Status: Idle")
lbl:Set("Status: Running")
Paragraph
A two-line block with a bold title and a wrapped body. Automatically resizes to fit the content.
local para = Tab:Paragraph({
Name = "Changelog v1.2",
Content = "Fixed infinite jump not working after respawn. Added speed slider.",
})
para:Set("Updated Title", "Updated body text.")
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Paragraph" | Bold title at the top |
| Content | string | "" | Wrapped body text below the divider |
ProgressBar
A visual progress indicator with a fill bar and a label. The value is a float between 0 and 1.
local pb = Tab:ProgressBar("Download Progress", 0)
task.spawn(function()
for i = 1, 10 do
task.wait(0.2)
pb:Set(i / 10, "Downloading... " .. (i * 10) .. "%")
end
pb:Set(1, "Complete!")
end)
KeyValue
A compact table of key-value pairs. Each row shows a left-aligned key label and a right-aligned value.
local kv = Tab:KeyValue({
Name = "Player Stats",
Pairs = {
{ "Username", game.Players.LocalPlayer.Name },
{ "User ID", tostring(game.Players.LocalPlayer.UserId) },
{ "Team", "None" },
}
})
kv:Set("Team", "Red Team")
kv:SetAll({ { "Ping", "42ms" }, { "FPS", "60" } })
Methods
| Method | Description |
|---|---|
| :Set(key, value) | Update the value of a specific key by its label text. |
| :SetAll(pairs) | Destroy all existing rows and rebuild with a new pairs table. |
Section
A labeled group that contains other elements. Sections automatically resize to fit their children.
local sec = Tab:Section("Movement")
sec:Toggle({
Name = "Infinite Jump",
Default = false,
Callback = function(v) print(v) end,
})
sec:Slider({
Name = "Walk Speed",
Min = 16,
Max = 250,
Default = 16,
Callback = function(v)
game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = v
end
})
Sections support all element types: :Button(), :Toggle(), :Slider(), :Dropdown(), :MultiDropdown(), :TextBox(), :Bind(), :Colorpicker(), :Label(), :Paragraph(), :ProgressBar(), :Stepper(), :KeyValue().
Separator
A thin horizontal dividing line. Can optionally display a centered text label between two line segments.
Tab:Separator()
Tab:Separator("Advanced Settings")
Grid
A fixed-column grid layout container. Elements placed inside arrange themselves into equal-width columns.
local grid = Tab:Grid({ columns = 3 })
grid:Button("Teleport", function() print("Teleport") end)
grid:Button("Kill All", function() print("Kill All") end)
grid:Button("Rejoin", function() print("Rejoin") end)
Note: Grid objects only support :Button(), :Toggle(), and :Label(). For other elements use a Section.
Notify
Sends a stacked notification from the bottom-right. Right-click to dismiss early.
Isotope:Notify({
Name = "Config Loaded",
Content = "Your saved config has been applied.",
Time = 5,
Image = "rbxassetid://4384403532",
DurationColor = Color3.fromRGB(0, 200, 120),
SoundId = 452267918,
OnClick = function() print("clicked") end,
})
Isotope:Notify("Simple message", 3)
Common mistake: The duration key is Time, not Duration.
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Notification" | Bold title line |
| Content | string | "" | Secondary body text |
| Time | number | 5 | Duration in seconds before auto-dismiss |
| Image | string | rbxassetid://4384403532 | Icon asset ID |
| DurationColor | Color3 | RGB(0,170,255) | Color of the side timer drain bar |
| SoundId | string / number | nil | Sound played when the notification appears |
| OnClick | function | nil | Fires when the notification is left-clicked |
CNotify
An advanced notification with hover-to-pause timer, right-click dismiss, and an optional Additional field that opens a fullscreen blurred modal on click.
Isotope:CNotify({
Name = "Update Available",
Content = "Version 2.0 is out. Click for details.",
Additional = "Full changelog text here. Opens as a fullscreen modal when clicked.",
Time = 12,
DurationColor = Color3.fromRGB(0, 170, 255),
Image = "rbxassetid://4384403532",
SoundId = 452267918,
OnClick = function() print("CNotify clicked") end,
})
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Advanced Notification" | Bold title |
| Content | string | "" | Short body text shown in the card |
| Additional | string | "" | Long-form text shown in the fullscreen modal on click |
| Time | number | 5 | Duration. Timer pauses while hovering. |
| DurationColor | Color3 | RGB(0,255,170) | Side timer bar color |
| Image | string | rbxassetid://4384403532 | Icon asset ID |
| SoundId | string / number | nil | Sound played on appear |
| OnClick | function | nil | Fires on left-click before modal opens |
Modal
A fullscreen blurred overlay that appears immediately without any click required. Clicking anywhere dismisses it.
Isotope:Modal({
Name = "Warning",
Content = "Your saved config is from a different version.",
Additional = "Delete the config file and restart to reset your settings.",
DurationColor = Color3.fromRGB(255, 160, 0),
OnClose = function() print("Modal dismissed") end,
})
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Notice" | Bold title inside the card |
| Content | string | "" | Primary body text |
| Additional | string | "" | Secondary smaller text below the divider |
| DurationColor | Color3 | theme Accent | Color of the pulsing top accent bar and card stroke |
| OnClose | function | nil | Called when the user dismisses the modal |
Toast
A small floating pill notification centered at the top of the screen. It slides in, waits 2 seconds, then fades out automatically.
Window:Toast("Settings saved!")
Window:Toast("Teleported!", "rbxassetid://137352523558390")
| Argument | Type | Default | Description |
|---|---|---|---|
| text | string | "" | Message displayed in the pill |
| icon | string | nil | Optional asset ID placed left of the text |
Watermark
A small floating bar in the top-left showing the script name, current time, live FPS, and any custom fields you add. Fully draggable and theme-aware.
local wm = Isotope:Watermark("My Script")
wm:Field("Map", function()
return game:GetService("Players").LocalPlayer:GetAttribute("Map") or "Lobby"
end)
wm:Field("Mode", "Ranked")
wm:SetField("Mode", "Casual")
wm:Title("My Script v2")
wm:Hide()
wm:Show()
wm:Destroy()
Note: Call Isotope:Watermark() after Isotope:Window() so the active theme is already set. The watermark always picks up Isotope._activeTheme.
Built-in Fields
The watermark always shows three built-in fields separated by | dividers: the script title (accent colored), the current local time (HH:MM:SS), and live FPS. Custom fields you add appear after these.
Methods
| Method | Description |
|---|---|
| :Title(text) | Update the title label on the left. |
| :Field(name, valueFn) | Add a custom field. valueFn can be a function (called every second for live updates) or a static string. |
| :SetField(name, value) | Update a named field's text and stop any live-update function on it. |
| :Hide() | Fade the watermark out. |
| :Show() | Fade the watermark back in. |
| :RefreshTheme(theme) | Apply a new theme table to the watermark. Called automatically by Window:SetTheme() if you store the wm object. |
| :Destroy() | Stop the update loop and remove the GUI. |
Topbar
An optional floating panel at the top-center of the screen showing icon buttons for every tab, a search bar, and optional owner buttons. Fully draggable and theme-aware.
Must be set before Isotope:Window().
Isotope.ShowTopbar = true
local Window = Isotope:Window({ ... })
Isotope:Init()
When more than 6 tabs are created the topbar adds a ... expand button to reveal additional rows. The built-in search panel indexes all flags, elements, and binds.
Radial Menu
A circular menu mapping each tab to a card arranged around a center point. Supports hold and toggle modes, plus five open/close animations.
Must be set before Isotope:Window().
Isotope.ShowRadial = true
Isotope.RadialHotkey = Enum.KeyCode.Q
Isotope.RadialMode = "hold"
Isotope.RadialAnim = "Bloom"
local Window = Isotope:Window({ ... })
Isotope:Init()
Isotope.RadialAnim = "Spiral"
| Property | Type | Description |
|---|---|---|
| ShowRadial | boolean | Enable the radial menu |
| RadialHotkey | KeyCode | Key that opens/closes the wheel |
| RadialMode | string | "hold" releases on key-up; "toggle" stays open until pressed again |
| RadialAnim | string | Scale, Spiral, Fan, Bloom, Unfold. Can be changed at runtime. |
Keybind List
A persistent overlay in the bottom-left showing all active binds. Updates automatically when a bind changes.
Isotope.ShowKeybindList = true
local Window = Isotope:Window({ ... })
Isotope:Init()
Flags & Config
Flags let you reference any element's value globally via Isotope.Flags["FlagName"]. When SaveConfig = true and Save = true on an element, its value is written to a JSON file and auto-loaded on the next run.
local Window = Isotope:Window({
Name = "My Script",
SaveConfig = true,
ConfigFolder = "MyScript",
Config = tostring(game.GameId),
ScriptKey = "myscript-2025",
})
Tab:Toggle({
Name = "Speed Hack",
Flag = "SpeedHack",
Save = true,
Default = false,
Callback = function(v) end,
})
print(Isotope.Flags["SpeedHack"].Value)
Isotope.Flags["SpeedHack"]:Set(true)
Isotope:Init()
Common mistake: Do not pass Config = true. Config is the filename string; SaveConfig is the boolean toggle. Set ScriptKey to prevent configs from loading in other scripts.
Startup Animations
Enable a startup animation by setting Startup = true on the window and picking an animation name.
| Name | Description |
|---|---|
| Blob | A circle expands from center, then morphs into the window shape. |
| Fade | The window fades in from transparent. |
| Typewriter | Overlay with a typing animation and progress bar. Supports StartupText and StartupIcon. |
| Bounce | The window drops in from above and bounces into position. |
| Unfold | The window expands horizontally then vertically. |
Tab Sections
Insert a collapsible label group between tabs in the sidebar. All tabs declared after a TabSection call until the next TabSection automatically belong to that section. Clicking the section header collapses or expands its tabs with a fade animation. An arrow icon rotates to indicate state.
Window:TabSection("Combat")
local AimTab = Window:Tab({ Name = "Aimbot", Icon = "rbxassetid://..." })
local EspTab = Window:Tab({ Name = "ESP", Icon = "rbxassetid://..." })
Window:TabSection("Misc")
local CfgTab = Window:Tab({ Name = "Config", Icon = "rbxassetid://..." })
No extra setup is needed. Tabs register themselves into the current section automatically based on the order they are created. Section membership is determined purely by call order.
Note: Tabs created before the first TabSection call are not part of any section and are always visible.
User Section
An optional footer at the bottom of the sidebar showing the player's avatar, display name, and username. Set Isotope.UserSection = true before Isotope:Window() to enable it.
Isotope.UserSection = true
Isotope.UserSectionRightClick = true
Isotope.USI = {
{ Name = "Discord", Callback = function() print("discord") end, Icon = "rbxassetid://4483345998" },
}
local Window = Isotope:Window({
Name = "My Script",
ShowDisplayName = true,
ShowUsername = true,
})
Window:AddAvatarMenuItem("Copy UserId", function()
if setclipboard then
setclipboard(tostring(game.Players.LocalPlayer.UserId))
Window:Toast("UserId copied!")
end
end, "rbxassetid://3944703587")
Window:SetDisplayName("Test")
Window:SetUsername("@test")
| Method | Description |
|---|---|
| Window:SetUserSectionEnabled(bool) | Show or hide the user section at runtime. |
| Window:SetAvatarMenuEnabled(bool) | Allow or disallow right-click on the avatar. |
| Window:AddAvatarMenuItem(name, cb, icon?) | Add a button to the avatar right-click profile panel. |
| Window:ClearAvatarMenu() | Remove all added avatar menu items. |
| Window:SetDisplayName(text) | Override the display name label. |
| Window:SetUsername(text) | Override the username label. |
| Window:SetAvatarText(text) | Set a small sub-label below the avatar. |
| Window:OpenProfileView(btns) | Open the fullscreen profile panel. |
| Window:GetAvatarFrame() | Returns the avatar button instance. |
| Window:GetUserSectionContainer() | Returns the user section container Frame. |
Owner Buttons
Custom icon buttons in the topbar to the right of tab buttons. Useful for Discord links or script-level actions. Supports an optional Dropdown array, when set, clicking the button opens a small dropdown menu instead of calling Callback directly. The selected option is passed to Callback as the first argument.
Must be added before Isotope:Window(), or call Isotope:Topbar(theme) again after adding them at runtime.
Isotope:AddOwnerButton({
Name = "Discord",
Icon = "rbxassetid://4483345998",
Tooltip = "Join Discord",
Color = Color3.fromRGB(88, 101, 242),
Order = 1,
Callback = function() Window:Toast("discord.gg/example") end
})
Isotope:AddOwnerButton({
Name = "Preset",
Icon = "rbxassetid://4483345998",
Tooltip = "Load Preset",
Order = 2,
Dropdown = { "Default", "Rage", "Legit", "Silent" },
Callback = function(selected)
print("Preset selected:", selected)
end
})
Isotope:ClearOwnerButtons()
| Option | Type | Default | Description |
|---|---|---|---|
| Name | string | "Button" | Internal name, not displayed |
| Icon | string | "" | Asset ID shown inside the button |
| Tooltip | string | "" | Tooltip label shown on hover |
| Color | Color3 | nil | Background and stroke color. Falls back to theme Main. |
| Order | number | 100 | Sort order. Lower = further left. |
| Dropdown | table | nil | Array of option strings. When provided, clicking opens a dropdown menu. The selected string is passed to Callback. |
| Callback | function | nil | Fires on click (no Dropdown), or fires with the selected option string (with Dropdown). |
Key System
Gate the window behind a key prompt. The prompt is animated and matches the current theme.
local Window = Isotope:Window({
Name = "My Script",
KeySystem = true,
Key = "mykey",
KeyLink = "https://linkvertise.com/getkey",
KeyDeniedCallback = function()
print("User closed without entering the correct key.")
end,
})
| Option | Type | Default | Description |
|---|---|---|---|
| KeySystem | boolean | false | Enable the key gate |
| Key | string | "" | The correct key the user must enter. |
| KeyLink | string | nil | URL copied when the user clicks "Get Key" |
| KeyDeniedCallback | function | nil | Called when the prompt is closed with an incorrect or no key |
SetTitle
Updates the window title label in the top bar at runtime.
Window:SetTitle("My Script - Wave 3")
task.wait(2)
Window:SetTitle("My Script")
Lock / Unlock
Overlays the entire UI with a semi-transparent dimmed blocker. All clicks are blocked while locked.
Window:Lock("Loading data...")
task.spawn(function()
task.wait(5)
Window:Unlock()
end)
Note: Always run the timed work inside a task.spawn(). Never call :Lock() before a task.wait() on the main thread.
Flash
Briefly pulses the window border stroke. Repeated rapid calls are safely ignored until the current flash finishes.
Window:Flash() Window:Flash(Color3.fromRGB(255, 200, 0))
Toggle Confirm
When Confirm = true is passed to a toggle, clicking it expands the row to show "Are you sure?" with Confirm and Cancel buttons.
Tab:Toggle({
Name = "Delete All Data",
Default = false,
Confirm = true,
Color = Color3.fromRGB(200, 60, 60),
Callback = function(state)
if state then clearAllData() end
end
})
Locked Toggle
When Locked = true is passed to a toggle, it starts with a lock overlay blocking interaction. Call :Lock() and :Unlock() at runtime to control it.
local t = Tab:Toggle({
Name = "Premium Feature",
Default = false,
Locked = true,
Callback = function(v) print(v) end
})
t:Unlock()
t:Lock()
Window Controls
Several window behaviors can be changed at runtime without recreating the window.
Window:SetReopenKey(Enum.KeyCode.RightControl)
Window:SetCloseAnim("Blob")
Window:SetMinimizeAnim("Blob")
Window:SetAccentColor(Color3.fromRGB(255, 100, 0))
| Method | Description |
|---|---|
| Window:SetReopenKey(key) | Change the key used to reopen after close or minimize. |
| Window:SetCloseAnim(anim) | Change close animation: "Shrink" or "Blob". |
| Window:SetMinimizeAnim(anim) | Change minimize animation: "Slide" or "Blob". |
| Window:SetAccentColor(color) | Update the accent color across registered elements. |
Destroy
Completely removes all Isotope GUIs and clears all internal state. Use this before reloading a script.
Isotope:Destroy()
Removes: IsotopeUI, IsotopeNotifications, IsotopeKeybindList, IsotopeTopbar, IsotopeRadial, IsotopeToasts. Also clears all Binds, Tabs, ElementRegistry, and OwnerButtons.