UI Modding Basics

Balatro comes with a built-in UI framework that draws most of the elements of the game. It may seem hard to grasp at first but it’s actually quite simple in its structure.

The G.FUNCS and G.UIDEF tables

The game uses 2 tables for the UI.

G.FUNCS

It’s the table that holds all of the UI callbacks. Basically, whenever you click on a button, its associated to a function defined here. Functions in G.FUNCS match the following signature, the UIElement class being defined in engine/ui.lua :

function(element: UIElement) -> nil

G.UIDEF

It’s the table that holds the UI definitions for the game. An UI definition is a function that returns a table that has a very strict structure:

G.UIDEF.my_ui_definition = function(element)
    return {
        n = G.UIT.ROOT,
        config = {},
        nodes = {}
    }
end

Let’s break this down:

  • n = G.UIT.ROOT: n here represents the node “type”. There are several node types available in Balatro
    • T, which is for text nodes
    • B, for boxes (which can be rounded)
    • C, for column layouts
    • R, for row layouts
    • O, for objects (such as cards and such)
    • ROOT, for the root node of an UI definition
  • config: configuration for the node, holds several attributes, each for configuring alignments, or button behavior for instance
  • nodes: is an array of child nodes

Think of the Balatro UI definition like you would an HTML document. In HTML, you’d write something like this

HTML example

<div>
  <input type="text"></input>
  <div>
    <span><p>Some Text</p></span>
    <span><p>Other Text</p></span>
  </div>
</div>

Which would roughly be equivalent to

Example HTML equivalent for Balatro UI

{
    n = G.UIT.ROOT,
    config = {},
    nodes = {
        {
            n = G.UIT.I,
            config = {},
        },
        {
            n = G.UIT.C,
            config = {},
            nodes = {
                {
                    n = G.UIT.R,
                    config = {},
                    nodes = {
                        {
                            n = G.UIT.T,
                            config = { text = "Some Text" }
                        },
                    },
                },
                {
                    n = G.UIT.R,
                    config = {},
                    nodes = {
                        {
                            n = G.UIT.T,
                            config = { text = "Other Text" }
                        },
                    },
                },
            },
        },
    },
}

Configuration options for each UI type

Common config options

Text options

Info

For text UI nodes, the following config table is expected, all values are optional (can be nil), unless specified otherwise.

  • config.text, must be specified, unless config.ref_table and config.ref_value are both provided. The text to display. Type: string
  • config.colour, defaults to G.C.UI.TEXT_LIGHT (which is white with full opacity, #FFFFFFFF)
  • config.scale, defaults to 1. Text scaling to apply to the text. Type: float
  • config.shadow, defaults to false. Whether to draw a shadow behind the text. Type: boolean
  • config.focus_args
  • config.ref_table: a reference table, basically, the text value will be computed by looking up config.ref_value in config.ref_table.
  • config.ref_value: the value to look up into the provided config.ref_table
  • config.func
  • config.id: An unique ID for the node
  • config.juice
  • config.outline_colour: Text outline colour

Box options

Column options

Row options

Object options

Premade UI widget factories

The following functions are defined in functions/UI_definitions.lua, and use the concepts defined above to make more complex UI elements.

create_slider(args) -> UIElement

create_toggle(args) -> UIElement

create_option_cycle(args) -> UIElement

create_tabs(args) -> UIElement

create_text_input(args) -> UIElement

create_keyboard_input(args) -> UIElement

Enumerations

Colours

Colors are specified in globals.lua, you can access them through the G.C table.

Color Name Color (hex) Color (tuple) Color
MULT #FE5F55 (1,0.37,0.33,1)
CHIPS #009DFF (0,0.62,1,1)
MONEY #F3B958 (0.95,0.73,0.35,1)
XMULT #FE5F55 (1,0.37,0.33,1)
FILTER #FF9A00 (1,0.6,0,1)
BLUE #009DFF (0,0.62,1,1)
RED #FE5F55 (1,0.37,0.33,1)
GREEN #4BC292 (0.29,0.76,0.57,1)
PALE_GREEN #56A887 (0.34,0.66,0.53,1)
ORANGE #FDA200 (0.99,0.64,0,1)
IMPORTANT #FF9A00 (1,0.6,0,1)
GOLD #EAC058 (0.92,0.75,0.35,1)
YELLOW #FFFF00FF (1,1,0,1)
CLEAR #00000000 (0,0,0,0)
WHITE #FFFFFFFF (1,1,1,1)
PURPLE #8867A5 (0.53,0.4,0.65,1)
BLACK #374244 (0.22,0.26,0.27,1)
L_BLACK #4F6367 (0.31,0.39,0.4,1)
GREY #5F7377 (0.37,0.45,0.47,1)
CHANCE #4BC292 (0.29,0.76,0.57,1)
JOKER_GREY #BFC7D5 (0.75,0.78,0.84,1)
VOUCHER #CB724C (0.8,0.45,0.3,1)
BOOSTER #646EB7 (0.39,0.43,0.72,1)
EDITION #FFFFFFFF (1,1,1,1)
DARK_EDITION #000000FF (0,0,0,1)
ETERNAL #C75985 (0.78,0.35,0.52,1)
PERISHABLE #4F5DA1 (0.31,0.36,0.63,1)
RENTAL #B18F43 (0.69,0.56,0.26,1)
DYN_UI.MAIN #374244 (0.22,0.26,0.27,1)
DYN_UI.DARK #374244 (0.22,0.26,0.27,1)
DYN_UI.BOSS_MAIN #374244 (0.22,0.26,0.27,1)
DYN_UI.BOSS_DARK #374244 (0.22,0.26,0.27,1)
DYN_UI.BOSS_PALE #374244 (0.22,0.26,0.27,1)
SO_1.Hearts #F03464 (0.94,0.2,0.39,1)
SO_1.Diamonds #F06B3F (0.94,0.42,0.25,1)
SO_1.Spades #403995 (0.25,0.22,0.58,1)
SO_1.Clubs #235955 (0.14,0.35,0.33,1)
SO_2.Hearts #F83B2F (0.97,0.23,0.18,1)
SO_2.Diamonds #E29000 (0.89,0.56,0,1)
SO_2.Spades #4F31B9 (0.31,0.19,0.73,1)
SO_2.Clubs #008EE6 (0,0.56,0.9,1)
SUITS.Hearts #FE5F55 (1,0.37,0.33,1)
SUITS.Diamonds #FE5F55 (1,0.37,0.33,1)
SUITS.Spades #374649 (0.22,0.27,0.29,1)
SUITS.Clubs #424E54 (0.26,0.31,0.33,1)
UI.TEXT_LIGHT #FFFFFFFF (1,1,1,1)
UI.TEXT_DARK #4F6367 (0.31,0.39,0.4,1)
UI.TEXT_INACTIVE #88888899 (0.53,0.53,0.53,0.6)
UI.BACKGROUND_LIGHT #B8D8D8 (0.72,0.85,0.85,1)
UI.BACKGROUND_WHITE #FFFFFFFF (1,1,1,1)
UI.BACKGROUND_DARK #7A9E9F (0.48,0.62,0.62,1)
UI.BACKGROUND_INACTIVE #666666FF (0.4,0.4,0.4,1)
UI.OUTLINE_LIGHT #D8D8D8 (0.85,0.85,0.85,1)
UI.OUTLINE_LIGHT_TRANS #D8D8D866 (0.85,0.85,0.85,0.4)
UI.OUTLINE_DARK #7A9E9F (0.48,0.62,0.62,1)
UI.TRANSPARENT_LIGHT #EEEEEE22 (0.93,0.93,0.93,0.13)
UI.TRANSPARENT_DARK #22222222 (0.13,0.13,0.13,0.13)
UI.HOVER #00000055 (0,0,0,0.33)
SET.Default #CDD9DC (0.8,0.85,0.86,1)
SET.Enhanced #CDD9DC (0.8,0.85,0.86,1)
SET.Joker #424E54 (0.26,0.31,0.33,1)
SET.Tarot #424E54 (0.26,0.31,0.33,1)
SET.Planet #424E54 (0.26,0.31,0.33,1)
SET.Spectral #424E54 (0.26,0.31,0.33,1)
SET.Voucher #424E54 (0.26,0.31,0.33,1)
SECONDARY_SET.Default #9BB6BDFF (0.61,0.71,0.74,1)
SECONDARY_SET.Enhanced #8389DDFF (0.51,0.54,0.87,1)
SECONDARY_SET.Joker #708B91 (0.44,0.55,0.57,1)
SECONDARY_SET.Tarot #A782D1 (0.65,0.51,0.82,1)
SECONDARY_SET.Planet #13AFCE (0.07,0.69,0.81,1)
SECONDARY_SET.Spectral #4584FA (0.27,0.52,0.98,1)
SECONDARY_SET.Voucher #FD682B (0.99,0.41,0.17,1)
SECONDARY_SET.Edition #4CA893 (0.3,0.66,0.58,1)
RARITY.1 #009DFF (0,0.62,1,1)
RARITY.2 #4BC292 (0.29,0.76,0.57,1)
RARITY.3 #FE5F55 (1,0.37,0.33,1)
RARITY.4 #B26CBB (0.7,0.42,0.73,1)
BLIND.Small #50846E (0.31,0.52,0.43,1)
BLIND.Big #50846E (0.31,0.52,0.43,1)
BLIND.Boss #B44430 (0.71,0.27,0.19,1)
BLIND.won #4F6367 (0.31,0.39,0.4,1)
HAND_LEVELS.1 #EFEFEF (0.94,0.94,0.94,1)
HAND_LEVELS.2 #95ACFF (0.58,0.67,1,1)
HAND_LEVELS.3 #65EFAF (0.4,0.94,0.69,1)
HAND_LEVELS.4 #FAE37E (0.98,0.89,0.49,1)
HAND_LEVELS.5 #FFC052 (1,0.75,0.32,1)
HAND_LEVELS.6 #F87D75 (0.97,0.49,0.46,1)
HAND_LEVELS.7 #CAA0EF (0.79,0.63,0.94,1)
BACKGROUND.L #FFFF00FF (1,1,0,1)
BACKGROUND.D #374244 (0.22,0.26,0.27,1)
BACKGROUND.C #374244 (0.22,0.26,0.27,1)