Window API

Every option Ember.new accepts, and every method a window has.

Ember.new#

Luau
local win = Ember.new({ Title = "My Script" })

Everything is optional.

Identity#

OptionTypeDefaultWhat it does
TitlestringShown in the title bar.
SubtitlestringA smaller second line under the title.
NamestringName for the ScreenGui, and the identity ReplaceExisting matches on. Falls back to Title.
Footerstring"ember"Small text at the bottom of the rail.
AccentColor3Sets the theme's accent. It is global: every live window repaints, the same as Ember.SetTheme({ accent = … }).

Geometry#

OptionTypeDefaultWhat it does
SizeVector2Vector2.new(700, 452)Starting size.
MinSizeVector2Vector2.new(560, 300)The user cannot resize below this.
MaxSizeVector2Upper limit. Defaults to the viewport.
PositionVector2 | UDim2Where it opens. Centred if unset.
Railnumber176Sidebar width in pixels.
MinRailnumber132Narrowest the sidebar can be dragged.
MaxRailnumber320Widest the sidebar can be dragged.
MinContentnumber300The content pane never shrinks past this.
ResizablebooleantrueWhether the resize grip is offered.
SafeAreabooleantrueKeeps the window inside the usable viewport.
SaveLayoutboolean | stringfalseRemember size, position and rail width between sessions. A string names the slot, so two windows can keep separate geometry; otherwise the slot is Name, then Title.

Behaviour#

OptionTypeDefaultWhat it does
KeybindEnumItem | string | falseEnum.KeyCode.RightShiftThe key that hides and shows the window. A string like "F4" works too. false means no toggle key. An unknown name warns and falls back to RightShift.
ReplaceExistingbooleantrueClose this script's previous window instead of stacking a second one.
SearchbooleanfalseAdds a search box to the rail that spans every section.
SearchPlaceholderstringGhost text for that box.
StatusBarboolean | tablefalseA strip along the bottom or top of the window. See Status bar below.
ThemestringApplies this theme as the window is built, so it wins over Config.Themes.Default and over an earlier SetTheme.
ReapplyOnRespawnbooleanfalseEvery control re-fires its callback when the character is replaced. A control can set Reapply = false to stay out.
RevertOnClosebooleanfalseEvery control is called with its off value when the window is destroyed. A control can set RevertOnClose = false to stay out, or RevertTo to pick the value it reverts to.

ReapplyOnRespawn and RevertOnClose are covered in Lifecycle and cleanup.

Status bar#

A strip along the bottom or top of the window, for things like what the script is doing or an FPS readout. Minimise takes it away with the body and brings it back.

Luau
local win = Ember.new({ Title = "Helper", StatusBar = true })
win.StatusBar:Set("Ready")

It has three zones, left, center and right. Everything in it is an item with an id, so a loop writing an FPS number and a one-off message do not tread on each other.

Luau
local win = Ember.new({
    Title = "Helper",
    StatusBar = {
        Position = "bottom",
        Text     = "Ready",
        Icon     = "circle-dot",
        Items    = {
            { Id = "fps",  Align = "left",  Text = "-- FPS", Icon = "gauge" },
            { Id = "ver",  Align = "right", Text = "v2.4" },
        },
    },
})
 
game:GetService("RunService").RenderStepped:Connect(function(dt)
    win.StatusBar:Item("fps", { Text = math.floor(1 / dt) .. " FPS" })
end)

Options#

OptionTypeDefaultWhat it does
Positionstring"bottom""bottom" or "top". Bottom sits on the window's edge; top sits under the title bar.
Heightnumber24Clamped to 16–64.
TextstringThe centre message. Shorthand for an item with the id "status".
IconstringAn icon for that message.
ColorColor3 | string"muted"Its colour, as a Color3 or a theme role name.
ItemsarraySegments to build up front. Each takes Id, Align, Text, Icon, Color, Order and Visible. Order defaults to its position in the array.

Methods#

MethodReturnsWhat it does
Set(text, opts?)true / false, reasonWrites the centre message
Get(id?)string | nilThe text of an item, or of the centre message
Item(id, opts)true / false, reasonCreates or updates a segment
Remove(id)true / false, reasonTakes one out
Items()arrayThe ids currently in the bar, sorted
Clear()trueEmpties it
Show() / Hide() / SetVisible(v)trueThe body takes the space back when it is hidden
IsVisible()booleanWhether it is showing
Height()numberIts height, or 0 while hidden
Position()string"bottom" or "top"

Item updates in place rather than rebuilding, so calling it every frame costs a string assignment and not two instances. Item(id, "text") is shorthand for Item(id, { Text = "text" }). Passing Icon = false removes an icon; leaving Icon out keeps whatever is there. Item(id, false) is the same as Remove(id).

Colours by role, not by hex

Color takes a theme role name such as "accent" or "muted", as well as a Color3. A role name keeps the bar in step when the theme changes; a literal colour does not.

Sections#

Luau
local main = win:Section("Main", "home")
 
-- with options
local big = win:Section("Everything", "list", {
    Search = true,
    SearchPlaceholder = "Filter this section…",
})

The first section created is the one shown on open.

Methods#

Content#

MethodWhat it does
Section(name, icon, opts)Adds a section and returns it
Select(section)Switches to a section
Notify(opts)Shows a notification
ThemeEditor(opts?)Builds a theme editor section and returns it

Appearance#

MethodWhat it does
SetTitle(text)Changes the title
SetSubtitle(text)Changes the subtitle
SetSize(width, height)Resizes
SetMinSize(v) / SetMaxSize(v)Changes the resize limits
SetPosition(v)Moves it
SetRailWidth(n)Resizes the sidebar
Centre() / Center()Centres it on screen. Both spellings work.

State#

MethodWhat it does
Toggle(visible?)Hides or shows, with the dissolve. Pass a boolean to force one way.
Minimise(state?) / Minimize(state?)Collapses to the title bar. Pass a boolean to force one way.
SaveLayout()Writes the current geometry to disk. false if the window was not created with SaveLayout.
RestoreLayout()Reads it back
GetLayout()Returns the current geometry as a table

Lifecycle#

MethodWhat it does
Destroy(immediate?)Tears the window down and disconnects everything. true skips the closing dissolve.
OnDestroy(fn)Registers cleanup to run on destroy
OnRespawn(fn)Runs fn(character) each time the character is replaced. Returns a subscription with :Disconnect().
Reapply()Re-fires every opted-in control's callback now, without waiting for a respawn
Track(connection)Hands a connection to the window to disconnect for you

See Lifecycle and cleanup.

A fully specified window#

Luau
local win = Ember.new({
    Title      = "Bloxburg Helper",
    Subtitle   = "v2.1",
    Footer     = "by you",
 
    Size       = Vector2.new(760, 500),
    MinSize    = Vector2.new(600, 340),
    Rail       = 190,
    SaveLayout = true,
 
    Keybind    = Enum.KeyCode.RightControl,
    Search     = true,
    StatusBar  = { Text = "Ready", Icon = "circle-dot" },
})

Pointer and cursor helpers#

Ember.Util holds the pointer tracking and cursor stack the window uses for its own resize corner. Use them for anything draggable you build yourself.

FunctionReturnsWhat it does
Util.pointerPosition(reference)Vector2 | nilThe pointer in the same space as AbsolutePosition. Pass any instance inside the GUI you are measuring against.
Util.pointerInside(instance, padding?)boolean | nilWhether the pointer is over that instance, with optional slack. nil means the position could not be read, which is not the same as false.
Util.watchPointer(instance, fn, padding?)subscriptionCalls fn(inside) whenever that answer changes. :Disconnect() to stop. Returns nil if the instance or the function is missing.
Util.setCursor(token, icon)booleanRequests a mouse cursor. Pass nil as the icon to drop the request.
Util.CursorstableResizeDiagonal, ResizeHorizontal, ResizeVertical, Hand
Luau
local Util = Ember.Util
 
Util.watchPointer(myHandle, function(inside)
    Util.setCursor(myHandle, inside and Util.Cursors.ResizeHorizontal or nil)
end, 3)

watchPointer re-tests the rectangle every Heartbeat. MouseEnter and MouseLeave do not fire when the object moves under a cursor that has not itself moved, which is what happens during a drag. One shared connection drives every watcher and it stops when the last one disconnects.

Cursor requests are a stack

setCursor shows the most recent request and falls back to the previous one when that is dropped, then restores the game's own icon when none are left. Drop your request when you are done, including on destroy, or the cursor stays for the rest of the session.