ui: remove on-screen BASE button from keypad grid

- BASE is now Tab-only (still fully functional, with clear hint: 'Tab:BASE').
- Deleted the special baseRow / fullRowWidth centering logic and the single-button bottom row.
- The keypad grid is now a clean, regular 4-row block of keys.
- This eliminates the persistent bottom-border alignment bug on the BASE key (chopped + shifted).
- Updated Tab handler to use the 'base' flash on the display label instead of trying to highlight a non-existent button.
- Cleaned up unused baseKey style and related comments.
- Updated docs/UI_DESIGN.md to document that BASE is keyboard-only via Tab.

As the user noted: with a good hint, the visual key was unnecessary and was causing layout friction. The keypad now looks much more balanced.
This commit is contained in:
Grok 2026-06-06 15:05:53 +01:00
parent 67d93acbaf
commit 7d6c4937f8
2 changed files with 7 additions and 21 deletions

View File

@ -50,7 +50,7 @@ Layout sketch (subject to refinement; 4-5 columns):
BASE
```
BASE is prominent because it is the distinctive "programmer display" feature.
The BASE action (cycle display format) is available via the `Tab` key (documented in the hint row). There is no on-screen BASE button in the keypad grid. This keeps the button layout regular and avoids awkward single-button rows, while still making the feature easily discoverable via the persistent hint.
All important actions have direct keys (digits, operators, =/Enter, Backspace, Tab for BASE, c/C, etc.). The on-screen buttons are primarily visual + mouse targets.

View File

@ -80,8 +80,9 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return a, tick(600*time.Millisecond, "cerr")
}
a.flash = "base"
a.pressedKey = "BASE"
return a, tick(140*time.Millisecond, "key")
// BASE is Tab-only now (no visual button in the grid).
// The "base" flash will highlight the base label in the display row.
return a, tick(140*time.Millisecond, "base")
case "c", "C":
a.engine.ClearEntry()
@ -224,7 +225,6 @@ func (a *App) View() string {
opKey := keyStyle.Copy().Foreground(lipgloss.Color("63")).Background(lipgloss.Color("235"))
clearKey := keyStyle.Copy().Foreground(lipgloss.Color("203")).Background(lipgloss.Color("52"))
modKey := keyStyle.Copy().Foreground(lipgloss.Color("214")) // orange-ish for MOD
baseKey := keyStyle.Copy().BorderForeground(lipgloss.Color("63")).Bold(true)
makeKey := func(label string) string {
var st lipgloss.Style
@ -235,8 +235,6 @@ func (a *App) View() string {
st = clearKey
case "MOD":
st = modKey
case "BASE":
st = baseKey
case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".":
st = numKey
case "+/-":
@ -256,23 +254,11 @@ func (a *App) View() string {
row3 := lipgloss.JoinHorizontal(lipgloss.Top, makeKey("1"), spacer, makeKey("2"), spacer, makeKey("3"), spacer, makeKey("-"), spacer, makeKey("AC"))
row4 := lipgloss.JoinHorizontal(lipgloss.Top, makeKey("0"), spacer, makeKey("."), spacer, makeKey("+/-"), spacer, makeKey("+"), spacer, makeKey("="))
// Make the BASE row the same width as the other rows.
// This ensures the BASE button is nicely centered on its own row
// when the whole grid is centered under the display.
fullRowWidth := lipgloss.Width(row1)
baseOnly := makeKey("BASE")
baseRow := lipgloss.NewStyle().
Width(fullRowWidth).
Align(lipgloss.Center).
Render(baseOnly)
// Compact grid of keys — every row has identical width so the BASE
// button sits nicely centered on its row.
rawGrid := lipgloss.JoinVertical(lipgloss.Left, row1, row2, row3, row4, baseRow)
// Compact 4-row keypad grid (BASE action is Tab-only; see hint).
rawGrid := lipgloss.JoinVertical(lipgloss.Left, row1, row2, row3, row4)
// Center the key grid directly under the display.
// No enclosing container or background panel — just the individually
// styled keys (each with their own border + color).
// No enclosing container — just the individually styled keys.
keypad := lipgloss.NewStyle().
Width(dispW).
Align(lipgloss.Center).