Skip to content

Styling

Rezi provides a comprehensive styling system for terminal UIs, including direct style props, semantic themes, icons, and focus indicators.

Overview

Rezi styling works at two levels:

Direct Styles
Apply colors and text attributes directly to widgets using RGB values and style objects.
Semantic Themes
Use predefined theme tokens for consistent colors across your application.

Beautiful Defaults

Core interactive widgets are recipe-styled by default (buttons, inputs, textareas, selects, checkboxes, progress, callouts). Use intent on buttons for common “primary/danger/link” patterns, and use manual style props to override specific attributes (they do not disable recipes).

Quick Example

import { ui, rgb, darkTheme } from "@rezi-ui/core";
import { createNodeApp } from "@rezi-ui/node";

const app = createNodeApp({
    initialState: {},
});

app.view(() =>
  ui.page({
    p: 1,
    gap: 1,
    header: ui.header({ title: "Styling" }),
    body: ui.column({ gap: 1 }, [
      // Direct RGB styling
      ui.text("Error!", { style: { fg: rgb(255, 100, 100), bold: true } }),

      // Theme-aware styling + composition helpers
      ui.panel("Panel", [
        ui.text("Content here"),
        ui.actions([ui.button({ id: "ok", label: "OK", intent: "primary" })]),
      ]),
    ]),
  })
);

// Apply a built-in theme
app.setTheme(darkTheme);

await app.start();

Style Properties

Every widget that displays text supports a style prop:

type TextStyle = Readonly<{
  fg?: Rgb24;            // Foreground (text) color
  bg?: Rgb24;            // Background color
  bold?: boolean;        // Bold text
  dim?: boolean;         // Dim/faint text
  italic?: boolean;      // Italic text
  underline?: boolean;   // Underlined text
  inverse?: boolean;     // Swap fg/bg colors
  strikethrough?: boolean; // Strikethrough text
  overline?: boolean;    // Overline text
  blink?: boolean;       // Blinking text
  underlineStyle?: "none" | "straight" | "double" | "curly" | "dotted" | "dashed";
  underlineColor?: Rgb24 | ThemeColor;
}>;

RGB Colors

Create colors with the rgb() helper:

import { rgb } from "@rezi-ui/core";

const red = rgb(255, 0, 0);
const green = rgb(0, 255, 0);
const customBlue = rgb(100, 150, 255);

ui.text("Colored text", { style: { fg: red, bg: customBlue } });

Text Attributes

ui.text("Bold text", { style: { bold: true } });
ui.text("Italic text", { style: { italic: true } });
ui.text("Underlined", { style: { underline: true } });
ui.text("Curly underline", {
  style: { underlineStyle: "curly", underlineColor: rgb(255, 107, 107) },
});
ui.text("Dim text", { style: { dim: true } });
ui.text("Struck through", { style: { strikethrough: true } });
ui.text("Overlined", { style: { overline: true } });
ui.text("Blinking", { style: { blink: true } });
ui.text("Inverted", { style: { inverse: true } });

Graphics Styling

Graphics widgets use color strings and rendering protocol options in addition to TextStyle.

Widget Styling knobs
link style, focus state, theme primary/underline defaults
canvas draw colors (#rrggbb or theme tokens), blitter quality
image fit, protocol, zLayer, imageId caching
lineChart / sparkline / barChart series colors, blitter, optional highRes rendering

Use lower-resolution blitters (quadrant, halfblock) for speed; use braille for maximum detail.

Built-in Themes

Rezi includes six built-in themes:

Theme Description
darkTheme Ayu-inspired dark theme with orange accents
lightTheme Clean light theme with blue accents
dimmedTheme Reduced contrast dark theme
highContrastTheme WCAG AAA compliant theme
nordTheme Nord color palette
draculaTheme Dracula color palette

Applying Themes

import { darkTheme, lightTheme, nordTheme } from "@rezi-ui/core";

// Set theme at startup
const app = createNodeApp({
    initialState: {},
  theme: darkTheme,
});

// Or switch themes at runtime
app.setTheme(nordTheme);

Semantic Color Tokens

Themes use semantic color tokens for consistent styling:

Surface Colors (bg.*)

  • bg.base - Main background
  • bg.elevated - Raised surfaces (cards, modals)
  • bg.overlay - Overlay surfaces (dropdowns, tooltips)
  • bg.subtle - Subtle backgrounds (hover states)

Foreground Colors (fg.*)

  • fg.primary - Primary text
  • fg.secondary - Secondary/less important text
  • fg.muted - Muted text (disabled, placeholders)
  • fg.inverse - Text on accent backgrounds

Accent Colors (accent.*)

  • accent.primary - Primary accent (actions, focus)
  • accent.secondary - Secondary accent (links, highlights)
  • accent.tertiary - Subtle accents

Semantic Colors

  • success - Success states
  • warning - Warning states
  • error - Error states
  • info - Informational states

Diagnostic Colors (diagnostic.*)

  • diagnostic.error - Diagnostic error underline/color
  • diagnostic.warning - Diagnostic warning underline/color
  • diagnostic.info - Diagnostic info underline/color
  • diagnostic.hint - Diagnostic hint underline/color

State Colors

  • focus.ring - Focus ring color
  • focus.bg - Focus background
  • selected.bg - Selected item background
  • selected.fg - Selected item foreground
  • disabled.fg - Disabled foreground
  • disabled.bg - Disabled background

Border Colors (border.*)

  • border.subtle - Subtle borders (dividers)
  • border.default - Default borders
  • border.strong - Emphasized borders

Border Styles

Box widgets support various border styles:

ui.box({ border: "single" }, [...])   // Single line (default)
ui.box({ border: "double" }, [...])   // Double line
ui.box({ border: "rounded" }, [...])  // Rounded corners
ui.box({ border: "heavy" }, [...])    // Heavy/thick line
ui.box({ border: "dashed" }, [...])   // Dashed line
ui.box({ border: "heavy-dashed" }, [...]) // Heavy dashed line
ui.box({ border: "none" }, [...])     // No border

Shadow Effects

Add depth with box shadows:

// Simple shadow
ui.box({ shadow: true }, [...])

// Custom shadow
ui.box({
  shadow: {
    offsetX: 2,
    offsetY: 1,
    density: "dense"  // "light" | "medium" | "dense"
  }
}, [...])

Spacing

Use the spacing scale for consistent layouts:

Key Value Use Case
"xs" 1 Tight spacing
"sm" 1 Compact elements
"md" 2 Default spacing
"lg" 3 Sections
"xl" 4 Major sections
"2xl" 6 Page margins
ui.box({ p: "md", border: "rounded" }, [
  ui.column({ gap: "sm" }, [...]),
])
ui.column({ py: "lg", px: "xl" }, [...])

Learn More