Skip to content

Appearance pages

Status: Implemented (API 1.21). A page of your mod in the Appearance screen (Appearance > Mods), built from rows the player edits like the built-in settings, bound to your client config.

Function table: ui. Related: Config, HUD Elements, The UI Kit.

A page

local config = cl.config.open("client")
config:define_bool("bar.show", true)
config:define_i32("bar.width", 160, 80, 240)
config:define_str("bar.labels", "Letters")
config:define_str("bar.marker", "#FFAA00")

cl.on("lifecycle.client_setup", function()
  local page = cl.ui.page_register{
    id = "settings", label = "Compass Plus", icon = "marker",
    subtitle = "The compass bar and its waypoints",
    on_change = function(page, key) print("changed: " .. key) end,
  }
  page:group("Compass bar")
  page:option("bar.show", "Show the compass bar", "Draw the bar at the top of the screen")
  page:option("bar.width", "Bar width", "Width in GUI pixels")
  page:choice("bar.labels", "Labels", "Directions as letters or as degrees", "Letters\nDegrees")
  page:color("bar.marker", "Marker colour", "The centre marker")
  page:button("open", "More settings", "The full settings screen", "Open")
end)

The page shows in the Appearance sidebar under Mods with your icon, and in Appearance > Mod Pages. It looks like every other Appearance page. In the Vanilla style the Appearance screen is the vanilla Client Settings > Appearance list; the options behind your rows stay reachable through your mod’s Config page in the Mods screen (they are ordinary config options).

Rows

C Lua (on the page) Row
cl_ui_page_group page:group(label) A group heading
cl_ui_page_note page:note(text) A line of text
cl_ui_page_option page:option(path, label, description) A row bound to a client config option: a toggle (bool), a slider (a number with a range), a text field (anything else)
cl_ui_page_choice page:choice(path, label, description, choices) A text option as a choice (up to 4: segments, more: a dropdown); the stored value is the choice’s text
cl_ui_page_color page:color(path, label, description) A text option holding "#RRGGBB" (or "#RRGGBBAA" with opacity), shown as the client’s colour picker (1.23: wheel, hex, theme colour, recent and saved colours)
cl_ui_page_button page:button(key, label, description, button) A row with a button; pressing it calls on_change(page, key)
cl_ui_page_hud_element page:hud_element(element) The rows of one of your HUD elements: show, style, scale, and a button to the HUD editor

path is an option you defined with cl_config_define_* in your client config (cl.config.open("client"); a common option with the same path also works). A change is checked (type, range), saved to the file at once, fires config.reloaded and then on_change(page, path). Read the values as usual with config:get_*.

page:open() opens Appearance at your page (for a “Settings” button in your own screen). page:remove() takes it away.

C

static void on_change(cl_ui_page page, cl_str key, void* user) { /* key: the path or the button key */ }

void setup_page(void) {
    cl_ui_page_desc d = CL_UI_PAGE_DESC_INIT;
    d.id = CL_STR("settings");
    d.label = CL_STR("Compass Plus");
    d.icon = CL_STR("marker");
    d.on_change = on_change;
    cl_ui_page page;
    cl_ui_page_register(&d, &page);
    cl_ui_page_option(page, CL_STR("bar.show"), CL_STR("Show the compass bar"), CL_STR(""));
}

C++: clight::ui::page_register(&d) returns Expected<clight::UiPage> with group, note, option, choice, color, button, hud_element, open, remove.

Pages are client-only. At most 64 pages and 256 rows per page.

Features (API 1.23)

The client has one Features screen (one click from the title screen, the pause menu and Settings) where every feature is a card: icon, name, one line, an on / off switch, a star to pin it to Favorites, and the card opens its settings. The search there is fuzzy and also finds the rows of your page. Put your mod’s features there instead of a menu of your own:

cl.on("lifecycle.client_setup", function()
  local page = cl.ui.page_register{ id = "trail", label = "Trail", icon = "sparkle" }
  page:option("trail.on", "Trail", "A ribbon behind you")
  page:color("trail.colour", "Color", "The ribbon's color")
  cl.ui.feature_register{
    id = "trail", name = "Trail", description = "A ribbon behind you while you move",
    icon = "sparkle", category = "visuals",
    keywords = "ribbon\nparticles",
    option = "trail.on",   -- a bool option of the client config: the card's switch
    page = page,           -- the card opens this page; the search finds its rows
  }
end)
Field Meaning
id Unique in your mod (a-z, 0-9, _ - .); the same id replaces the feature
name, description The card’s title and one line (keep it short: what it does, not how)
icon A name of the icon set (Theme Tokens)
category CL_FEATURE_VISUALS, HUD, ANIMATIONS, CAMERA, TAB_CHAT, COSMETICS, PERFORMANCE, UTILITY or MODS (the default)
keywords More words the search knows, one per line
option A bool option of your client config: the card’s switch (none: the card only opens its page)
page Your Appearance page with its settings (none: the card has only the switch)

cl_ui_feature_remove takes a feature away; features go with their mod when it is turned off. At most 128 features. In the Vanilla style the Features screen is the vanilla Client Settings list; your options stay reachable through the mod’s Config page.

C: cl_ui_feature_desc d = CL_UI_FEATURE_DESC_INIT; d.id = CL_STR("trail"); ... cl_ui_feature_register(&d, &f); C++: clight::ui::feature_register(&d).