feat(tui): migrate from Ink to OpenTUI/Solid.js with theming, mouse support, and performance improvements
Merged
JU
7mo ago+4467+4467+0123456789012345678901234567890123456789-1386-1386-0123456789012345678901234567890123456789
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
tsxtobun(required for OpenTUI's native modules) - Added custom type declarations for OpenTUI (
opentui.d.ts) - Added
bunfig.tomlfor 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
createMemofor 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
fginstead ofbackgroundColor) - Fixed
currentStreakcalculation to count backwards from today - Fixed
--help/--versionrouting (global flags now work correctly) - Fixed
selectedIndexunbounded 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
inkdependency, added@opentui/solid,solid-js
Files Changed (29 files)
packages/cli/package.json- Updated dependenciespackages/cli/bunfig.toml- NEW: Bun config for Solid.jspackages/cli/src/cli.ts- Updated CLI entry with TUI as default modepackages/cli/src/tui/*.tsx- All components migrated to Solid.jspackages/cli/src/tui/config/themes.ts- NEW: 9 color palettespackages/cli/src/tui/config/settings.ts- NEW: Theme persistencepackages/cli/src/tui/types/index.ts- NEW: Consolidated typespackages/cli/src/tui/utils/format.ts- NEW: Format utilitiespackages/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
-
--helpand--versionflags work correctly