Themes

The nine built-in palettes and the fourteen colour roles behind them.

Switching theme#

One call. Everything already on screen repaints, including notifications:

Luau
Ember.SetTheme("Midnight")

Let the user choose:

Luau
settings:Dropdown({
    Text = "Theme",
    Options = Ember.ThemeNames(),
    Default = "Dark",
    Save = "theme",
    Callback = function(name) Ember.SetTheme(name) end,
})

The nine built in#

Dark
Midnight
Slate
Nord
Rose
Mono
Ember
Ocean
Grape

Set the one your script opens with before creating a window:

Luau
Ember.Configure({ Themes = { Default = "Nord" } })

Default applies when no theme has been set. A later SetTheme wins over it, so a script can put back whatever its user picked last session:

Luau
Ember.Configure({ Themes = { Default = "Nord" } })
 
local saved = Ember.Store.get("prefs")
if saved and saved.theme then
    Ember.SetTheme(saved.theme)     -- this sticks; the window will not undo it
end
 
local win = Ember.new({ Title = "My Script" })

Ember.new({ Theme = "Ocean" }) runs when the window is built, so it wins over both.

Restricting the list#

To publish a script with a fixed look, limit what ThemeNames() returns:

Luau
-- Only these, in this order
Ember.Configure({ Themes = { Only = { "Dark", "Midnight", "Ember" } } })
 
-- Everything except these
Ember.Configure({ Themes = { Hide = { "Mono", "Rose" } } })

Set both and both apply: Only picks the list, then Hide is subtracted from it. Only = { "Dark", "Ember" } with Hide = { "Ember" } leaves Dark.

The fourteen roles#

A theme is fourteen Color3 values and nothing else.

RoleWhat it paints
bgWindow background
panelSidebar
panel2Card surface
panel3Hover surface
borderHairline border
border2Strong border
textBody text
mutedSecondary text
faintPlaceholder text
accentAccent
accentInkText on accent
dangerDanger / delete
hoverControl hover fill
scrollIdleScrollbar at rest

The four you will change most often:

  • accent is the brand colour. Every filled control uses it.
  • bg sits behind everything, and inside input fields.
  • panel2 is every control's card.
  • text is titles and values. muted is labels, faint is placeholders.

accentInk has to stay dark

accentInk is the text on a filled accent button. If you set the accent to a pale colour and leave accentInk light, filled buttons become unreadable.

Reading the current theme#

Luau
Ember.Theme.accent      --> Color3
Ember.Theme.panel2      --> Color3
 
Ember.CurrentTheme      --> the name last applied; nil until a named SetTheme
Ember.ThemeNames()      --> { "Dark", "Midnight", … } what the user may pick
Ember.Themes            --> every palette by name, including registered ones
Ember.ThemeRoles        --> { "bg", "panel", … } every role name
Ember.ThemeRoleLabels   --> { panel2 = "Card surface", … } all of them at once
Ember.ThemeRoleLabel("panel2")   --> "Card surface"
Ember.IsBuiltInTheme("Dark")     --> true

ThemeNames honours Only and Hide; Themes does not, so read it when you want the whole set.

Ember.Theme is live: after SetTheme, reading it gives the new colours. Use it to paint your own GUI elements so they match:

Luau
myLabel.TextColor3 = Ember.Theme.text
myFrame.BackgroundColor3 = Ember.Theme.panel2

To keep them matching when the theme changes:

Luau
Ember.OnThemeApplied(function()
    myLabel.TextColor3 = Ember.Theme.text
    myFrame.BackgroundColor3 = Ember.Theme.panel2
end)

It fires when a theme is applied by name. A single-role apply such as Ember.SetTheme({ accent = colour }) changes Ember.Theme without calling it.

Making your own#

See Custom themes for registering your own palettes and for the built-in editor.