NoNameHub
ExploreResourcesAbout
Browse resources ↗
NoNameHub
💬▶

Product

  • All resources
  • How it works

Community

  • Discord
  • YouTube

Company

  • About
  • Terms of Service
  • Privacy Policy

© 2026 NoNameHub

NONAMEHUB / DOCS

Noname UI v1.16.0

Contents

OverviewInstallationQuick startProject structureLazy loadingPublic APIElementsNotificationsWatermarkThemesConfigurationDevice & mobileAdvancedMigrationTroubleshootingChangelog

Overview

Noname UI is a modular Roblox Luau UI library. v1.16.0 keeps full API compatibility with v1.12–v1.15, adds lazy loading for ~50% of the library, replaces per-element keybind listeners with a shared dispatcher, and reworks the save pipeline.

Config-file tag remains V-1.15.0 — existing configs load without migration.

Installation

lua
local NonameUI = loadstring(game:HttpGet("https://library.nonamehub.fyi/latest.lua"))()

NonameUI:Init("MyGame")
local win = NonameUI:CreateWindow({ Title = "My UI", Theme = "Dark" })

Requires loadstring and HTTP. Config persistence additionally requires writefile / readfile / isfile.

Roblox Studio

lua
local NonameUI = require(game.ReplicatedStorage["NonameUI-1.16.0"])
NonameUI:Init("MyGame")

Optional capabilities

CapabilityIf missing
writefile / readfile / isfileConfig persistence disabled (warning).
gethuiFalls back to game.CoreGui.
setclipboard / getclipboardColor HEX copy/paste disabled.
getgenvFalls back to _G.

Check via NonameUI:HasFeature("hasWriteFile").

Quick start

lua
local NonameUI = loadstring(game:HttpGet("https://library.nonamehub.fyi/latest.lua"))()
NonameUI:Init("MyGame")

local win = NonameUI:CreateWindow({
    Title = "My UI",
    Theme = "Dark",
    AutoProfile = false,
})

local tab = win:AddTab("Main", { Icon = "home" })
tab:AddLabel("Welcome")

tab:AddButton("Print Hello", function()
    print("Hello!")
    win:Notify("Clicked!", 2, { Type = "success" })
end)

tab:AddToggle("God Mode", function(state)
    print(state)
end, { Flag = "godmode" })

tab:AddSlider("Speed", 16, 100, 16, 1, function(v)
    print(v)
end, { Flag = "speed", Suffix = "studs" })

Project structure

lua
NonameUI-1.16.0/
├── init.lua                    # Entry / proxy API
├── Core/
│   ├── Context.lua             # Services, device, sizing
│   ├── Bootstrap.lua           # Init, ErrorBus, keybind dispatch, save
│   └── Window.lua              # CreateWindow, header, sidebar, watermark
├── Components/
│   ├── Primitives.lua          # Shared UI primitives (eager)
│   ├── Containers.lua          # Tabs, sections, cards (lazy)
│   ├── Notifications.lua       # Notify + ShowConfirm (lazy)
│   ├── Input/                  # Button, Toggle, Slider, Input (lazy)
│   ├── Selection/              # Dropdown, Segmented, ColorPicker (lazy)
│   ├── Display/                # Label, Search (lazy)
│   └── Keyboard/               # Keybind variants (lazy)
├── Modules/
│   ├── ThemeManager.lua
│   └── SaveManager.lua
├── Utility/                    # Signals, Naming, MemoryPool, AsyncIO,
│                               # RateLimit, Migrations, ThemeRegistry,
│                               # GestureDetector
└── Extras/
    └── KeySystem.lua           # Optional; not auto-loaded

Lazy loading

13 modules load at Init(). The rest load on first use and stay cached for the session.

Eager

lua
Utility/Signals, Naming, MemoryPool, RateLimit,
Migrations, AsyncIO, ThemeRegistry, GestureDetector
Modules/ThemeManager, SaveManager
Core/Context, Bootstrap
Components/Primitives

Deferred

lua
Core/Window                     → first :CreateWindow()
Components/Containers           → alongside Window
Components/Notifications        → alongside Window
Components/Display/Search       → first Ctrl+K / search button
Components/Display/Label        → first tab:AddLabel()
Components/Input/Button         → first tab:AddButton()
Components/Input/Toggle         → first tab:AddToggle()
Components/Input/Slider         → first tab:AddSlider()
Components/Input/Input          → first tab:AddInput()
Components/Selection/Dropdown   → first tab:AddDropdown()
Components/Selection/Segmented  → first tab:AddSegmented()
Components/Selection/ColorPicker→ first tab:AddColorPicker()
Components/Keyboard/Keybind     → first tab:AddKeybind()

Introspection

lua
NonameUI:GetLoadedModules()      -- array of loaded keys
NonameUI:IsModuleLoaded(name)    -- boolean
NonameUI:GetTotalModules()       -- count (excl. init)
NonameUI:PreloadComponents(path) -- force-load
NonameUI:GetLazyStats()          -- { loads, cacheHits, cached }

Public API

Module: NonameUI

MethodDescription
Init(uid)Required. Sets config identity.
CreateWindow(opts)Returns a window object.
SetLiteMode(on)Switch Desktop/Mobile profile.
IsLiteMode()Current profile is Mobile.
GetDeviceInfo()Type, IsMobile, IsDesktop, Profile, Input.
HasFeature(name)Check executor capability.
RegisterTheme(name, t)Register a custom theme.
GetThemes()Sorted theme names.
RemoveTheme(name)Remove a custom theme.
importTheme(t)Import multiple themes.
GetLoadedModules()Loaded module keys (excludes init).
IsModuleLoaded(name)true if module is loaded.
GetTotalModules()Total module count (excludes init).
PreloadComponents(...)Force-load lazy modules.
LazyLoad(path)Low-level lazy require.
GetLazyStats(){ loads, cacheHits, cached }

CreateWindow options

OptionDefault / meaning
Title"Noname UI" — window title
Theme"Dark" — initial theme
AutoProfilefalse — Desktop↔Mobile auto-switch
MaxStickyNotifs3 — concurrent sticky notifications

Window methods

MethodDescription
AddTab(name, opts)Returns a tab for Add* calls.
Notify(text, duration, opts)Show notification.
ShowConfirm(opts)Confirm dialog.
ClearStickyNotifications()Remove sticky notifications.
SetTitle(text)Change title.
GetFlags() / SetFlag(n, v)Read / write flags.
LoadConfiguration() / ResetConfig()Reload / reset config.
SetTheme(name, instant) / GetTheme()Change / read theme.
SetThemeAnimation(e, d, s)Tune theme animation.
GetVersion()Version string.
PrintDebug()Diagnostics.
IsMinimized() / DoMinimize()Minimize state / toggle.
Destroy()Destroy window.

Elements

All methods are called on the tab returned by window:AddTab(). Wrapper methods available on every return value: MoveUp, MoveDown, MoveTo, MoveToTop, MoveToBottom, SetOrder, GetOrder, Remove, Destroy.

AddLabel

tab:AddLabel(text, opts)

Options: Color, Bg, Icon, IconColor, Subtitle, SubtitleColor, Bold, RichText, Accent, Align, TextSize, Typewriter, TypeSpeed, Pulse, Clickable, Description

Returns: Set, SetColor, SetIcon, SetSubtitle, SetBold, SetAlign, SetVisible, Get, GetInstance, StopTypewriter, Reset

lua
local label = tab:AddLabel("Hello", { Icon = "info", Accent = true })
label:Set("Ready")

AddButton

tab:AddButton(text, callback, opts)

Options: Description

Returns: SetEnabled, Disable, Enable, IsEnabled, Reset

lua
local button = tab:AddButton("Run", function() print("clicked") end)
button:Disable("Unavailable")
button:Enable()

AddButtonRow

tab:AddButtonRow(buttons, opts)

Options: Per-button: Text, Callback, Danger

Returns: Reset + wrapper methods

lua
tab:AddButtonRow({
  { Text = "Save", Callback = function() end },
  { Text = "Reset", Callback = function() end, Danger = true },
})

AddToggle

tab:AddToggle(text, callback, opts)

Options: Flag, Description

Returns: Get, Set, Reset

lua
local toggle = tab:AddToggle("God Mode", function(s) print(s) end, { Flag = "godmode" })
toggle:Set(true)

AddCheckbox

tab:AddCheckbox(text, default, callback, opts)

Options: Flag, Description

Returns: Get, Set, Toggle, Reset

lua
tab:AddCheckbox("Show FPS", false, function(s) end, { Flag = "show_fps" }):Toggle()

AddToggleGroup

tab:AddToggleGroup(title, list, opts)

Options: Single, OnChanged; each item: text, default, callback, description

Returns: Get, Set, GetAll, Reset

lua
tab:AddToggleGroup("Features", {
  { text = "Auto Farm", default = false },
  { text = "Auto Sell", default = true },
}, { Single = false, OnChanged = function(name, state) end })

AddInput

tab:AddInput(text, placeholder, callback, opts)

Options: Type = "any" | "text" | "number", Min, Max, Flag, Description

Returns: Get, Set, Reset

lua
tab:AddInput("Name", "Enter…", function(v) print(v) end, { Type = "text", Min = 1, Max = 50 })

AddSlider

tab:AddSlider(text, min, max, default, step, callback, opts)

Options: Suffix, Flag, Description

Returns: Get, Set, Reset

lua
tab:AddSlider("Speed", 16, 100, 16, 1, function(v) print(v) end, { Suffix = "studs", Flag = "speed" })

AddRangeSlider

tab:AddRangeSlider(text, min, max, defMin, defMax, callback, opts)

Options: Step, Flag, Description

Returns: Get (returns vMin, vMax), Set, Reset

lua
tab:AddRangeSlider("Time", 0, 24, 6, 18, function(vMin, vMax) end, { Step = 1 })

AddProgressBar

tab:AddProgressBar(text, min, max, default, opts)

Options: Suffix, ShowValue, Flag, Description, Callback

Returns: Get, Set, Add, SetText, SetLabel, Reset

lua
local p = tab:AddProgressBar("Loading", 0, 100, 0, { Suffix = "%" })
p:Set(50); p:Add(10)

AddDropdown

tab:AddDropdown(text, options, callback, opts)

Options: Flag, Placeholder, Searchable, MaxHeight, SearchPlaceholder, Description

Returns: Get, Set, SetOptions, Reset

lua
tab:AddDropdown("Select", { "A", "B", "C" }, function(v) print(v) end, { Searchable = true })

AddMultiDropdown

tab:AddMultiDropdown(text, options, callback, opts)

Options: Same as AddDropdown

Returns: Same as AddDropdown; callback receives array of selected values

lua
tab:AddMultiDropdown("Select many", { "A", "B", "C" }, function(vals) print(#vals) end)

AddSegmented

tab:AddSegmented(text, segments, default, callback, opts)

Options: Flag

Returns: Get, Set, Reset

lua
tab:AddSegmented("Mode", { "Easy", "Normal", "Hard" }, "Normal", function(v) print(v) end)

AddColorPicker

tab:AddColorPicker(text, defaultColor, callback, opts)

Options: Alpha, Flag, Presets, Description

Returns: Get, GetAlpha, Set, SetAlpha, Reset

lua
tab:AddColorPicker("Highlight", Color3.fromRGB(255, 0, 0), function(c, a) end, { Alpha = true })

AddKeybind

tab:AddKeybind(text, defaultKey, callback, opts)

Options: Flag, Timeout

Returns: Get, Set, Reset

lua
tab:AddKeybind("Toggle UI", Enum.KeyCode.K, function(key, down) print(key.Name, down) end)

AddKeybindMode

tab:AddKeybindMode(text, defaultKey, callback, opts)

Options: Mode = "Hold" | "Toggle" | "Always", Flag, Timeout

Returns: Get, GetMode, IsActive, Set, SetMode, Reset

lua
local k = tab:AddKeybindMode("Aim", Enum.KeyCode.Q, function(key, mode, active) end, { Mode = "Hold" })
k:SetMode("Toggle")

AddToggleKeybind

tab:AddToggleKeybind(text, defaultKey, callback, opts)

Options: Flag, Timeout

Returns: Get, Set, Reset

lua
tab:AddToggleKeybind("Fly", Enum.KeyCode.F, function(state) end)

AddSection

tab:AddSection(text, opts)

Options: defaultCollapsed

Returns: Set, Get, SetCollapsed, Toggle, IsCollapsed, Expand, Collapse, Reset

lua
local sec = tab:AddSection("Movement")
sec:AddToggle("Sprint", function(s) end)

AddDivider

tab:AddDivider()

Options: —

Returns: wrapper methods

lua
tab:AddDivider()

AddChip / AddTag

tab:AddChip(text, label, opts)

Options: Color, Closable, OnClose, Flag, Description

Returns: Set, Get, Reset

lua
tab:AddChip("Status", "Active", { Color = Color3.fromRGB(80, 200, 120), Closable = true })

AddModuleCard

tab:AddModuleCard(cfg)

Options: Title, Description, Default, Keybind, Risky, Expanded, Flag, Callback

Returns: Get, Set, Reset, Expand, Collapse + every Add* method delegated

lua
local card = tab:AddModuleCard({ Title = "Auto Farm", Description = "Example" })
card:AddToggle("Loop", function(s) end)
card:Expand()

Notifications

Desktop: bottom-right stack. Mobile: top-right, full width.

lua
win:Notify("Saved", 3, {
    Type = "success",      -- info | success | warn | error
    Title = "Settings",
    sticky = false,
    sound = "",            -- "" disables
    Actions = {
        { text = "OK", callback = function() end, dismiss = true },
    },
})
OptionMeaning
Typeinfo | success | warn | error; default "info"
TitleCustom title
stickyPrevent auto-close
soundrbxassetid; empty string disables
iconOverride icon
Actions{ text, callback, dismiss }[]
noAutoDurationSkip auto duration extension

ShowConfirm

lua
win:ShowConfirm({
    Title = "Delete?",
    Message = "This cannot be undone.",
    ConfirmText = "Yes",
    CancelText = "No",
    Danger = true,
    OnConfirm = function() end,
    OnCancel = function() end,
})

win:ClearStickyNotifications()

Watermark

Two-row overlay (top-right): title + version; FPS, ping, uptime, and a red dot after 3 ticks of sustained bad metrics.

lua
win.Watermark:SetVisible(false)
win.Watermark:IsVisible()

local s = win.Watermark:GetStats()
-- { fps, ping, uptime, profile, version, stable }

win.Watermark:Destroy()  -- usually handled by win:Destroy()

Colors: FPS ≥55 green / ≥30 yellow / <30 red · Ping <80 green / <150 yellow / ≥150 red.

KeybindList

Second overlay (below watermark). Auto-populates from AddKeybindMode and AddToggleKeybind.

lua
win.KeybindList:Register(name, key, getStateFn)
win.KeybindList:Update(name)
win.KeybindList:Unregister(name)

Themes

Built-in: Red, Orange, Yellow, Green, Aqua, Blue, Purple, Dark, Light.

Slots

lua
Background, Sidebar, Accent
Text, TextDark, Element, Stroke
toggleActive, toggleInActive
Muted, Danger, DangerBg, Success, Warn
SliderTrack, Overlay

Custom theme

lua
NonameUI:RegisterTheme("MyTheme", {
    Background = Color3.fromRGB(20, 20, 30),
    Accent = Color3.fromRGB(0, 200, 255),
    -- unspecified slots fall back to Dark
})

win:SetTheme("MyTheme", true)  -- true = instant

Animation

lua
NonameUI:SetThemeAnimation(true, 0.40, 0.012)
-- { Enabled, Duration, Stagger, LiveDuration, FlashEnabled }

win:SetThemeAnimation(true, 0.35, 0.008)  -- per-window

Live Theme Editor is available from the Settings tab. Custom themes save under __custom_themes, overrides under __live_theme_slots.

Configuration

Controls with Flag persist when the executor supports filesystem. Config tag stays V-1.15.0 (frozen across v1.12–v1.16).

lua
local flags = win:GetFlags()
win:SetFlag("godmode", true)
win:LoadConfiguration()
win:ResetConfig()

Reserved keys

lua
__ui_pos, __ui_size
__ui_theme
__live_theme_slots, __custom_themes
__auto_profile, __debug_mode, __theme_anim
__schema

Format

json
{
  "_crc": "abc12345",
  "_v": 4,
  "data": { "godmode": true, "speed": 42 }
}

saveConfig() is debounced 120 ms and routed through AsyncIO. Writes use retry + backoff + CRC + .bak/.bak2 rotation. SaveManager.flush() runs synchronously for BindToClose. Bad flags are discarded individually.

Device & mobile

lua
NonameUI:SetLiteMode(true)
NonameUI:IsLiteMode()
NonameUI:GetDeviceInfo()

NonameUI.DynamicProfile.setEnabled(false)     -- stops Heartbeat
NonameUI.DynamicProfile.lockProfile("Mobile")
NonameUI.DynamicProfile.lockProfile(nil)       -- unlock
NonameUI.DynamicProfile.getStats()

Auto-switch: FPS < 45 for 1.5 s → Mobile; FPS > 55 for 3 s → Desktop. Sampling on Heartbeat (0.5 s window). Mobile sidebar becomes a swipeable pageLayout.

Advanced

lua
-- MemoryPool
NonameUI.MemoryPool.stats()
NonameUI.MemoryPool.drain()
NonameUI.MemoryPool.acquire("UIStroke", parent)
NonameUI.MemoryPool.release("UIStroke", stroke)  -- Parent must be nil

-- AsyncIO
NonameUI.AsyncIO.enqueue(function() end)
NonameUI.AsyncIO.drain(3)
NonameUI.AsyncIO.setBudget(0.008)
NonameUI.AsyncIO.setErrorHandler(warn)

-- KeybindDispatch
local D = NonameUI:GetBootstrap().KeybindDispatch
local tok = {}
D.registerKey(tok, Enum.KeyCode.F,
    function(i) end,     -- began
    function(i) end)     -- ended
D.unregister(tok)

-- GestureDetector
local GD = NonameUI:GetMods().GestureDetector
local h = GD.onSwipe(frame, { Deadzone = 24, Threshold = 70, Slope = 1.6 },
    function(dir, dx, dy) end)
h.Disconnect()
GD.onLongPress(btn, { Duration = 0.6 }, function(x, y) end)

-- RateLimit
local rl = NonameUI.RateLimit.wrap(fn, { Capacity = 30, RefillRate = 60 })
rl()          -- true = executed, false = blocked
rl:reset()
rl:remaining()

-- Migrations
NonameUI.Migrations.register(fromVer, function(flags) end)
NonameUI.Migrations.currentSchema()  -- 4

Migration v1.15 → v1.16

No API changes required. Behavior fixes:

Areav1.16.0
AddKeybindMode:IsActive()Always mode reports active while held
AddKeybindMode:SetMode()Resets latched/held state
AddToggleKeybindVisible in KeybindList
AddKeybind:Set(invalid)Silently ignored (was: crash)
DynamicProfile.setEnabled(false)Actually disconnects Heartbeat
saveConfig()Debounced 120 ms + AsyncIO
Notifications (desktop)Bottom-right stack
Lazy loadingInit() no longer loads everything

Troubleshooting

config persistence disabled

Executor lacks writefile/readfile/isfile. UI works; settings do not persist. Check NonameUI:HasFeature("hasWriteFile").

[Signal] attempt to call nil

A nil or non-function was passed to :Connect(). Verify callbacks are functions.

Notifications do not appear

window._notifyHolder must be set and Notifications.install(window, actx) called inside CreateWindow.

Dropdown opens below the screen

v1.16.0 includes popup repositioning. If it persists, verify _markPopupDirty fires on scroll/resize.

ScrollingFrame passed to PageLayout JumpTo

Deferred selectTab fired after window:Destroy(). Guarded in v1.16.0 — update to the latest bundle.

[NonameUI/lazy] Failed to load '…'

A lazy module path is missing from the bundle. Rebuild with build.js and verify the source file exists.

Changelog — v1.16.0

  • Lazy loading for 13/26 modules (Windows, Containers, Notifications, Search, all elements).
  • Shared KeybindDispatch — O(k) per keystroke.
  • saveConfig 120 ms debounce + AsyncIO; CRC + .bak/.bak2.
  • Search 60 ms debounce + pooled result buttons.
  • Dropdown virtualized list, persistent handlers, autocomplete.
  • Diff-based theme apply — unchanged slots skip tween.
  • DynamicProfile disconnects Heartbeat when disabled.
  • Notifications stack bottom-right on desktop, top-right on mobile.
  • Watermark rework: color-coded FPS/ping, uptime, GetStats().
  • Fixes: KeybindMode state, ToggleKeybind in KeybindList, invalid keybind no-op, AddSlider min/max warning.
  • Config tag unchanged: V-1.15.0.