avelino/roam-tui

Light theme support

Open

#14 opened on Feb 25, 2026

View on GitHub
 (0 comments) (0 reactions) (0 assignees)Rust (0 forks)github user discovery
area: configarea: renderinghelp wantedpriority: lowroam parity

Repository metrics

Stars
 (21 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

Summary

Implement a light theme as an alternative to the current dark-only color scheme. The config already accepts theme = "light" but all colors are hardcoded for dark backgrounds.

Roam web behavior: Roam web is light-themed by default. Custom CSS themes (via [[roam/css]] page) can make it dark.

TUI adaptation: Ship two built-in themes: dark (current default) and light. Extracting colors into a theme struct ensures all UI components use consistent theming. No custom CSS equivalent needed — just the two presets.

Implementation hints

Current color locations (all hardcoded)

These files have hardcoded Color::* values that need to be replaced with theme references:

  • src/markdown.rs:45-192 — inline formatting colors: bold (White), italic, strikethrough (DarkGray), highlight (Yellow bg), code (Green on DarkGray), links (Cyan), tags (Cyan), TODO (Red), DONE (Green), embeds (Magenta)
  • src/ui/main_area.rs:124-420 — block rendering: selection highlight, day headings, separators, code block labels/lines, blockquotes, collapsed indicators, bullet colors
  • src/ui/header.rs:17-35 — header bar colors
  • src/ui/status_bar.rs:18-47 — status bar, hints, mode indicator colors
  • src/highlight.rs:23-35 — syntax highlighting: keyword (Blue), string (Green), comment (DarkGray), function (Yellow), type (Cyan), number (Magenta)

Theme struct

Create a new file src/theme.rs:

pub struct Theme {
    pub bg: Color,
    pub fg: Color,
    pub selection_bg: Color,
    pub selection_fg: Color,
    pub heading: Color,
    pub link: Color,
    pub tag: Color,
    pub code_fg: Color,
    pub code_bg: Color,
    pub todo: Color,
    pub done: Color,
    pub embed: Color,
    pub highlight_bg: Color,
    pub strikethrough: Color,
    pub comment: Color,
    pub keyword: Color,
    pub string: Color,
    pub function: Color,
    pub type_color: Color,
    pub number: Color,
    pub separator: Color,
    pub hint_key: Color,
    pub hint_desc: Color,
    pub status_bg: Color,
    pub header_bg: Color,
    // ... etc
}

Configuration

  • src/config.rs:31pub theme: String already exists (default: "dark")
  • Load theme based on config value
  • Theme::dark() and Theme::light() constructors

Passing theme through

  • Option A: Store Theme in AppState, pass to all render functions
  • Option B: Use a once_cell/LazyLock global (simpler but less testable)
  • Option A is preferred — pass &Theme alongside &AppState to render functions

Light theme color choices

For good contrast on light backgrounds:

  • Text: Color::Black or Color::Rgb(30, 30, 30)
  • Links: Color::Blue (not Cyan — poor contrast on white)
  • Code bg: Color::Rgb(240, 240, 240)
  • Selection: Color::Rgb(200, 220, 255) bg
  • Syntax: adjust all colors for light background contrast

Acceptance criteria

  • theme = "light" in config activates light color scheme
  • All UI components respect the active theme
  • No hardcoded colors remain in rendering code
  • Both themes have good contrast and readability
  • Existing dark theme looks identical after refactor

Contributor guide