Framework / Documentation

RustUI Documentation

The developer-first CUI engine for Rust Oxide plugins.

Meet RustUI

Building user interfaces with the native Rust Oxide CUI can be a painful experience. Most developers spend hours battling float anchors, fixing broken layouts on odd screen resolutions, and digging through massive files where layout code and core plugin logic are completely mixed up. It gets messy quickly, which is why clean, modern interfaces are rarely seen on Rust servers.

Built as an extension on top of the native Oxide CUI foundation, it introduces a clean, declarative syntax that makes UI development straightforward and organized. It cuts out the mathematical guesswork so you can focus on building great features.

Key Features

  • Expressive Syntax:

    RustUI injects the style engine directly into your component builder actions. This allows you to chain methods like SetText() or SetWidth() instantly without messy, deeply nested code blocks.

  • Contextual Payloads:

    Every user interface can receive a contextual payload via its Show() call. This lets you seamlessly pass game data, such as a clicked furnace or storage chest, directly into the UI window and completely eliminates the need for maintaining messy global dictionaries.

  • Fluid Theming:

    Crafting modern interfaces is incredibly simple. RustUI packs virtually every standard color right into its core. With fluent modifiers like Darken(), Lighten(), and transparency controls, your components look elegant out of the box.

  • Components:

    Keep your codebase clean and modular by utilizing built-in components or composing your own custom, reusable interface components directly within your plugin.

  • Intuitive State Management:

    Effortlessly change the state of your elements at runtime. With simple Update() and Refresh() calls, or by binding powerful lambda actions directly to components, managing active user interaction becomes second nature.

  • Inline Actions:

    Eliminate the need for registering cluttered plugin commands. With inline actions, you can bind executable lambdas directly to buttons and text fields, allowing your interaction logic to run directly in your UI.

Installing RustUI

Getting started with RustUI is straightforward. Because RustUI is built as a native server extension rather than a standard Oxide plugin, it integrates directly into your server core to deliver maximum performance and fluid state management without runtime overhead.

Prerequisites

Before installing, ensure your Rust server meets the following criteria:

  • Rust Server Version

    Protocol: 2632.287.1
    Build Date: 08/07/2026 11:36:35
    Unity Version: 6000.3.15x1-8
    Changeset: 160556
    Branch: release

  • Oxide Version

    Version: 2.0.7585
    Branch: master

You can use the version and oxide.version commands in your server console to verify if your Rust Server matches the prerequisites listed above.

Installation Steps

To install the framework, copy the Oxide.Ext.RustUI.dll extension file and place it directly into the RustDedicated_Data/Managed/ directory

Because RustUI loads as a native low-level assembly extension, a full server restart is required to mount the engine into the server memory. Once the server completes its boot cycle, RustUI is instantly active and ready to use.

Configuration

RustUI is completely ready out of the box, allowing you to dive straight into building a UI inside your Rust plugin.

Importing the Namespace

To begin utilizing RustUI within your Rust plugin, simply import the official framework namespace at the very top of your plugin file:

using Oxide.Ext.RustUI;

// your plugin class

That is all it takes to integrate the framework. With the namespace successfully imported and the extension running on your Rust Server, you have completely bypassed the limitations of the traditional interface engine. You are now fully equipped to move forward and start building your very first UI.

Architecture Concepts

To build beautiful and maintainable user interfaces, it is essential to understand how RustUI structures layout spaces under the hood. Traditional Rust Oxide UI development forces you to think in confusing, abstract float anchors and absolute screen coordinates. RustUI completely abandons this mathematical headaches by introducing a predictable, state-of-the-art rendering architecture inspired by the layout engines of modern web browsers.

Automatic Layout Computation

The core power of RustUI lies in its automated layout computation engine. In traditional CUI development, changing the size of a single element requires you to manually recalculate the positions of every surrounding component. RustUI handles this heavy lifting for you entirely out of the box.

The engine continuously monitors your component tree, automatically computing the exact structural dimensions and pixel values of every container in real time. Because the framework instantly understands the precise height and width of every element, you can build advanced, fluid layouts like dynamic scroll regions and complex grids without ever writing brittle mathematical formulas. If content changes, the layout automatically recalculates and shifts beautifully.

The Fluid Canvas & Inheritance

In RustUI, layout design follows a strict hierarchical inheritance pattern. By default, every child element you instantiate is automatically centered and stretches to inherit 100% of its parent container's width and height. This lets you nest components freely while maintaining relative structural control:

root.Panel((panel) =>
{
    // Configure fixed boundaries for the parent container
    panel.Style.SetWidth("600px")
               .SetHeight("400px");
         
    panel.Label((label) =>
    {
        // This label automatically inherits and fills 100% of the parent panel
        // No anchors, no manual position guessing required
    });
});

Whenever you need to deviate from this full-bleed default, you manipulate the element using expressive, native-feeling sizing parameters like SetWidth("100px") or intuitive percentages SetWidth("25%"). Furthermore, RustUI introduces native Flexbox capabilities into the Rust gaming context. You can align components horizontally or vertically, distribute space evenly, and let elements grow or shrink dynamically. The engine handles the responsive boundary shifts instantly behind the scenes, ensuring your interface renders flawlessly across all player monitor resolutions.

The RustUI Box Model

To guarantee that elements never overlap and visual borders align with absolute precision, RustUI implements a rigorous, automated 3-layer Box Model. Every standard visual component automatically encapsulates three distinct structural boundaries:

  • The Outer Rect: The absolute boundary of the element, defining its total physical footprint inside the parent container.
  • The Border Rect: An intelligent boundary layer nested inside the Outer Rect. If you define a custom border thickness, the engine automatically pushes this rect inward. This ensures your borders are rendered cleanly on the inside edges, preventing awkward visual spilling. Furthermore, each side can receive its own independent width configuration.
  • The Padding Rect (Inner Rect): The final core layer nested safely inside the Border Rect. This canvas hosts the actual inner content, preserving an unbreachable protective margin around your elements.

Visually, the hierarchical computation flow of the box model engine coordinates your element spaces like this:

+---------------------------------------------------------+
| OUTER RECT (Total Physical Footprint)                   |
| +-----------------------------------------------------+ |
| | BORDER RECT (Custom Inside Edge Borders)            | |
| | +-------------------------------------------------+ | |
| | | PADDING RECT (Inner Content Canvas)             | | |
| | |                                                 | | |
| | | [ Your Label, Image or Widget Text Here ]       | | |
| | |                                                 | | |
| | +-------------------------------------------------+ | |
| +-----------------------------------------------------+ |
+---------------------------------------------------------+

Non-Container Elements

While components like panels and buttons act as structural layout containers that can host child trees, certain elements serve purely as content terminals. In RustUI, image objects and text labels behave exactly like <img> tags in the modern web standard.

Because these elements are classified as non-containers, they cannot nest other child primitives. This architectural distinction guarantees maximum rendering performance on the server core, allowing the engine to compile and pass the final UI layout directly to the active player viewport with zero execution overhead.

Creating a UI

Every interface in RustUI starts with the RustUI.Create factory method. This method serves as the entry point for every UI you want to create.

RustUI ui = RustUI.Create(Ext.RustUI.Layer.Overlay, root => 
{
    UIWindow window  = root.Window;
});

Arg 1. Ext.RustUI.Layer

The first argument specifies the layer to bind your root element to. RustUI provides the following pre-defined layers matching the native Oxide layer stack:

  • Ext.RustUI.Layer.Under
  • Ext.RustUI.Layer.UnderNonScaled
  • Ext.RustUI.Layer.Main
  • Ext.RustUI.Layer.Hud
  • Ext.RustUI.Layer.HudMenu
  • Ext.RustUI.Layer.Overlay
  • Ext.RustUI.Layer.OverlayNonScaled
  • Ext.RustUI.Layer.Overall
  • Ext.RustUI.Layer.Inventory
  • Ext.RustUI.Layer.Crafting
  • Ext.RustUI.Layer.Contacts
  • Ext.RustUI.Layer.Clans
  • Ext.RustUI.Layer.TechTree
  • Ext.RustUI.Layer.Map

To learn more about Layers, please consult the official Oxide CUI Layer Documentation.

Arg 2. Action

The final argument is an executable lambda that fires whenever the UI renders for a player. This closure provides three highly expressive parameters to construct your UI state:

  • root: The root container acting as the canvas for your UI. You will utilize this object to attach child elements like panels, labels, and buttons.
  • root.Window: The Window Instance. This object contains the active BasePlayer Player viewing the UI, the UIPayload Payload passed to the Show() function, and the active RustUI UI instance itself.

A more complete example

Let's look at a complete example. Below, we define a new UI and implement a reactive button that dynamically updates a label's style at runtime:

RustUI ui = RustUI.Create(Ext.RustUI.Layer.Overlay, root => 
{
    UIWindow window  = root.Window;
    
    // style our root element
    root.Style.SetBlurBackground()
         .SetKeyboardEnabled(true)
         .SetCursorEnabled(true);
                            
    // create a flex column 
    root.FlexColumn((flexPanel) => 
    {
        // this styles the flex column with some basic styling
        flexPanel.Style.SetBackgroundColor(Theme.Primary.Darken(60f, 0.98f))
             .SetBorder("2px")
             .SetBorderColor(Theme.Primary.Darken(80))
             .SetOffset("50px", "50px", "50px", "50px");
        
        // create a text label and give it an ID                        
        flexPanel.Label("my_label", (label) =>
        {
            label.Style.SetText("Click on the button!")
                 .SetFontColor(Theme.Danger);
        });
        
        // create our button
        flexPanel.Button((button) =>
        {
            button.Style.SetText("Click Me")
                 .SetBackgroundColor(Theme.Primary.Darken(10f))
                 .SetHoverColor(Theme.Primary.Lighten(10f));
            
            // bind the inline click event
            button.OnClick((Event) =>
            {
                // Reactively update the target element's style at runtime
                window.Update("my_label", (style) => 
                {
                    style.SetText($"{Event.Player.displayName} clicked the button")
                         .SetFontColor(Theme.Success);
                }); 
            });
        });
    });
});

// show the UI to a specific player
ui.Show(player);

Showing the UI

RustUI offers you various ways to show a UI

  • Show the UI for one specific player

    If you want to show the UI just to one specific player then you can pass the BasePlayer object to the Show() method

    ui.Show(player)
  • Show the UI for all players

    By omitting the player object allows you to broadcast the UI to all connected players simultaneously.

    ui.Show()
  • Show the UI for a defined set of players

    You may also want to show the UI to a specific set of players, you can achieve this by passing a ListHashSet<BasePlayer> to the Show() method.

    ui.Show({ 
        player1, 
        player2 
    })

Passing a payload to the UI

You may want to pass data to the UI so it know in what context it should build the UI, for example, you want to show a player profile, in this case you need to tell the UI for which player it should create the profile layout. You can achieve this by passing a UIPayload object using tuples

ui.Show(player, new UIPayload(
    ("profilePlayer", otherPlayer)
))

Retrieving payload data

After passing a payload to the UI you can retrieve the data like so

ui = RustUI.Create(Ext.RustUI.Layer.Overlay, root =>
{
    UIWindow window   = root.Window;
    UIPayload payload = window.Payload;
    
    // retrieve the profile player from the passed payload
    BasePlayer profilePlayer = payload.Get<BasePlayer>("profilePlayer");
    
    root.Label((label) => 
    {
        label.Style.SetText($"Profile for {profilePlayer.displayName}");
    });
});

Hiding the UI

Just like showing the UI, RustUI offers also various ways to hide the UI

  • Hide the UI for one specific player

    If you want to hide the UI just to one specific player then you can pass the BasePlayer object to the Hide() method

    ui.Hide(player)
  • Hide the UI for all players

    By omitting the player object allows you to hide the UI to all connected players simultaneously.

    ui.Hide()
  • Hide the UI for a defined set of players

    You may also want to hide the UI for a specific set of players, you can achieve this by passing a ListHashSet<BasePlayer> to the Hide() method.

    ui.Hide({ 
        player1, 
        player2 
    })

Updating Elements

After the UI is shown to the player you are able to Update elements. Updating an element only renders that particular element without sending a fully re-rendered UI to the player. In order to update elements you are required to give the element an id

root.Panel("my_panel_id", panel => 
{
    
});

Now that RustUI is able to identify the panel, you are ready to manipulate the panel and stream te updated panel back to the player that is viewing the UI. Lets create a simpel button and change the background color of the panel to green when the player clicks the button

root.Panel("my_panel_id", panel => 
{
    panel.Style.BackgroundColor("red");
});

root.Button(button => 
{
    button.OnClick(Event => 
    {
        Event.Window.Update("my_panel_id", (style) => 
        {
            style.BackgroundColor("green");
        });
    });
    
});

In the example above only the window player receives the updated panel. In case you want to update the panel for all players at once you may want to call the Update method on the UI instance

root.Panel("my_panel_id", panel => 
{
    panel.Style.BackgroundColor("red");
});

root.Button(button => 
{
    button.OnClick(Event => 
    {
        // this will update the panel for all players viewing this UI
        Event.UI.Update("my_panel_id", (style) => 
        {
            style.BackgroundColor("green");
        });
    });
    
});

Refreshing Elements

Just like updating elements, elements that needs to receive a refresh require to have set an ID. Where updating elements only update the style of the element triggers a refresh a full element re-render

bool HasError = false;

root.Panel("my_panel_id", panel => 
{
    if(HasError)
    {
        panel.Style.SetBackgroundColor(UIColor.Red700);
        
        panel.Label(label => 
        {
            label.Style.SetText("An Error Occured!")
                       .SetFontColor(UIColor.Red100);
        });
        
        return;
    }
    
    panel.Style.SetBackgroundColor(UIColor.Neutral100);
});

root.Button(button => 
{
    button.OnClick(Event => 
    {
        HasError = true;
        
        Event.Window.Refresh("my_panel_id");
    });
});

Trigger Element Actions

RustUI alows you to replace the default action for an element. For example, you have build a menu with buttons and when a player clicks a button in the menu you want to trigger a action in a panel that acts like a IFRAME. This allows you to define a single panel element that dynamically changes content.

root.Panel("content_frame", panel => 
{
    panel.Label(label => 
    {
        label.Style.SetText("This is default content!");
    });
});

root.Button(button => 
{
    button.OnClick(Event => 
    {
        Event.Window.Action<ElementPanel>("content_frame", (panel) => 
        {
            panel.Label(label => 
            {
                label.Style.SetText("This is the Rules page!");
            });                                
        });
    });
    
});


root.Button(button => 
{
    button.OnClick(Event => 
    {
        Event.Window.Action<ElementPanel>("content_frame", (panel) => 
        {
            panel.Label(label => 
            {
                label.Style.SetText("This is the contact page!");
            });                                
        });
    });
    
});

root.Button(button => 
{
    button.OnClick(Event => 
    {
        // to prevent a bloating UI with tons of actions you could set a plugin method as the callback
        Event.Window.Action<ElementPanel>("content_frame", ShowSomeOtherPage});
    });
    
});

Introduction to CUI Elements

RustUI offers pre-defined elements matching the native Oxide elements stack that you can use to build your UI. Every element expects a lambda closure that receives exactly 1 argument

(element)
{
    //
}

You can use the element to:

  • Nest child elements

    root.Panel(panelElement => 
    {
        // nest a label inside the panel "element"
        panelElement.Label(labelElement => 
        {
        
        })
    });
  • Access the Style object

    root.Panel(panelElement => 
    {
        panelElement.Style.SetWidth("400px");
    });
  • Access the Window object

    root.Label(label => 
    {
        label.Style.SetText($"Hello, {label.Window.Player.displayName}");
    });

Giving elements an ID

By default every element gets a unique ID behind the scenes, but you may want to assign an ID yourself to identify the element you want to update or refresh. You can achieve this by calling the Id() method on the element:

root.Label("my_label_id", label => 
{

});

After you assigned the label ID, the label is ready to get updated or refreshed:

string labelText = "Label is sad :(";

root.Label("my_label_id", label => 
{
    label.Style.SetText(labelText)
});

root.Button(button => 
{
    button.OnClick(Event => 
    {
        labelText = "Label is happy :D";
        
        // refresh the label
        window.Refresh("my_label_id");
    });
});
Note: Make sure you give elements a unique ID! Element ID's are only bound to their respective UI, so you can assign the same ID to elements in other UI's

Panel

The panel element acts as a container and is able to accept child elements

root.Panel(panel => 
{
    panel.Style.SetWidth("600px")
               .SetHeight("400px");
});

Label

The label element is a text element, unlike the panel element the label element does not accept child elements

root.Label(label => 
{
    label.Style.SetText("Hello World!");
});

Button

The button element is a interactable element, It does accept child elements

root.Button(button => 
{
    button.Style.SetText("Submit");
});

Handle click events

A button is interactable, you can assign a lambda closure to capture and handle the event when a player clicks on the button

root.Button(button => 
{
    button.Style.SetText("Submit")
                .SetBackgroundColor(Theme.Primary)
                .SetHoverColor(Theme.Primary.Lighten(10f));
    
    button.OnClick(clickEvent => 
    {
        Puts($"{clickEvent.Player.displayName} clicked on the button");
    });
});

Using the default command string

If you want use the default command string when a player clicks on a button, then do the following:

root.Button(button => 
{
    button.Style.SetCommand("chat.say /kits");
});

Textfield

Just like the button element, the textfield element is also a interactable element, But it does not accept child elements

root.Textfield(textfield => 
{
    textfield.Style.SetAutoFocus(true)
                   .SetCharsLimit(30)
                   .SetIsPassword(false);
});

Handle change events

A textfield is interactable, you can assign a lambda closure to capture and handle the event when the input changes

root.Textfield(textfield => 
{
    textfield.Style.SetAutoFocus(true);
    
    textfield.OnChange(changeEvent => 
    {
        string value = changeEvent.Payload.Get("value", "");
        
        Puts($"{changeEvent.Player.displayName} has typed {value}");
    });
});

Using the default command string

If you want use the default command string when the input changes, then do the following:

root.Textfield(textfield => 
{
    textfield.Style.SetCommand("SomeCommandName");
});

Image

You can use the image element to display images, it does not accept child elements

The image element leverages the Image Library plugin so make sure it is installed on your Rust Server

You can download Image Library here: https://umod.org/plugins/image-library

In-Game Rust Item image

Simply pass the shortname of the In-Game Rust Item

root.Image(image => 
{
    image.Style.SetImageSource("rifle.ak");
    
    // optional skin id
    image.Style.SetSkinId(3764289135);
});

In-Game Rust Assets

If you want to display a Rust asset then pass the assets/*.png path to the image

root.Image(image => 
{
    image.Style.SetImageSource("assets/icons/fun.png");
});

Steam Image

You can do the following when you want to display a steam image for a player

root.Image(image => 
{
    image.Style.SetImageSource($"steam://{window.Player.userID}");
});

Image from a URL

To display an image from an external url then all you have to do is pass the url to the image

root.Image(image => 
{
    image.Style.SetImageSource($"https://www.iconsdb.com/icons/download/white/happy-64.png");
});

Controlling image blending

You may want to control the blending of an image

root.Image(image => 
{
    // make the image blend to red
    image.Style.SetImageBlend("red");
});

Scroller

The scroller element gives you the ability to scroll when the child elements exceeds the dimensions of the viewport, it does accept child elements

panel.Scroller(scroller =>
{
    scroller.Style.SetScrollHandleColor(Theme.Primary.Darken(60))
                  .SetScrollTrackColor(Theme.Primary.Darken(70))                                            
                  .SetHoverColor(Theme.Primary.Darken(55))                                            
                  .SetPressedColor(Theme.Primary.Darken(55));
                  
    scroller.Panel(panel => 
    {
        panel.Style.SetHeight("2000px");
    });
});

ScrollHeight

The scroller element tries to detect the scrollheight automatically, but if for some reason the scroller is not able to calculate the scrollheight correctly then you can set the scrollheight mannually

panel.Scroller(scroller =>
{
    scroller.Style.SetScrollHeight("2000px");
                  
    scroller.Panel(panel => 
    {
        panel.Style.SetHeight("2000px");
    });
});

FlexRow

The FlexRow element distributes flex items horizontally. Flex items are all equally width and height.

// create a flex row with 3 panels that are all distributed from left to right
root.FlexRow((row) =>
{
    row.Panel(panel => {
    
    });
    
    row.Panel(panel => {
    
    });
    
    row.Panel(panel => {
    
    });
});

Setting flex item width

You can adjust the width of a flex item individually. In the example below we set the width of the second flex item to 60%, flex items on the left and right will span the remaining width of the viewport equally

root.FlexRow((row) =>
{
    row.Panel(panel => 
    {
        // spans 20% of the remaining width
    });
    
    row.Panel(panel => 
    {
        panel.Style.SetWidth("60%");
    });
    
    row.Panel(panel => 
    {
        // spans 20% of the remaining width
    });
});

Flex Gap

You can tell the FlexRow how much space there should be between the flex items by setting the FlexGap property

root.FlexRow(row =>
{
    row.Style.SetFlexGap("10px");
});

Flex Reverse

You can inverse the order of the flex items by setting the FlexReverse property

root.FlexRow(row =>
{
    row.Style.SetFlexReverse(true);
});

Combining the FlexReverse property with a Button element

bool FlexReverse = false;

root.FlexRow("example_flex_row", row =>
{
    row.Style.SetFlexReverse(FlexReverse);
    
    row.Panel(panel => 
    {
        panel.Style.SetBackgroundColor("red");
    });
    
    row.Panel(panel => 
    {
        panel.Style.SetBackgroundColor("green");
    });
    
    row.Panel(panel => 
    {
        panel.Style.SetBackgroundColor("blue");
    });                        
});

root.Button(button => 
{
    button.Style.SetText("Toggle Flex Reverse");
    
    button.OnClick(clickEvent => 
    {
        FlexReverse = !FlexReverse;
        
        clickEvent.Window.Refresh("example_flex_row");
    });
});

Or instead of using a bool FlexReverse variable you could use the FlexReverse property on the element itself

row.Style.SetFlexReverse(!row.Style.FlexReverse);

FlexColumn

The FlexColumn element has the same purpose as FlexRow but a FlexColumn distributes flex items vertically. Flex items are all equally width and height.

// create a flex column with 3 panels that are all distributed from top to bottom
root.FlexColumn(column =>
{
    column.Panel(panel => {
    
    });
    
    column.Panel(panel => {
    
    });
    
    column.Panel(panel => {
    
    });
});

Setting flex item height

You can adjust the height of a flex item individually. In the example below we set the height of the second flex item to 60%, flex items above and below will span the remaining height of the viewport equally

root.FlexColumn((column) =>
{
    column.Panel(panel => 
    {
        // spans 20% of the remaining height
    });
    
    column.Panel(panel => 
    {
        panel.Style.SetHeight("60%");
    });
    
    column.Panel(panel => 
    {
        // spans 20% of the remaining height
    });
});

Flex Gap

You can tell the FlexRow how much space there should be between the flex items by setting the FlexGap property

root.FlexColumn(row =>
{
    row.Style.SetFlexGap("10px");
});

Flex Reverse

You can inverse the order of the flex items by setting the FlexReverse property

root.FlexColumn(row =>
{
    row.Style.SetFlexReverse(true);
});

Combining the FlexReverse property with a Button element

bool FlexReverse = false;

root.FlexColumn("example_flex_column", column =>
{
    column.Style.SetFlexReverse(FlexReverse);
    
    column.Panel(panel => 
    {
        panel.Style.SetBackgroundColor("red");
    });
    
    column.Panel(panel => 
    {
        panel.Style.SetBackgroundColor("green");
    });
    
    column.Panel(panel => 
    {
        panel.Style.SetBackgroundColor("blue");
    });                        
});

root.Button(button => 
{
    button.Style.SetText("Toggle Flex Reverse");
    
    button.OnClick(clickEvent => 
    {
        FlexReverse = !FlexReverse;
        
        clickEvent.Window.Refresh("example_flex_column");
    });
});

Or instead of using a bool FlexReverse variable you could use the FlexReverse property on the element itself

column.Style.SetFlexReverse(!column.Style.FlexReverse);

Bringing it all together

By combining FlexRow and FlexColumn elements you are able to create practically any template you can think of! Lets create a 3x3 grid using only Flex elements

root.FlexColumn((column) =>
{
    column.Style.SetFlexGap("10px");
    
    column.FlexRow(row => 
    {
        row.Style.SetFlexGap("10px");
        
        row.Panel(panel => 
        {
            panel.Label(label => label.Style.SetText("Item 1"));
        });
        
        row.Panel(panel => 
        {
            panel.Label(label => label.Style.SetText("Item 2"));
        });

        row.Panel(panel => 
        {
            panel.Label(label => label.Style.SetText("Item 3"));
        });
    });
    
    column.FlexRow(row => 
    {
        row.Style.SetFlexGap("10px");
        
        row.Panel(panel => 
        {
            panel.Label(label => label.Style.SetText("Item 4"));
        });
        
        row.Panel(panel => 
        {
            panel.Label(label => label.Style.SetText("Item 5"));
        });

        row.Panel(panel => 
        {
            panel.Label(label => label.Style.SetText("Item 6"));
        });
    });
    
    column.FlexRow(row => 
    {
        row.Style.SetFlexGap("10px");
        
        row.Panel(panel => 
        {
            panel.Label(label => label.Style.SetText("Item 7"));
        });
        
        row.Panel(panel => 
        {
            panel.Label(label => label.Style.SetText("Item 8"));
        });

        row.Panel(panel => 
        {
            panel.Label(label => label.Style.SetText("Item 9"));
        });
    });                        
});

Or use the build-in GridView component

root.Component<GridView<string>>(component =>
{
    component.GridId = "grid_example";
    component.UseScroll = false;
    component.ItemsPerRow = 3;
    component.FlexGap = 10f;
    component.Items = new List<string>(){"1", "2", "3", "4", "5", "6", "7", "8", "9"};
    component.ItemAction = (container, item) =>
    {
        container.Label(label => 
        {
            label.Style.SetText($"Item {item}")
        });
    }
});

Custom

The Custom element allows you to mannually pass Oxide CUI Components and compose the element as you like. RustUI will take care of the element position and size like any other element.

using Oxide.Game.Rust.Cui;

panel.Custom(custom =>
{
    custom.Components.Add(new CuiOutlineComponent 
    { 
        Color = "0 0 0 1",
        Distance = "2 2",
        UseGraphicAlpha = false
    });
});

Custom elements also supports nesting child elements like all container elements

using Oxide.Game.Rust.Cui;

panel.Custom(custom =>
{
    custom.Components.Add(new CuiOutlineComponent 
    { 
        Color = "0 0 0 1",
        Distance = "2 2",
        UseGraphicAlpha = false
    });
    
    custom.Image(image =>
    {
        image.Style.SetImageSource("rifle.ak");
    });                        
});

Element Styles

Every element in RustUI has a Style property that you can use to style or configure the element. All of these methods may be chained to fluently manipulate the underlying Style object. You can find every style option in the list below.

Available Styles

Autofocus

Sets or gets the autofocus of the textfield

// setters
element.Style.SetAutofocus(false); 

// getter
bool value = element.Style.Autofocus;

AutoScrollHeight

Sets or gets if scroll height should automatically get calculated

// setter
element.Style.SetAutoScrollHeight(true);

// getter
bool value = element.Style.AutoScrollHeight;

BackgroundColor

Sets or gets the background color

// setter
element.Style.SetBackgroundColor("black");

// getter
UIColor value = element.Style.BackgroundColor;

BackgroundImage

Sets or gets the background image of a panel, this can be set to an material, sprite, icon, rust item or external images

// setter
element.Style.SetBackgroundImage(Materials.Binocular);

// or and external image
element.Style.SetBackgroundImage("https://example.com/image.png");

// or a sprite
element.Style.SetBackgroundImage(Sprites.SkewedGradient);


// getter
UIColor value = element.Style.BackgroundImage;

Border

Sets multiple borders at once

// setter per side
element.Style.SetBorder(top: "10px", right: "10px", bottom: "10px", left: "10px");

// setter all at once
element.Style.SetBorder("10px");

BorderBottom

Sets or gets the bottom border

// setter
element.Style.SetBorderBottom("10px");

// getter
LayoutValue value = element.Style.BorderBottom;

BorderBottomColor

Sets or gets the bottom border color

// setter
element.Style.SetBorderBottomColor(Theme.Primary);

// getter
UIColor value = element.Style.BorderBottomColor;

BorderColor

Sets multiple border colors at once

// setter per side
element.Style.SetBorder(top: UIColor.Zinc500, right: UIColor.Zinc600, bottom: UIColor.Zinc700, left: UIColor.Zinc800);

// setter all at once
element.Style.SetBorder(Theme.Secondary.Lighten(10f));

BorderLeft

Sets or gets the left border

// setter
element.Style.SetBorderLeft("10px");

// getter
LayoutValue value = element.Style.BorderLeft;

BorderLeftColor

Sets or gets the left border color

// setter
element.Style.SetBorderLeftColor(Theme.Secondary);

// getter
UIColor value = element.Style.BorderLeftColor;

BorderRight

Sets or gets the right border

// setter
element.Style.SetBorderRight("10px");

// getter
LayoutValue value = element.Style.BorderRight;

BorderRightColor

Sets or gets the right border color

// setter
element.Style.SetBorderRightColor(UIColor.Zinc500);

// getter
UIColor value = element.Style.BorderRightColor;

BorderTop

Sets or gets the top border

// setter
element.Style.SetBorderTop("100px");

// getter
LayoutValue value = element.Style.BorderTop;

BorderTopColor

Sets or gets the top border color

// setter
element.Style.SetBorderTopColor("black");

// getter
UIColor value = element.Style.BorderTopColor;

Bottom

Sets or gets the bottom offset

// setter
element.Style.SetBottom("10px");

// getter
LayoutValue value = element.Style.Bottom;

BoxShadowColor

Sets or gets the color of the box shadow

// setters
element.Style.SetBoxShadowColor(UIColor.Zinc800.SetAlpha(80f)); 

// getter
UIColor value = element.Style.BoxShadowColor;

BoxShadowPosition

Sets or gets the position of the box shadow

// setters
element.Style.SetBoxShadowPosition("1 1"); 

// getter
string value = element.Style.BoxShadowPosition;

CharsLimit

Sets or gets the max chars of the textfield

// setters
element.Style.SetCharsLimit(30); 

// getter
int value = element.Style.CharsLimit;

ColorMultiplier

Sets or gets the color multiplier (applies to the button element)

// setter
element.Style.SetColorMultiplier(1f);

// getter
float? value = element.Style.ColorMultiplier;

Command

Sets or gets the command that should get executed (buttons and textfields)

// setters
element.Style.SetCommand("chat.say /kits"); 

// getter
string value = element.Style.Command;

CursorEnabled

Enables or disables the cursor in the UI

// setter
element.Style.SetCursorEnabled(true);

// getter
bool value = element.Style.CursorEnabled;

Disabled

Sets or gets if the element is disabled or enabled

// setter
element.Style.SetDisabled(false);

// getter
bool value = element.Style.Disabled;

DisabledColor

Sets or gets the color when the element is disabled

// setters
element.Style.SetDisabledColor(UIColor.Neutral400); 

// getter
UIColor value = element.Style.DisabledColor;

FadeIn

Sets or gets the duration the element should fadeIn

// setters
element.Style.SetFadeIn(1f); 

// getter
float value = element.Style.FadeIn;

FadeOut

Sets or gets the duration the element should fadeOut

// setters
element.Style.SetFadeOut(1f); 

// getter
float value = element.Style.FadeOut;

FlexDirection

Sets or gets the direction of the flex container

// setters
element.Style.SetFlexDirection("row"); 
element.Style.SetFlexDirection("column"); 

// getter
string value = element.Style.FlexDirection;

FlexGap

Sets or gets the gap between flex items

// setters
element.Style.SetFlexGap("10px"); 

// getter
LayoutValue? value = element.Style.FlexGap;

FlexReverse

Sets or gets the order of the flex items

// setters
element.Style.SetFlexReverse(false); 

// getter
bool value = element.Style.FlexReverse;

FontColor

Sets or gets the font color

// setter
element.Style.SetFontColor("black");

// getter
UIColor value = element.Style.FontColor;

FontFamily

Sets or gets the font family

// setters
element.Style.SetFontFamily("RobotoCondensed-Bold.ttf"); 
element.Style.SetFontFamily("DroidSansMono.ttf"); 
element.Style.SetFontFamily("PermanentMarker.ttf"); 
element.Style.SetFontFamily("RobotoCondensed-Regular.ttf"); // default

// getter
string value = element.Style.FontFamily;

FontSize

Sets or gets the font size

// setter
element.Style.SetFontSize(14);

// getter
int value = element.Style.FontSize;

Height

Sets or gets the height

// setter
element.Style.SetHeight("100px");

// getter
LayoutValue value = element.Style.Height;

HoverColor

Sets or gets the color when hovering over a button or scrollhandle

// setters
element.Style.SetHoverColor(Theme.Primary.Lighten(5f)); 

// getter
UIColor value = element.Style.HoverColor;

ImageSource

Sets or gets the image source

// setters
element.Style.SetImageSource("rifle.ak"); 

// getter
string value = element.Style.ImageSource;

ImageBlend

Sets or gets the blending of the image

// setters
element.Style.SetImageBlend(Theme.Primary.SetAlpha(0.5f)); 

// getter
string value = element.Style.ImageBlend;

ImageType

Sets or gets the image type for images

// setters
element.Style.SetImageType(UnityEngine.UI.Image.Type.Filled); 
element.Style.SetImageType(UnityEngine.UI.Image.Type.Tiled); 
element.Style.SetImageType(UnityEngine.UI.Image.Type.Sliced); 
element.Style.SetImageType(UnityEngine.UI.Image.Type.Simple); 

// getter
UnityEngine.UI.Image.Type value = element.Style.ImageType;

IsPassword

Sets or gets if the textfield is a password field

// setters
element.Style.SetIsPassword(false); 

// getter
bool value = element.Style.IsPassword;

KeyboardEnabled

Enables or disables the player movement while the UI is open

// setter
element.Style.SetKeyboardEnabled(false);

// getter
bool value = element.Style.KeyboardEnabled;

Left

Sets or gets the left offset

// setter
element.Style.SetLeft("10px");

// getter
LayoutValue value = element.Style.Left;

LineType

Sets or gets the linetype of the textfield element

// setter
element.Style.SetTextAlign(InputField.LineType.SingleLine); 
element.Style.SetTextAlign(InputField.LineType.MultiLineSubmit); 
element.Style.SetTextAlign(InputField.LineType.MultiLineNewline); 

// getter
InputField.LineType value = element.Style.LineType;

Offset

Sets multiple offsets at once

// setter per side
element.Style.SetOffset(top: "10px", right: "10px", bottom: "10px", left: "10px");

// setter all at once
element.Style.SetOffset("10px");

Padding

Sets multiple paddings at once

// setter per side
element.Style.SetPadding(top: "10px", right: "10px", bottom: "10px", left: "10px");

// setter all at once
element.Style.SetPadding("10px");

PaddingBottom

Sets or gets the bottom padding

// setter
element.Style.SetPaddingBottom("10px");

// getter
LayoutValue value = element.Style.PaddingBottom;

PaddingLeft

Sets or gets the left padding

// setter
element.Style.SetPaddingLeft("10px");

// getter
LayoutValue value = element.Style.PaddingLeft;

PaddingRight

Sets or gets the right padding

// setter
element.Style.SetPaddingRight("10px");

// getter
LayoutValue value = element.Style.PaddingRight;

PaddingTop

Sets or gets the top padding

// setter
element.Style.SetPaddingTop("100px");

// getter
LayoutValue value = element.Style.PaddingTop;

PressedColor

Sets or gets the color when pressing a button or scrollhandle

// setters
element.Style.SetPressedColor(Theme.Primary.Lighten(5f)); 

// getter
UIColor value = element.Style.PressedColor;

ReadOnly

Sets or gets if the textfield is a readonly textfield

// setters
element.Style.SetReadOnly(false); 

// getter
bool value = element.Style.ReadOnly;

Right

Sets or gets the right offset

// setter
element.Style.SetRight("10px");

// getter
LayoutValue value = element.Style.Right;

ScrollHeight

Sets or gets a forced scroll height

// setter
element.Style.SetScrollHeight("2000px");

// getter
LayoutValue value = element.Style.ScrollHeight;

ScrollHandleColor

Sets or gets the color of the scroll handle

// setters
element.Style.SetScrollHandleColor(UIColor.Zinc800); 

// getter
UIColor value = element.Style.ScrollHandleColor;

ScrollHandleWidth

Sets or gets the with of the scroll handle

// setters
element.Style.SetScrollHandleWidth(8); 

// getter
int value = element.Style.ScrollHandleWidth;

ScrollTrackColor

Sets or gets the color of the scroll track

// setters
element.Style.SetScrollTrackColor(UIColor.Zinc500); 

// getter
UIColor value = element.Style.ScrollTrackColor;

SkinId

Sets or gets the skinID of the image (shortnamed images)

// setters
element.Style.SetSkinId(3764289135); 

// getter
ulong value = element.Style.SkinId;

Text

Sets or gets the text in a label or button

// setter
element.Style.SetText("Hello World!");

// getter
string value = element.Style.Text;

TextAlign

Sets or gets the text alignment

// setters
element.Style.SetTextAlign(TextAnchor.UpperLeft); 
element.Style.SetTextAlign(TextAnchor.UpperCenter); 
element.Style.SetTextAlign(TextAnchor.UpperRight); 
element.Style.SetTextAlign(TextAnchor.MiddleLeft); 
element.Style.SetTextAlign(TextAnchor.MiddleCenter); 
element.Style.SetTextAlign(TextAnchor.MiddleRight); 
element.Style.SetTextAlign(TextAnchor.LowerLeft); 
element.Style.SetTextAlign(TextAnchor.LowerCenter); 
element.Style.SetTextAlign(TextAnchor.LowerRight); 

// getter
TextAnchor value = element.Style.TextAlign;

TextShadowColor

Sets or gets the text shadow (outline)

// setters
element.Style.SetTextShadowColor("0 0 0 0.5"); 

// getter
UIColor value = element.Style.TextShadowColor;

TextShadowPosition

Sets or gets the position of the text shadow (outline)

// setters
element.Style.SetTextShadowPosition("1 1"); 

// getter
string value = element.Style.TextShadowPosition;

TextWrap

Sets or gets the text wrap of the label element

// setters
element.Style.SetTextWrap(VerticalWrapMode.Truncate); 
element.Style.SetTextWrap(VerticalWrapMode.Overflow); 

// getter
VerticalWrapMode value = element.Style.TextWrap;

TooltipDelay

Sets or gets the duration on how long the tooltip stays visible

// setters
element.Style.SetTooltipDelay(Tooltip.DelayType.Short); 
element.Style.SetTooltipDelay(Tooltip.DelayType.Long); 

// getter
Tooltip.DelayType value = element.Style.TooltipDelay;

TooltipEnabled

Sets or gets if the tooltip is enabled

// setters
element.Style.SetTooltipEnabled(true);

// getter
bool value = element.Style.TooltipEnabled;

TooltipPosition

Sets or gets the position of the tooltip

// setters
element.Style.SetTooltipPosition(TooltipContainer.PositionMode.Auto);
element.Style.SetTooltipPosition(TooltipContainer.PositionMode.Top);
element.Style.SetTooltipPosition(TooltipContainer.PositionMode.Bottom);
element.Style.SetTooltipPosition(TooltipContainer.PositionMode.Left);
element.Style.SetTooltipPosition(TooltipContainer.PositionMode.Right);
element.Style.SetTooltipPosition(TooltipContainer.PositionMode.TopLeft);

// getter
TooltipContainer.PositionMode value = element.Style.TooltipPosition;

TooltipText

Sets or gets the text of a tooltip when a player hovers over de element

// setters
element.Style.SetTooltipText("Hello World!"); 

// getter
string value = element.Style.TooltipText;

TooltipType

Sets or gets the tooltip type

// setters
element.Style.SetTooltipDelay(CommunityEntity.TooltipType.Default); 
element.Style.SetTooltipDelay(CommunityEntity.TooltipType.AlwaysOnTop); 
element.Style.SetTooltipDelay(CommunityEntity.TooltipType.AlwaysOnTopEmoji); 

// getter
CommunityEntity.TooltipType value = element.Style.TooltipType;

TooltipUseCentre

Sets or gets the if the text of the tooltip should get centered

// setters
element.Style.SetTooltipUseCentre(true); 

// getter
bool value = element.Style.TooltipUseCentre;

Top

Sets or gets the top offset

// setter
element.Style.SetTop("100px");

// getter
LayoutValue value = element.Style.Top;

Width

Sets or gets the width

// setter
element.Style.SetWidth("100px");

// getter
LayoutValue value = element.Style.Width;

Themes

RustUI lets you style your interfaces using a dedicated theme engine.

Instead of hardcoding colors, margins, and sizes on every single button or panel, the framework uses a straightforward CSS-like approach. This means you can write clean, reusable stylesheet rules using selectors you already know, such as classes, IDs, child relations, and even pseudo-states. It completely separates your layout structure from your styling, keeping your plugin code organized and much easier to maintain as your project grows.

Writing your stylesheets feels just like writing traditional CSS, wrapped in a clean, fluent C# API:

// Matches every "ElementButton" element
Theme.Css("ElementButton", style => 
{
   style.SetWidth("120px")
        .SetHeight("40px")
        .SetBackgroundColor(UIColor.Gray700)
        .SetHoverColor(UIColor.Gray600);
});

// Matches every "ElementButton" element inside a parent with a "dashboard_panel" ID
Theme.Css("#dashboard_panel ElementButton", style => 
{
   style.SetBackgroundColor(UIColor.Cyan600);
});

// Matches the element with "submit_btn" ID that has a disabled state
Theme.Css("#submit_btn:disabled", style => 
{
   style.SetBackgroundColor(UIColor.Gray500);
});

// Matches every "odd" element with class "item" nested inside the "GridView" component
Theme.Css("ComponentPanel.GridView .item:nth-child(odd)", style => 
{
   style.SetBackgroundColor("#1e1e1e");
});

Available Selectors

  • ElementType

    Matches elements based on their exact Element class name or any base class they inherit from (e.g., ElementButton or PanelElement).

  • .class

    Matches any element that contains the specified class name.

  • #id

    Matches the unique element whose Id() method exactly matches the specified ID string.

  • .class1.class2

    Matches a single element that possesses all consecutive class names simultaneously (Compound Selector).

  • #id.class

    Matches a specific element based on its unique ID, but only if the element currently possesses the specified class name as well.

  • ComponentPanel.ComponentType

    Matches your custom RustUI component wrappers by inspecting whether the internal Component type matches the ComponentType (supports generic classes like GridView).

  • selector, selector

    Allows applying the same style rules to multiple independent target selectors separated by commas.

  • selector selector

    Matches an element that is deeply nested anywhere inside (as a descendant of) a specific ancestor element (Descendant Selector).

  • selector > selector

    Matches an element only if it is a direct and immediate child of the specified parent element (Child Selector).

  • selector + selector

    Matches an element only if it is a adjacent of the specified element (Right Sibling).

  • :disabled

    Matches elements that have their Style.Disabled state set to true. This rule is automatically given extra specificity weight.

  • :first-child

    Matches an element only if it occupies the very first position (Index() == 0) within its parent's children list.

  • :last-child

    Matches an element only if it occupies the absolute last position within its parent's children list.

  • :only-child

    Matches an element if it is the sole and only child element contained within its parent's list.

  • :nth-child(even)

    Matches all elements occupying an even numerical position (2, 4, 6, etc.) within their parent, ideal for zebra-striping grids.

  • :nth-child(odd)

    Matches all elements occupying an odd numerical position (1, 3, 5, etc.) within their parent.

  • :nth-child(number)

    Matches an element occupying an exact, specific index position within its parent (e.g., :nth-child(3) for the third element).

  • :not(selector)

    Negates the matching logic; applies styles to the element only if it does NOT satisfy the selector conditions inside the parentheses (e.g., :not(.active)).

  • :is(selector)

    Applies styles to the element only if it does satisfy the selector conditions inside the parentheses (e.g., :is(.active)).

  • :has(selector)

    Applies styles to the parent element only if at least one of its child or descendant elements satisfies the selector conditions inside the parentheses (e.g., .card:has(ElementImage)).

Creating A Theme

Lets define a basic theme:

Theme.Primary     = UIColor.Cyan600;

Theme.Secondary   = UIColor.LightGreen;

Theme.Background  = Theme.Primary.Darken(percent: 50f, alpha: 0.5f);

Theme.FontColor   = Theme.Primary.Lighten(percent: 80f, alpha: 0.8f);

Theme.Css(".my-panel", style => 
{
   style.SetBackgroundColor(Theme.Background);
});

Theming Elements

RustUI also offers you the option to theme basic elements like buttons, textfield and labels. After you applied the default theme styles on your elements will inherit these style when you create the element inside your UI.

Theme.Primary     = UIColor.Cyan600;

Theme.Secondary   = UIColor.LightGreen;

Theme.Background  = Theme.Primary.Darken(percent: 50f, alpha: 0.5f);

Theme.FontColor   = Theme.Primary.Lighten(percent: 80f, alpha: 0.8f);

Theme.Css("ElementButton", (style) =>
{
    style.SetBackgroundColor(Primary)
         .SetHoverColor(Theme.Primary.Lighten(20f))
         .SetMaterial(Materials.Binocular)
         .SetBorderColor(Theme.Primary.Darken(20f))
         .SetBorder("0px");                
});

Theme.Css("ElementButton.secondary", (style) =>
{
    style.SetBackgroundColor(Theme.Secondary)
         .SetHoverColor(Theme.Secondary.Lighten(20f))
         .SetBorderColor(Theme.Secondary.Darken(20f));                
});

Theme.Css("ElementButton.success", (style) =>
{
    style.SetBackgroundColor(Theme.Success)
         .SetHoverColor(Theme.Success.Lighten(20f))
         .SetBorderColor(Theme.Success.Darken(20f));                
});

Theme.Css("ElementButton.danger", (style) =>
{
    style.SetBackgroundColor(Theme.Danger)
         .SetHoverColor(Theme.Danger.Lighten(20f))
         .SetBorderColor(Theme.Danger.Darken(20f));                
});

Theme.Css("ElementButton.warning", (style) =>
{
    style.SetBackgroundColor(Theme.Warning)
         .SetHoverColor(Theme.Warning.Lighten(20f))
         .SetBorderColor(Theme.Warning.Darken(20f));                
});

Theme.Css("ElementButton.info", (style) =>
{
    style.SetBackgroundColor(Theme.Info)
         .SetHoverColor(Theme.Info.Lighten(20f))
         .SetBorderColor(Theme.Info.Darken(20f));                
});

Theme.Css("ElementScroller", (style) =>
{
    style.SetScrollHandleColor(Theme.Primary.Darken(60))
         .SetScrollTrackColor(Theme.Primary.Darken(70))                                            
         .SetHoverColor(Theme.Primary.Darken(55))                                            
         .SetPressedColor(Theme.Primary.Darken(55));                
});

UI Colors

The UIColor object provides an expressive, fluid interface for accessing the most commonly used colors in modern UI design. Out of the box, it arms your application with a beautiful, comprehensive palette right at your fingertips. Beyond basic values, UIColor instances unlock powerful color-manipulation capabilities. You may chain fluent methods such as Darken() and Lighten() directly onto any defined color.

Lighten a color

element.Style.SetBackgroundColor(UIColor.Cyan900.Lighten(20f));

Darken a color

element.Style.SetBackgroundColor(UIColor.Cyan900.Darken(percent: 20f));

Applying Alpha

element.Style.SetBackgroundColor(UIColor.Cyan900.Darken(percent: 20f, alpha: 0.5f));

// or use the SetAlpha method
element.Style.SetBackgroundColor(UIColor.Cyan900.SetAlpha(0.5f));

Named Colors

The UIColor object gives you the option to define a color by name, hex, rgba and Rust format

// named
element.Style.SetBackgroundColor("cyan900");

// hex
element.Style.SetBackgroundColor("#164e63");

// rgb
element.Style.SetBackgroundColor("rgba(22,78,99)");

// rgba
element.Style.SetBackgroundColor("rgba(22,78,99,1)");

// hsl
element.Style.SetBackgroundColor("hsl(196,64%,24%)");

// rust
element.Style.SetBackgroundColor("0.08627 0.30588 0.38824 1.0");

Available Colors

Simply click any color block to copy its signature to your clipboard.

UIColor.Success#66BB6A
UIColor.Info#3D85C6
UIColor.Warning#F39C12
UIColor.Danger#D93F33
UIColor.White#ffffff
UIColor.Black#000000
UIColor.Slate50#f8fafc
UIColor.Slate100#f1f5f9
UIColor.Slate200#e2e8f0
UIColor.Slate300#cbd5e1
UIColor.Slate400#94a3b8
UIColor.Slate500#64748b
UIColor.Slate600#475569
UIColor.Slate700#334155
UIColor.Slate800#1e293b
UIColor.Slate900#0f172a
UIColor.Slate950#020617
UIColor.Gray50#f9fafb
UIColor.Gray100#f3f4f6
UIColor.Gray200#e5e7eb
UIColor.Gray300#d1d5db
UIColor.Gray400#9ca3af
UIColor.Gray500#6b7280
UIColor.Gray600#4b5563
UIColor.Gray700#374151
UIColor.Gray800#1f2937
UIColor.Gray900#111827
UIColor.Gray950#030712
UIColor.Zinc50#fafafa
UIColor.Zinc100#f4f4f5
UIColor.Zinc200#e4e4e7
UIColor.Zinc300#d4d4d8
UIColor.Zinc400#a1a1aa
UIColor.Zinc500#71717a
UIColor.Zinc600#52525b
UIColor.Zinc700#3f3f46
UIColor.Zinc800#27272a
UIColor.Zinc900#18181b
UIColor.Zinc950#09090b
UIColor.Neutral50#fafafa
UIColor.Neutral100#f5f5f5
UIColor.Neutral200#e5e5e5
UIColor.Neutral300#d4d4d4
UIColor.Neutral400#a3a3a3
UIColor.Neutral500#737373
UIColor.Neutral600#525252
UIColor.Neutral700#404040
UIColor.Neutral800#262626
UIColor.Neutral900#171717
UIColor.Neutral950#0a0a0a
UIColor.Stone50#fafaf9
UIColor.Stone100#f5f5f4
UIColor.Stone200#e7e5e4
UIColor.Stone300#d6d3d1
UIColor.Stone400#a8a29e
UIColor.Stone500#78716c
UIColor.Stone600#57534e
UIColor.Stone700#44403c
UIColor.Stone800#292524
UIColor.Stone900#1c1917
UIColor.Stone950#0c0a09
UIColor.Red50#fef2f2
UIColor.Red100#fee2e2
UIColor.Red200#fecaca
UIColor.Red300#fca5a5
UIColor.Red400#f87171
UIColor.Red500#ef4444
UIColor.Red600#dc2626
UIColor.Red700#b91c1c
UIColor.Red800#991b1b
UIColor.Red900#7f1d1d
UIColor.Red950#450a0a
UIColor.Orange50#fff7ed
UIColor.Orange100#ffedd5
UIColor.Orange200#fed7aa
UIColor.Orange300#fdba74
UIColor.Orange400#fb923c
UIColor.Orange500#f97316
UIColor.Orange600#ea580c
UIColor.Orange700#c2410c
UIColor.Orange800#9a3412
UIColor.Orange900#7c2d12
UIColor.Orange950#431407
UIColor.Amber50#fffbeb
UIColor.Amber100#fef3c7
UIColor.Amber200#fde68a
UIColor.Amber300#fcd34d
UIColor.Amber400#fbbf24
UIColor.Amber500#f59e0b
UIColor.Amber600#d97706
UIColor.Amber700#b45309
UIColor.Amber800#92400e
UIColor.Amber900#78350f
UIColor.Amber950#451a03
UIColor.Yellow50#fefce8
UIColor.Yellow100#fef9c3
UIColor.Yellow200#fef08a
UIColor.Yellow300#fde047
UIColor.Yellow400#facc15
UIColor.Yellow500#eab308
UIColor.Yellow600#ca8a04
UIColor.Yellow700#a16207
UIColor.Yellow800#854d0e
UIColor.Yellow900#713f12
UIColor.Yellow950#422006
UIColor.Lime50#f7fee7
UIColor.Lime100#ecfccb
UIColor.Lime200#d9f99d
UIColor.Lime300#bef264
UIColor.Lime400#a3e635
UIColor.Lime500#84cc16
UIColor.Lime600#65a30d
UIColor.Lime700#4d7c0f
UIColor.Lime800#3f6212
UIColor.Lime900#365314
UIColor.Lime950#1a2e05
UIColor.Green50#f0fdf4
UIColor.Green100#dcfce7
UIColor.Green200#bbf7d0
UIColor.Green300#86efac
UIColor.Green400#4ade80
UIColor.Green500#22c55e
UIColor.Green600#16a34a
UIColor.Green700#15803d
UIColor.Green800#166534
UIColor.Green900#14532d
UIColor.Green950#052e16
UIColor.Emerald50#ecfdf5
UIColor.Emerald100#d1fae5
UIColor.Emerald200#a7f3d0
UIColor.Emerald300#6ee7b7
UIColor.Emerald400#34d399
UIColor.Emerald500#10b981
UIColor.Emerald600#059669
UIColor.Emerald700#047857
UIColor.Emerald800#065f46
UIColor.Emerald900#064e3b
UIColor.Emerald950#022c22
UIColor.Teal50#f0fdfa
UIColor.Teal100#ccfbf1
UIColor.Teal200#99f6e4
UIColor.Teal300#5eead4
UIColor.Teal400#2dd4bf
UIColor.Teal500#14b8a6
UIColor.Teal600#0d9488
UIColor.Teal700#0f766e
UIColor.Teal800#115e59
UIColor.Teal900#134e4a
UIColor.Teal950#042f2e
UIColor.Cyan50#ecfeff
UIColor.Cyan100#cffafe
UIColor.Cyan200#a5f3fc
UIColor.Cyan300#67e8f9
UIColor.Cyan400#22d3ee
UIColor.Cyan500#06b6d4
UIColor.Cyan600#0891b2
UIColor.Cyan700#0e7490
UIColor.Cyan800#155e75
UIColor.Cyan900#164e63
UIColor.Cyan950#083344
UIColor.Sky50#f0f9ff
UIColor.Sky100#e0f2fe
UIColor.Sky200#bae6fd
UIColor.Sky300#7dd3fc
UIColor.Sky400#38bdf8
UIColor.Sky500#0ea5e9
UIColor.Sky600#0284c7
UIColor.Sky700#0369a1
UIColor.Sky800#075985
UIColor.Sky900#0c4a6e
UIColor.Sky950#031b2e
UIColor.AliceBlue#F0F8FF
UIColor.AntiqueWhite#FAEBD7
UIColor.Aqua#00FFFF
UIColor.Aquamarine#7FFFD4
UIColor.Azure#F0FFFF
UIColor.Beige#F5F5DC
UIColor.Bisque#FFE4C4
UIColor.BlanchedAlmond#FFEBCD
UIColor.BlueViolet#8A2BE2
UIColor.Brown#A52A2A
UIColor.Burlywood#DEB887
UIColor.CadetBlue#5F9EA0
UIColor.Chartreuse#7FFF00
UIColor.Chocolate#D2691E
UIColor.Coral#FF7F50
UIColor.CornflowerBlue#6495ED
UIColor.Cornsilk#FFF8DC
UIColor.Crimson#DC143C
UIColor.DarkBlue#00008B
UIColor.DarkCyan#008B8B
UIColor.DarkGoldenrod#B8860B
UIColor.DarkGray#A9A9A9
UIColor.DarkGreen#006400
UIColor.DarkKhaki#BDB76B
UIColor.DarkMagenta#8B008B
UIColor.DarkOliveGreen#556B2F
UIColor.DarkOrange#FF8C00
UIColor.DarkOrchid#9932CC
UIColor.DarkRed#8B0000
UIColor.DarkSalmon#E9967A
UIColor.DarkSeaGreen#8FBC8F
UIColor.DarkSlateBlue#483D8B
UIColor.DarkSlateGray#2F4F4F
UIColor.DarkTurquoise#00CED1
UIColor.DarkViolet#9400D3
UIColor.DeepPink#FF1493
UIColor.DeepSkyBlue#00BFFF
UIColor.DimGray#696969
UIColor.DodgerBlue#1E90FF
UIColor.Firebrick#B22222
UIColor.FloralWhite#FFFAF0
UIColor.ForestGreen#228B22
UIColor.Gainsboro#DCDCDC
UIColor.GhostWhite#F8F8FF
UIColor.Gold#FFD700
UIColor.Goldenrod#DAA520
UIColor.GreenYellow#ADFF2F
UIColor.Honeydew#F0FFF0
UIColor.HotPink#FF69B4
UIColor.IndianRed#CD5C5C
UIColor.Ivory#FFFFF0
UIColor.Khaki#F0E68C
UIColor.Lavender#E6E6FA
UIColor.LavenderBlush#FFF0F5
UIColor.LawnGreen#7CFC00
UIColor.LemonChiffon#FFFACD
UIColor.LightBlue#ADD8E6
UIColor.LightCoral#F08080
UIColor.LightCyan#E0FFFF
UIColor.LightGoldenrodYellow#FAFAD2
UIColor.LightGray#D3D3D3
UIColor.LightGreen#90EE90
UIColor.LightPink#FFB6C1
UIColor.LightSalmon#FFA07A
UIColor.LightSeaGreen#20B2AA
UIColor.LightSkyBlue#87CEFA
UIColor.LightSlateGray#778899
UIColor.LightSteelBlue#B0C4DE
UIColor.LightYellow#FFFFE0
UIColor.LimeGreen#32CD32
UIColor.Linen#FAF0E6
UIColor.MediumAquamarine#66CDAA
UIColor.MediumBlue#0000CD
UIColor.MediumOrchid#BA55D3
UIColor.MediumPurple#9370DB
UIColor.MediumSeaGreen#3CB371
UIColor.MediumSlateBlue#7B68EE
UIColor.MediumSpringGreen#00FA9A
UIColor.MediumTurquoise#48D1CC
UIColor.MediumVioletRed#C71585
UIColor.MidnightBlue#191970
UIColor.MintCream#F5FFFA
UIColor.MistyRose#FFE4E1
UIColor.Moccasin#FFE4B5
UIColor.NavajoWhite#FFDEAD
UIColor.Navy#000080
UIColor.OldLace#FDF5E6
UIColor.Olive#808000
UIColor.OliveDrab#6B8E23
UIColor.Orchid#DA70D6
UIColor.PaleGoldenrod#EEE8AA
UIColor.PaleGreen#98FB98
UIColor.PaleTurquoise#AFEEEE
UIColor.PaleVioletRed#DB7093
UIColor.PapayaWhip#FFEFD5
UIColor.PeachPuff#FFDAB9
UIColor.Peru#CD853F
UIColor.Plum#DDA0DD
UIColor.PowderBlue#B0E0E6
UIColor.RosyBrown#BC8F8F
UIColor.RoyalBlue#4DAAC7
UIColor.SaddleBrown#8B4513
UIColor.Salmon#FA8072
UIColor.SandyBrown#F4A460
UIColor.SeaGreen#2E8B57
UIColor.SeaShell#FFF5EE
UIColor.Sienna#A0522D
UIColor.Silver#C0C0C0
UIColor.SkyBlue#87CEEB
UIColor.SlateBlue#6A5ACD
UIColor.SlateGray#708090
UIColor.Snow#FFFAFA
UIColor.SpringGreen#00FF7F
UIColor.SteelBlue#4682B4
UIColor.Tan#D2B48C
UIColor.Thistle#D8BFD8
UIColor.Tomato#FF6347
UIColor.Turquoise#40E0D0
UIColor.Violet#EE82EE
UIColor.Wheat#F5DEB3
UIColor.WhiteSmoke#F5F5F5
UIColor.YellowGreen#9ACD32

Components

RustUI gives you the ability to theme your UI. You can create multiple themes and bind a theme to individual UI's.

Core Components

Components allows you to inject powerful reusable functionality in to your UI. Below you will find a list of core components:

CloseButton

This component can be used to display a button that closes the UI

Configuration Options

  • string Size
    The size of the button in px or %
  • OnClick(Action<UIEvent> Event)
    Override the default click event
root.Component<CloseButton>(component = > 
{
    component.Size = "30px";
});

By default this component will close the UI, if you wish you can override the OnClick event

root.Component<CloseButton>(component = > 
{
    component.Size = "30px";
    component.OnClick(Event =>
    {
        ShowOverlay = false;
        Event.Window.Refresh("overlay_element"); 
    });
});

You can style the CloseButton component like so:

Theme.Css("ComponentPanel.CloseButton ElementButton", (style) => 
{
    style.SetBackgroundColor(UIColor.Amber500);
});

GridView

This component renders a flex grid.

Configuration Options

  • string GridId
    The ID for this grid
  • bool UseScroll
    true or false if the component should scroll when the content overflows the parent
  • int ItemsPerRow
    How many flex items the grid should render per row
  • string FlexGap
    Distance between the flex items
  • float ItemHeight
    The height of the item container
  • string EmptyGridMessage
    Text to show when the Items contains zero entries
  • List<T> Items
    A list with items of type (T)
  • Action<ElementPanel, Item> ItemAction
    A closure action for each item
root.Component<GridView<T>>((component) =>
{
    component.GridId = "grid_example";
    component.UseScroll = false;
    component.ItemsPerRow = 3;
    component.FlexGap = 10f;
    component.Items = new List<string>(){"1", "2", "3", "4", "5", "6", "7", "8", "9"};
    component.ItemAction = (container, item) =>
    {
        container.Label(label => 
        {
            label.Style.SetText($"Item {item}")
        });
    }
});

You can style the GridView component like so:

Theme.Css("ComponentPanel.GridView .item", (style) => 
{
    style.SetBackgroundColor(UIColor.Amber500);
});

TimerEvery

The TimerEvery component is useful when you want to updates elements with a interval

Configuration Options

  • float Delay
    The timer interval
  • Slot(Action<ElementPanel>) Slot()
    The slot that defines the template that should update every Delay
root.Component<TimerEvery>(component =>
{
    component.Delay = 1f;

    component.Slot(panel =>
    {
        panel.Label(label =>
        {
            if (ZoneManager.IsInPVPZone(label.Window.Player))
            {
                label.Style.SetText("<b>PVP ZONE</b>")
                           .SetFontColor("red");
            }
            else
            {
                label.Style.SetText("<b>PVE ZONE</b>")
                           .SetFontColor("green");
            }                          
        });                                     
    });
});

Creating a Component

Creating your own components is really easy. All a component needs is a public override Action<ComponentPanel> Action() method that RustUI calls to render the template for the component. Lets create very basic component with a label that displays some text that has been set in the ComponentLabelText config option.

public class MyCustomComponent : Component<MyCustomComponent>
{
    public string ComponentLabelText = "Default label text";

    public MyCustomComponent( ComponentPanel panel ) : base(panel)
    {
        // every component requires a constructor            
    }

    public override void OnDestroy(UIWindow window)
    {
        // called when the component gets destroyed           
    }

    public override void OnReady(UIWindow window)
    {
        // called when the component has been initialized
    }

    public override Action<ComponentPanel> Action()
    {
        return (panel) =>
        {
            panel.Label(label => 
            {
                label.Style.SetText(ComponentLabelText);
            });
        };
    }
}

Using the Custom Component

Now that we defined our MyCustomComponent we are ready to use it in the UI

root.Component<MyCustomComponent>(component =>
{
    component.ComponentLabelText = "MyCustomComponent Works!";
});

You can even style the label inside your component

Theme.Css("ComponentPanel.MyCustomComponent ElementLabel", (style) => 
{
    style.SetFontColor(Theme.Success);
});

Chapter Contents