Skip to content

Theming

Klix uses a small semantic theme surface so applications can stay readable without coupling themselves to a specific renderer implementation.

This guide explains how to define a theme, how widgets consume it, and where the boundaries are. For the renderer layer, see Renderer.

ThemeConfig

The theme model is ThemeConfig.

Current fields are:

  • accent
  • background
  • text
  • input_background
  • input_text_color
  • muted
  • info
  • border
  • cursor
  • success
  • warning
  • error

You can pass a theme when creating the app:

python
app = klix.App(
    name="DocsTool",
    version="0.1.0",
    description="Theme example",
    state_schema=DocsState,
    theme=klix.ThemeConfig(
        accent="#6EA8FE",
        text="#F7F9FC",
        muted="#7C8698",
        info="#8AB4F8",
        border="#2D3B55",
        success="#7BD88F",
        warning="#F6C177",
        error="#FF7B72",
        input_background="#171B24",
        input_text_color="#F7F9FC",
    ),
)

input_background is optional. If you leave it unset, Klix keeps the default prompt styling.

Why Semantic Colors Matter

A command should say:

python
session.ui.print("Saved successfully.", color="success")

not:

python
session.ui.print("Saved successfully.", color="#22c55e")

Why:

  • renderers can translate semantic names however they need to
  • theme changes stay centralized
  • fallback renderers degrade more cleanly

Use Theme Keys Across Output

Panels:

python
session.ui.output.panel(
    "Deployment finished.",
    title="Status",
    border_color="success",
    title_color="accent",
)

Tables:

python
session.ui.output.table(
    headers=["Step", "State"],
    rows=[["build", "done"], ["deploy", "running"]],
    header_color="accent",
    border_color="border",
)

Layout:

python
session.ui.layout.header.set("OpsTool", color="accent")
session.ui.layout.status.set("ready", "prod", color="muted")

Input bar:

python
app = klix.App(
    name="OpsTool",
    theme=klix.ThemeConfig(
        input_background="#171B24",
        input_text_color="#F7F9FC",
    ),
)

In capable terminals, Klix applies that background to the active input area through prompt_toolkit styling while keeping cursor and selection behavior intact.

Mock Theme Switching

The chat example in the repository shows the usual pattern: mutate the live renderer theme and redraw.

python
def set_theme(session: klix.Session) -> None:
    theme = session.ui.renderer.theme
    theme.accent = "#2B6CB0"
    theme.text = "#1F2937"
    theme.muted = "#6B7280"

Then redraw any layout regions or output that should reflect the change.

This is intentionally simple. Klix does not implement a more elaborate theme manager.

What Fallback Renderers Do

The rich renderer uses colors and rich widgets when possible. The fallback and CI renderers reduce that formatting to plain text output.

That means a theme should improve the experience in capable terminals, but your app should still read well without heavy styling.

Common Mistakes

  • Passing arbitrary color names that are not in the theme config. Some widgets resolve unknown colors directly, but semantic keys are the safer path.
  • Building meaning into raw color values instead of labels and copy.
  • Expecting a theme update to automatically repaint all previous output. Existing printed lines stay as they were; redraw affects layout and future output.
  • Assuming input_background affects fallback or CI prompts the same way. Rich prompt styling is only available in interactive prompt_toolkit mode.

Released under the MIT License.