feat(tui): migrate from Ink to OpenTUI/Solid.js with theming, mouse support, and performance improvements

Merged
JU
7mo ago
+4467-1386

Summary

This PR completely rewrites the TUI framework to eliminate rendering flicker/blink issues caused by Ink's reconciler. The migration path was Ink → OpenTUI/React → OpenTUI/Solid.js.

Why OpenTUI?

Ink has known blinking issues during re-renders (#513, #809, #359, #450). OpenTUI from SST uses a native Zig rendering engine that only updates changed cells, eliminating flicker entirely.

Changes

Framework Migration

  • Replaced Ink with @opentui/solid (Solid.js renderer)
  • Switched runtime from tsx to bun (required for OpenTUI's native modules)
  • Added custom type declarations for OpenTUI (opentui.d.ts)
  • Added bunfig.toml for Solid.js JSX preload

New Features

  • Theming: 9 color palettes for contribution graphs (green, halloween, teal, blue, pink, purple, orange, monochrome, YlGnBu)
  • Mouse Support: Click handlers for tabs, source filters, sort buttons, theme toggle, refresh
  • Keyboard Navigation: Arrow keys (←/→) for tab navigation
  • Per-model Colors: Consistent color coding across all views
  • Animated Loading Spinner: Knight Rider style 8-character sweep animation
  • Improved Footer: Full token breakdown (Input/Output/Cache Read/Cache Write/Cost)
  • Settings Persistence: Theme saves to ~/.config/token-tracker/tui-settings.json

Performance Optimizations

  • Pre-compiled regex patterns with Map cache for model colors
  • createMemo for sorted entries in ModelView and DailyView
  • Cache for repeated strings in BarChart (with 256 entry limit)
  • Pre-computed contribution grid in useData.ts
  • Replaced Math.max(...arr.map()) with for loops
  • Module-level constants for TABS and PALETTE_NAMES

Bug Fixes

  • Fixed contribution graph colors (use fg instead of backgroundColor)
  • Fixed currentStreak calculation to count backwards from today
  • Fixed --help/--version routing (global flags now work correctly)
  • Fixed selectedIndex unbounded increment in down arrow handler
  • Prevent disabling all sources (require at least 1 enabled)
  • Added error handling to export feature

Architecture Improvements

  • Centralized format utilities (utils/format.ts)
  • Consolidated type definitions (types/index.ts)
  • Barrel exports for components (components/index.ts)

Breaking Changes

  • Runtime: TUI now requires Bun runtime for development (bun run dev:tui)
  • Dependency: Removed ink dependency, added @opentui/solid, solid-js

Files Changed (29 files)

  • packages/cli/package.json - Updated dependencies
  • packages/cli/bunfig.toml - NEW: Bun config for Solid.js
  • packages/cli/src/cli.ts - Updated CLI entry with TUI as default mode
  • packages/cli/src/tui/*.tsx - All components migrated to Solid.js
  • packages/cli/src/tui/config/themes.ts - NEW: 9 color palettes
  • packages/cli/src/tui/config/settings.ts - NEW: Theme persistence
  • packages/cli/src/tui/types/index.ts - NEW: Consolidated types
  • packages/cli/src/tui/utils/format.ts - NEW: Format utilities
  • packages/cli/src/tui/opentui.d.ts - NEW: Type declarations

Verification Checklist

  • TUI launches without errors: bun packages/cli/src/cli.ts
  • Tab switching works (1-4 keys and ←/→ arrows)
  • Theme cycling with 'p' key
  • Mouse clicks work on interactive elements
  • No blinking/flickering during updates
  • --help and --version flags work correctly