Icons
All 1,573 Lucide icons are built in. How to find the one you want, and how to add your own.
Anywhere Ember takes an Icon, it takes a name — a plain string:
win:Section("Main", "house")
main:Toggle({ Text = "God mode", Icon = "shield" })
main:Button({ Text = "Refresh", ButtonIcon = "refresh-cw" })If the name is not one Ember knows, nothing is drawn — the control renders fine, just without a glyph. Nothing errors and nothing crashes.
Where they come from#
The icons are Lucide — the same open-source set used by a lot of modern software. They are baked into the library as sprites, so there is no download, no asset ID to upload, and no delay before they appear.
The entire set is included — 1,573 icons — not a hand-picked subset. If it exists on lucide.dev, you can use its name.
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.
Checking at runtime#
Two helpers, useful when the name comes from somewhere you do not control:
Ember.HasIcon("shield") --> true
Ember.HasIcon("not-an-icon") --> false
local names = Ember.Icons() -- every registered name, sorted
print(#names) --> 1573Adding your own#
RegisterIcon takes a name and a Roblox asset ID. Once registered, the name
works anywhere a built-in name does:
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:
-- name, assetId, rectX, rectY, cell
Ember.RegisterIcon("swordIcon", "rbxassetid://1234567890", 96, 48, 48)| Option | Type | Default | What it does |
|---|---|---|---|
namereq | string | — | What you will pass as Icon. Any non-empty string. |
assetIdreq | string | — | A rbxassetid:// URL. |
rectX | number | 0 | X offset into a sprite sheet. |
rectY | number | 0 | Y offset into a sprite sheet. |
cell | number | — | Size of one cell in the sheet. |
Registering several at once is one call, and it is all-or-nothing — if any entry is malformed, none are added, so you never end up with half a set:
local ok, err = Ember.RegisterIcons({
mylogo = "rbxassetid://1234567890",
myBadge = "rbxassetid://1234567891",
})
if not ok then
warn("icon set rejected:", err)
endBoth functions return false, reason on failure rather than throwing, so a bad
asset ID cannot take your whole script down.
Where icons show up#
| Place | Option | Notes |
|---|---|---|
| Section tab | second argument to win:Section | win:Section("Main", "house") |
| Window title | Icon on Ember.new | Shown next to the title |
| Any control | Icon | Before the label |
| Button | ButtonIcon | Inside the button, alongside its text |
| Group header | Icon | Before the group's name |
| Notification | Icon | In the toast |
Colour and size are adjustable per control with IconColor and IconSize:
main:Toggle({
Text = "Danger zone",
Icon = "triangle-alert",
IconColor = Color3.fromRGB(232, 93, 93),
IconSize = 18,
})Left alone, icons take the theme's colour and the control's natural size, which is what keeps a window looking consistent.
ButtonIcon is the exception
A button's ButtonIcon ignores IconColor — it takes 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. That is deliberate: an icon in a
different colour from the label beside it looks like a rendering bug. The row's
own Icon honours IconColor normally.