diff --git a/src/ui/routes/MonthRoute.tsx b/src/ui/routes/MonthRoute.tsx index 7c9fd4c..9d04644 100644 --- a/src/ui/routes/MonthRoute.tsx +++ b/src/ui/routes/MonthRoute.tsx @@ -3,6 +3,7 @@ import { Link, useParams } from "react-router"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; +import { NativeSelect } from "@/components/ui/native-select"; import { useDataset } from "../hooks/useDataset.ts"; import { useMutate } from "../hooks/useMutate.ts"; import { monthView, type MonthViewModel } from "../../domain/views.ts"; @@ -42,9 +43,9 @@ export function MonthRoute() { className="flex items-center justify-between gap-3 rounded-lg border border-destructive/40 bg-destructive/5 p-3 text-sm" > Could not save: {error} - + )} @@ -190,41 +191,63 @@ function PurchaseRow({ }) { const slice = sliceAmountForMonth(purchase, monthId)!; return ( -
  • - + // `-mx-2 px-2` rather than `px-1`: the row's text now starts exactly where + // its own date heading does — `px-1` indented it 4px past the heading — + // and the hover wash bleeds 8px outward, so the highlight has an inset + // instead of stopping flush against the first character. + // + // One line from `sm:` up, two below it. At 390px this row's fixed parts — + // a mono amount, "edit", "delete" — take about 215px of a 350px card, + // which left the description roughly 110px: it truncated to "Weeken…", + // then "Bik…", and on the financed row to nothing but its badge. The + // description is the only part that says what the purchase WAS, so at that + // width it gets a line to itself and everything else gets the next one. + // The same call PostTable already makes, for the same reason. +
  • + {purchase.description} {purchase.note && ( {purchase.note} )} - {purchase.schedule && ( - - financed + + {/* `sm:contents` dissolves this wrapper from `sm:` up, so the desktop row + is exactly the flat flex line it has always been. Below `sm:` it is + the second line, and its `w-full` is what forces the wrap. */} + + {purchase.schedule && ( + + financed + + )} + + {formatMoney(slice.amount, slice.currency)} + + + {/* From `sm:` up: revealed on hover, and held at a fixed width so + revealing it cannot shift the amounts, which are the column being + read down. Below `sm:`: always visible. A phone has no hover, so + `opacity-0` had made these two the hardest controls in the app to + reach, while still reserving 120px of the row to hide them in. */} + + + edit + + } + /> + - )} - - {formatMoney(slice.amount, slice.currency)} - - {/* Held at a fixed width so revealing the actions on hover cannot shift - the amounts, which are the column being read down. */} - - - edit - - } - /> -
  • ); @@ -260,7 +283,7 @@ function MonthStep({ to, label, back = false }: { to: string; label: string; bac return ( {back ? `\u2190 ${label}` : `${label} \u2192`} @@ -307,12 +330,12 @@ function RuleFromMonth({ } return ( -
    +
    {post.name}: allocate from {monthId} onward - +