CELLIUM 006 - CSS Support

Summary:

Cellium has introduced basic CSS support, allowing developers to separate the visual styling of widgets from their structural definition. This currently includes ID and class selectors, as well as state-based styling for focused elements.

Introduction

One of the challenges in building Terminal User Interfaces (TUIs) is managing the visual properties of widgets without cluttering the layout logic. By adopting a subset of CSS, Cellium allows for a more declarative approach to styling.

While not 'perfect', the concepts of CSS styling widgets should allow for developers to be able to theme their work with familiar concepts.

Current State of CSS Support

The current implementation in css.erl provides several key features:

Selectors

Cellium supports two primary selectors:

  • ID Selectors: Target specific widgets using #widget_id.
  • Class Selectors: Target groups of widgets using .class_name.

State-based Styling

The :focused pseudo-class is supported, enabling different styles when a widget has input focus. For example:

.button:focused {
    color: black;
    background-color: cyan;
}

Stylesheet Loading

Stylesheets can be loaded from external files using css:load_stylesheet/1, or the default styles can be applied via css:style/1.

Property Parsing

The parser currently handles:

  • Integers (for colors and sizes)
  • Booleans (true, false)
  • Atoms (for general property values like colors or alignment)
  • Note: at the moment it only allows for a single stylesheet, but I feel like it should allow for multiple style sheets.

Examples of Working CSS

Here are some examples of CSS rules that currently work in Cellium:

Basic Widget Styling

You can set colors and background colors using either standard color names (as atoms) or integer values if your terminal supports them.

.box {
    color: white;
    background-color: blue;
}

#sidebar {
    background-color: black;
    color: 7;
}

Layout Control

The expand property is used by containers to determine if a widget should take up all available space.

.main-content {
    expand: true;
}

.fixed-sidebar {
    expand: false;
    width: 20;
}

Focus and Interactivity

You can define which widgets are focusable and how they look when they gain focus.

.input-field {
    focusable: true;
    background-color: black;
    color: white;
}

.input-field:focused {
    background-color: white;
    color: black;
}

.button {
    focusable: true;
    color: cyan;
}

.button:focused {
    color: black;
    background-color: cyan;
}

Specialized Widget Properties

Some properties are specific to certain widget types, like title alignment for frames or debug borders for containers.

.bordered-frame {
    title_align: center;
}

.debug-container {
    debug: true;
}

Technical Implementation

When styling is applied, Cellium walks the layout tree and merges properties from the stylesheet into the widget maps. It prioritizes ID styles over class styles and focused styles over normal styles.

Crucially, the styling engine respects calculated layout properties like x, y, width, and height, ensuring that visual updates don't accidentally break the layout positioning. As a developer you probably dont want to be messing with that in the css anyway.

Conclusion

While the current CSS support is a subset of the full specification, it provides a solid foundation for building themed and interactive terminal applications in Erlang.

Resources: