Icons

All 1,573 Lucide icons are built in. Finding one, and adding your own.

Anywhere Ember takes an Icon, it takes a name: a plain string.

Luau
local main = win:Section("Main", "home")
 
main:Toggle({ Text = "God mode", Icon = "shield" })
 
main:Button({ Text = "Refresh", ButtonIcon = "refresh-cw" })

If Ember does not know the name, nothing is drawn. The control still renders without a glyph, nothing errors, and Ember warns [Ember] unknown icon "<name>" to the console.

Where they come from#

The icons are Lucide, an open-source set. All 1,573 of them are baked into the library as sprites, so they load with it.

Names match lucide.dev exactly

If you find an icon on lucide.dev called sliders-horizontal, that is the exact string Ember expects. Browse there, then check it is in the list below.

Find one#

Type to filter. Click any icon to copy its name.

1,573

Checking at runtime#

Two helpers, useful when the name comes from somewhere you do not control:

Luau
Ember.HasIcon("shield")     --> true
Ember.HasIcon("not-an-icon") --> false
 
local names = Ember.Icons() -- every registered name, sorted
print(#names)               --> 1573

Using an image directly#

Icon also takes an asset id, with no registration step:

Luau
main:Toggle({ Text = "Custom", Icon = "rbxassetid://1234567890" })
main:Toggle({ Text = "Custom", Icon = 1234567890 })   -- or the bare number
main:Toggle({ Text = "Avatar", Icon = "rbxthumb://type=AvatarHeadShot&id=1&w=48&h=48" })

A table is a sprite descriptor: { assetId, rectX, rectY, cell }, the last three optional. cell may be a number or a Vector2 for non-square cells.

Luau
main:Toggle({ Text = "Sword", Icon = { 1234567890, 96, 48, 48 } })

Register a name instead once you use the same image in more than one place.

Adding your own#

RegisterIcon takes a name and a Roblox asset ID. Once registered, the name works anywhere a built-in name does:

Luau
Ember.RegisterIcon("mylogo", "rbxassetid://1234567890")
 
main:Toggle({ Text = "Custom", Icon = "mylogo" })

If your image is a sprite sheet, pass the offset and cell size as well:

Luau
-- name, assetId, rectX, rectY, cell
Ember.RegisterIcon("swordIcon", "rbxassetid://1234567890", 96, 48, 48)
OptionTypeDefaultWhat it does
namereqstringWhat you will pass as Icon. Any non-empty string.
assetIdreqstring | numberA rbxassetid:// or rbxthumb:// string, or a bare asset id number.
rectXnumber0X offset into a sprite sheet.
rectYnumber0Y offset into a sprite sheet.
cellnumber | Vector2Size of one cell in the sheet.

RegisterIcons adds several at once. Each value is a sprite descriptor table, the same { assetId, rectX, rectY, cell } shape as above. The call is all-or-nothing: if any entry is malformed, none are added.

Luau
local ok, err = Ember.RegisterIcons({
    mylogo  = { "rbxassetid://1234567890" },
    myBadge = { "rbxassetid://1234567891", 96, 48, 48 },
})
 
if not ok then
    warn("icon set rejected:", err)
end

Neither function throws. RegisterIcon returns the name on success, RegisterIcons returns true, and both return false, reason on failure.

Where icons show up#

PlaceOptionNotes
Section tabsecond argument to win:Sectionwin:Section("Main", "home")
Any controlIconBefore the label
ButtonButtonIconInside the button, alongside its text
Group headerIconBefore the group's name
NotificationIconIn the toast
Status bar itemIconwin.StatusBar:Item("fps", { Text = "60", Icon = "gauge" })

Colour and size are adjustable per control with IconColor and IconSize:

Luau
main:Toggle({
    Text = "Danger zone",
    Icon = "triangle-alert",
    IconColor = Color3.fromRGB(232, 93, 93),
    IconSize = 18,
})

Left alone, an icon is drawn in the theme's muted colour at 16 pixels on a control row and 13 on a group header.

ButtonIcon is the exception

A button's ButtonIcon ignores IconColor and IconSize. It is drawn at 14 pixels in the colour of the button style it sits in, so a filled button's icon is always accentInk and a Danger button's is the danger colour. The row's own Icon honours both options normally.