Files
owlen/docs/tui-ux-playbook.md

8.6 KiB
Raw Blame History

Owlen TUI UX & Keybinding Playbook

Last updated: October 25, 2025

This playbook documents the design principles, modal ergonomics, command metadata, theming tokens, and animation policy that guide Owlens terminal UI. Use it both as a contributor reference and as a migration guide when extending custom keymaps or UI affordances.


1. Modal Philosophy

Owlen embraces a Vim-inspired modal workflow with discoverability helpers layered on top.

Mode Entry Primary Purpose Escape
Normal Esc, Ctrl+[, application start Navigation, pane switching, command prefixes, leader chords i, :, ?, F1
Editing i, a, Enter in Normal Compose prompt, multi-line editing, history cycling (Ctrl+↑/↓) Esc
Visual v in Normal Region selection across chat, thinking, and input panes Esc, v
Command : Run palette commands (:session save, :mode code, :limits) Esc, Enter
Help F1, ? Cheat sheet tabs, onboarding tour Esc, F1
Browsers :sessions, :themes, repo search keys Context-specific pickers with shared navigation primitives Esc

Modal transitions fire AppEvent::Composer::ModeChanged, enabling keymap state to reset cleanly (see ChatApp::set_input_mode). Maintain this flow when adding new modes to avoid orphaned key sequences.

Focus Shortcuts

  • Ctrl+1…5 focus Files, Chat, Code, Thinking, Input (mirrors leader chords).
  • Tab / Shift+Tab cycle panes; g t toggles Files visibility in Vim keymap.
  • Ctrl+Alt+5 (Vim) / Alt+5 (Emacs) jump back to the input editor.

Keep focus hops single-chord and mnemonic. Prefer documenting any new shortcut in the cheat sheet (render_guidance_cheatsheet) and the status HUD hints.


2. Keybinding Design & Migration

Built-in Profiles

Switch at runtime via :keymap vim|emacs; persist with ui.keymap_profile = "vim" or "emacs" in config.toml.

Custom Keymaps

Set ui.keymap_path = "/absolute/path/to/keymap.toml" to override the built-in profiles. The schema matches the shipped TOML files:

[[bindings]]
mode = "normal"
sequence = ["g", "t"]
command = "workspace.toggle_files"

Migration notes (v0.2+)

  1. Multi-step sequences: All keymaps now support arbitrary-length sequences (Ctrl+W, w, Ctrl+K, ). Update custom maps to the trie syntax if you previously shadowed hard-coded Rust handlers.
  2. Leader remapping: ui.keymap_leader defaults to space. Custom profiles should mirror the new leader sections so the cheat sheet can surface alternate hints (binding_pair_string).
  3. Discoverability hooks: Register new commands in commands::catalog() with category, summary, tags, and optional preview callback. The command palette relies on this metadata for fuzzy search and tag filtering.
  4. Help overlay: If you introduce new focus or layout commands, add them to build_cheatsheet_sections so onboarding and help stay in sync.

Run cargo test -p owlen-tui --test chat_snapshots after keymap changes to refresh guidance snapshots.


3. Command Metadata Schema

Located in crates/owlen-tui/src/commands/catalog.rs, each command descriptor should populate:

  • category: High-level grouping shown in the palette (navigation, session, provider).
  • keywords: Fuzzy aliases; include verbs (open, focus), nouns (chat, files), and tags (#agent).
  • key_hint: Optional string rendered in previews (e.g., Ctrl+Shift+F).
  • modes: Restrict availability by InputMode when needed (e.g., editing-only commands).
  • preview: Use for sidecar previews (commands::Preview), returning lines that explain impact.

When adding new commands:

  1. Define the handler in commands::handlers.
  2. Register metadata in catalog() and supply tests in crates/owlen-tui/tests/state_tests.rs or palette-specific snapshots.
  3. Update the cheat sheet if the command introduces a new focus or mode affordance.

4. Theming & Layer Tokens

Themes live in owlen_core::theme. The TUI applies a glass/neon layer via GlassPalette::for_theme_with_mode using config.ui.layers:

Setting Default Description
shadow_elevation 2 Depth of drop shadow around the chat stage.
glass_tint 0.82 Opacity mix between base theme background and frosted layer.
neon_intensity 60 Percentage controlling accent saturation.
focus_ring true Draws neon outlines around the active stage container.

Best practices

  • Keep contrasts AA+; avoid low-alpha custom tints when accessibility_high_contrast = true.
  • Re-render custom palettes through the snapshot suite to catch regression diffs.

5. Animation Policy

Controlled by config.ui.animations:

Field Effect Range
micro Enables pane glow, gauge easing, mode flash. true/false
gauge_smoothing Exponential smoothing factor for usage gauges. 0.051.0
pane_decay Decay applied to pulse effects on pane switches. 0.20.95

Accessibility flags (ui.accessibility.high_contrast, ui.accessibility.reduced_chrome) automatically disable micro animations. When adding new animations:

  1. Guard with ChatApp::micro_animations_enabled().
  2. Provide non-animated fallbacks (e.g., direct gauge snap).
  3. Update documentation and consider adding snapshot coverage under both animated and non-animated configurations.

6. Status Surface & Toasts

The status HUD (render_status) now renders three columns:

  1. Left: Mode/operating badges, focus hints, agent state, help shortcuts.
  2. Center: Primary status message with auto-leveled badge (info/success/warning/error) and contextual usage gauges.
  3. Right: Repository/path summary, provider & model badge, streaming hints, and toast history.

Toast enhancements:

  • Icons per severity (, , , ).
  • Optional keyboard hints via push_toast_with_hint.
  • Progress bar countdown plus remaining seconds.
  • Persistent history (20 entries) exposed to the HUD for quick recall.

Guidelines

  • Provide actionable hints (e.g., "F12 · Debug log", ":limits").
  • Reserve ToastLevel::Error for recoverable issues the user must address.
  • Use status primary line for the most recent action; employ system_status for secondary context.

7. Contributor Checklist

When modifying TUI UX or keybindings:

  1. Update this playbook if the change affects modal ergonomics, theming tokens, animation policy, or keymap conventions.
  2. Extend the cheat sheet / onboarding overlays for new focus or command shortcuts.
  3. Refresh snapshots: INSTA_UPDATE=always cargo test -p owlen-tui --test chat_snapshots.
  4. Run cargo clippy -p owlen-tui -- -D warnings and the owlen-tui test suite.
  5. Document user-facing changes in CHANGELOG.md.

Keeping these steps in sync ensures Owlens keyboard-first UX remains predictable, accessible, and discoverable.

8. Screenshot Pipeline

Use the scripted pipeline to regenerate gallery assets and documentation illustrations:

  • cargo xtask screenshots emits ANSI dumps under images/generated and, by default, converts them to PNG with chafa. Pass --no-png to skip PNG rendering or --chafa /path/to/chafa to override the binary. Each scene is deterministic—no network calls—and mirrors the regression snapshots.
  • The pipeline reuses the same stub provider harness as the snapshot tests, so new scenes should be added in tandem with chat_snapshots.rs to keep visual regression coverage and documentation imagery aligned.