gralculator/internal/ui/ui.go

68 lines
1.7 KiB
Go
Raw Normal View History

package ui
import (
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/gmgauthier/gralculator/internal/calc"
)
// App is the root Bubble Tea model for the gralculator TUI.
// Phase 1/3 skeleton only — real implementation in phase 3.
type App struct {
engine *calc.Engine
width int
height int
// flash state etc. will be added during spike (see gostations patterns)
}
func NewApp() *App {
return &App{
engine: calc.NewEngine(),
}
}
func (a *App) Init() tea.Cmd {
return nil
}
func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
a.width = msg.Width
a.height = msg.Height
case tea.KeyMsg:
switch msg.String() {
case "q", "ctrl+c", "esc":
return a, tea.Quit
case "tab":
// Will drive engine.CycleBase() + possible CERR flash
_ = a.engine.CycleBase()
// TODO (phase 3): trigger flash on error, re-render small row
}
}
return a, nil
}
func (a *App) View() string {
// Placeholder view. Real two-row display + keypad grid in phase 3.
// Will use lipgloss heavily for:
// - large number area (tall + styled)
// - small current-base row (highlighted label)
// - centered content card (lipgloss.Place)
// - button cells for keypad (including single "BASE")
// - flash styles (140ms color 63)
// - minimal hint row
base := a.engine.CurrentBase()
return lipgloss.NewStyle().Padding(1, 2).Render(
"gralculator skeleton\n\n" +
"Large number area (TODO)\n" +
"Current base: " + string(base) + " (press Tab to cycle)\n\n" +
"See docs/UI_DESIGN.md and spec.md",
)
}
// TODO (phase 3): full model with flashes, proper display rendering,
// keypad grid, Tab + other key handling wired to engine, resize/centering.