fix(ui): SimpleFIN transaction table fixed column sizing (batch 0.33.7.3)
- Table now uses table-fixed + colgroup for fixed column widths - Long transaction text can no longer push action buttons off-screen - Action buttons are compact icon-only with aria-label/title - Long matched bill names are truncated with truncate class - Bump v0.33.7.2 -> v0.33.7.3
This commit is contained in:
parent
32f1568515
commit
392de3264f
|
|
@ -1,5 +1,13 @@
|
|||
# Bill Tracker — Changelog
|
||||
|
||||
## v0.33.7.3
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **SimpleFIN transaction table now uses fixed column sizing** — Long transaction text no longer pushes action buttons off-screen. Action buttons are compact icon-only with aria-label/title for accessibility. Long matched bill names are truncated.
|
||||
|
||||
---
|
||||
|
||||
## v0.33.7.2
|
||||
|
||||
### 🚀 Features
|
||||
|
|
|
|||
|
|
@ -521,7 +521,14 @@ export default function TransactionMatchingSection({ refreshKey, simplefinConn }
|
|||
No transactions found for this filter.
|
||||
</div>
|
||||
) : (
|
||||
<table className="w-full text-sm">
|
||||
<table className="w-full min-w-[860px] table-fixed text-sm">
|
||||
<colgroup>
|
||||
<col className="w-[92px]" />
|
||||
<col />
|
||||
<col className="w-[200px]" />
|
||||
<col className="w-[120px]" />
|
||||
<col className="w-[96px]" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr className="border-b border-border/50 bg-muted/30 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground">
|
||||
<th className="px-4 py-2 text-left">Date</th>
|
||||
|
|
@ -540,7 +547,7 @@ export default function TransactionMatchingSection({ refreshKey, simplefinConn }
|
|||
<td className="px-4 py-3 text-xs text-muted-foreground whitespace-nowrap">
|
||||
{transactionDate(tx)}
|
||||
</td>
|
||||
<td className="px-4 py-3 min-w-[240px]">
|
||||
<td className="max-w-0 px-4 py-3">
|
||||
<div className="min-w-0">
|
||||
<p className="truncate text-sm font-medium">{transactionTitle(tx)}</p>
|
||||
<p className="mt-0.5 truncate text-xs text-muted-foreground">
|
||||
|
|
@ -548,11 +555,11 @@ export default function TransactionMatchingSection({ refreshKey, simplefinConn }
|
|||
</p>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-4 py-3 min-w-[180px]">
|
||||
<td className="px-4 py-3">
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<TransactionStatusBadge tx={tx} />
|
||||
{tx.matched_bill_name ? (
|
||||
<span className="text-xs text-foreground">{tx.matched_bill_name}</span>
|
||||
<span className="truncate text-xs text-foreground">{tx.matched_bill_name}</span>
|
||||
) : (
|
||||
<span className="text-xs text-muted-foreground">No bill linked</span>
|
||||
)}
|
||||
|
|
@ -564,29 +571,64 @@ export default function TransactionMatchingSection({ refreshKey, simplefinConn }
|
|||
)}>
|
||||
{formatTransactionAmount(tx.amount, tx.currency)}
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
<div className="flex justify-end gap-1.5">
|
||||
<td className="px-3 py-3">
|
||||
<div className="flex justify-end gap-1.5 whitespace-nowrap">
|
||||
{status === 'ignored' ? (
|
||||
<Button size="sm" variant="outline" type="button" disabled={busy} onClick={() => runTransactionAction(tx, 'unignore')}>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="outline"
|
||||
type="button"
|
||||
disabled={busy}
|
||||
onClick={() => runTransactionAction(tx, 'unignore')}
|
||||
className="h-8 w-8 shrink-0"
|
||||
aria-label="Unignore transaction"
|
||||
title="Unignore transaction"
|
||||
>
|
||||
{busy ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Eye className="h-3.5 w-3.5" />}
|
||||
<span className="ml-1.5 hidden xl:inline">Unignore</span>
|
||||
<span className="sr-only">Unignore</span>
|
||||
</Button>
|
||||
) : (
|
||||
<>
|
||||
{status === 'matched' ? (
|
||||
<Button size="sm" variant="outline" type="button" disabled={busy} onClick={() => runTransactionAction(tx, 'unmatch')}>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="outline"
|
||||
type="button"
|
||||
disabled={busy}
|
||||
onClick={() => runTransactionAction(tx, 'unmatch')}
|
||||
className="h-8 w-8 shrink-0"
|
||||
aria-label="Unmatch transaction"
|
||||
title="Unmatch transaction"
|
||||
>
|
||||
{busy ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Link2Off className="h-3.5 w-3.5" />}
|
||||
<span className="ml-1.5 hidden xl:inline">Unmatch</span>
|
||||
<span className="sr-only">Unmatch</span>
|
||||
</Button>
|
||||
) : (
|
||||
<Button size="sm" type="button" disabled={busy || billsLoading} onClick={() => openMatchDialog(tx)}>
|
||||
<Button
|
||||
size="icon"
|
||||
type="button"
|
||||
disabled={busy || billsLoading}
|
||||
onClick={() => openMatchDialog(tx)}
|
||||
className="h-8 w-8 shrink-0"
|
||||
aria-label="Match transaction"
|
||||
title="Match transaction"
|
||||
>
|
||||
<Link2 className="h-3.5 w-3.5" />
|
||||
<span className="ml-1.5 hidden xl:inline">Match</span>
|
||||
<span className="sr-only">Match</span>
|
||||
</Button>
|
||||
)}
|
||||
<Button size="sm" variant="ghost" type="button" disabled={busy} onClick={() => runTransactionAction(tx, 'ignore')}>
|
||||
<Button
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
type="button"
|
||||
disabled={busy}
|
||||
onClick={() => runTransactionAction(tx, 'ignore')}
|
||||
className="h-8 w-8 shrink-0"
|
||||
aria-label="Ignore transaction"
|
||||
title="Ignore transaction"
|
||||
>
|
||||
{busy ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <EyeOff className="h-3.5 w-3.5" />}
|
||||
<span className="ml-1.5 hidden xl:inline">Ignore</span>
|
||||
<span className="sr-only">Ignore</span>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,13 @@ export const APP_NAME = 'BillTracker';
|
|||
export const RELEASE_NOTES = {
|
||||
version: APP_VERSION,
|
||||
date: '2026-05-29',
|
||||
version: APP_VERSION,
|
||||
highlights: [
|
||||
{
|
||||
icon: '🔄',
|
||||
title: 'SimpleFIN transaction table fix',
|
||||
desc: 'Transaction table now uses fixed column sizing so long text can\'t push action buttons off-screen. Action buttons are compact icon-only with accessible labels.',
|
||||
},
|
||||
{
|
||||
icon: '🔄',
|
||||
title: 'SimpleFIN payment backfill',
|
||||
|
|
@ -33,11 +39,6 @@ export const RELEASE_NOTES = {
|
|||
title: 'Privacy and release notes',
|
||||
desc: 'A public Privacy page is available from About, release notes can render images, and this update card now resets from the backend whenever the app version changes.',
|
||||
},
|
||||
{
|
||||
icon: '❄️',
|
||||
title: 'Ramsey Snowball mode',
|
||||
desc: 'Debt Snowball now defaults to smallest-balance-first, keeps custom drag ordering behind a toggle, skips mortgages by default, and adds an inline Ramsey readiness checklist.',
|
||||
},
|
||||
],
|
||||
image: {
|
||||
src: '/img/doingmypart.jpg',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "bill-tracker",
|
||||
"version": "0.33.7.2",
|
||||
"version": "0.33.7.3",
|
||||
"description": "Monthly bill tracking system",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
Loading…
Reference in New Issue