Commit Graph
5 Commits
Author SHA1 Message Date
Lucas WintherandClaude Opus 5 85ba899059 fix(dialog): let the dialog's own padding decide its layout
DialogContent is a grid whose single implicit column is `auto`, so it sized
to the widest child's min-content — and one row of the split editor (a
select, an amount, a unit, a radio and a remove button) has a min-content
width of 480px against the 464px the padding leaves.

The column grew past the padding box and every stretched child grew with it,
so measured, every field in the purchase dialog sat 6.6px from the right
edge and 25px from the left. One crowded row was setting the padding for the
whole dialog.

`grid-cols-[minmax(0,1fr)]` lets the column shrink to the space actually
available, which puts the element's own `p-6` back in charge.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-02 22:58:33 +02:00
Lucas WintherandClaude Opus 5 394c5f74df feat(ui): add a shared native select and a segmented control
Two patterns the app had been rebuilding per call site.

NativeSelect: eight `<select>` elements had each been hand-styled, arriving
at four different answers — `h-8 rounded border px-1 text-xs`, `h-9 rounded
border px-2 text-sm`, `h-9 flex-1 rounded ...`, and one correct `h-9
rounded-md border-input px-2`. Measured, that is two radii (4px against the
system's 6px), two border colours (the row hairline against the 3:1 field
border) and three text indents against Input's 12px. In the purchase dialog
a select sat directly beside the Total input in a visibly different control
language.

It stays a native select on purpose: the platform picker on a phone and
type-to-select on a keyboard are worth more here than a prettier menu, and
entry speed is a stated product principle. The chevron is a background image
from a new `--budget-select-chevron` token rather than a positioned icon,
because that needs no wrapper element — so `className` lands on the select
itself and every call site's existing `w-full`, `flex-1`, `h-8` and `w-40`
keeps behaving as it did. The token is declared per theme since a
background-image stroke cannot be `currentColor`.

Segmented: four screens had built the same view switch from two loose
buttons, the selected one filled and the other outlined, separated by a gap.
That reads as one primary action beside one unrelated button rather than as
two states of a single control. One track, no gap, `aria-pressed` per
segment.

Neither is wired up yet; the call sites follow.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-02 22:58:20 +02:00
Lucas WintherandClaude Opus 5 f85b967a9d fix(ui): draw one focus ring, not two
src/index.css already declared "one visible, consistent focus treatment",
but shadcn's primitives ship a `focus-visible:ring-[3px]` of their own, so
every button and input actually drew two: a soft translucent halo hugging
the border, then a hard 2px outline 2px further out.

The global rule is the one that stays, because it also covers the links and
bare table buttons that never go through a primitive. The rings come out of
button.tsx and input.tsx instead.

Its `border-radius: 2px` goes too. That was squaring the corners of every
control with no radius utility of its own — the rule-history triggers in
Settings measured `rad=0`, so a focused one drew a sharp rectangle. The
outline now follows each element's own radius.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-02 22:57:59 +02:00
Lucas WintherandClaude Opus 5 dd612565cb feat(ui): add month view with income entry and post table
Negative remaining balances are shown in a warning treatment; nothing
blocks going over budget.

Applies the Tasks 18-23 design contract: --paper/--ink/--rule/--accent/
--surplus/--overspend tokens and the three type-role font variables in
src/index.css, --font-money on every money figure, and the carry meter
(a 3px hard-stopped gradient beneath each PostTable row) encoding
carried-in surplus, allocation track, spend fill and overrun.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-01 20:35:35 +02:00
Lucas Winther 26752aa225 chore: scaffold Bun + React + shadcn project
bun init --react=shadcn, with the demo API routes removed since this app
has no backend. Adds project invariants to CLAUDE.md and a smoke test
proving the domain layer imports with no DOM.
2026-09-01 16:18:55 +02:00