fix(quotes): repair misaligned items table on the quote detail page

The table had 9 header cells against 8 body cells: a stray duplicate
"Description" header sat above the one carrying min-w-[360px]. Every
column therefore rendered one position off its label (the "Qty" header
sat over the supplier cell, "Supplier" over cost, and so on), and the
360px reserved for Description landed on Qty instead.

The visible symptom was a long description crushed into ~99px and
wrapped one word per line down a tall thin column, while the Qty cell
sat in 360px of empty space.

Removing the stray header restores the header/cell alignment and gives
Description its intended 360px. Also switches the row action from a
"Update price" text button to an icon-only button with the same title
and an aria-label, which trims the table's natural width from 911px to
789px — the card it lives in is only ~430px wide, so every pixel is
horizontal scrolling the operator has to do.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dave 2026-08-29 09:00:35 +02:00
parent 7c3083c017
commit 42179229aa

View file

@ -2284,20 +2284,31 @@ export default function QuoteDetailPage({ params }: { params: Promise<{ id: stri
</div>
) : (
<>
<div className="hidden md:block rounded-md border overflow-x-auto">
<div className="hidden md:block rounded-md border overflow-x-auto">
<Table>
<TableHeader>
<TableRow>
<TableHead>Description</TableHead>
{/* `min-w-[360px]` guarantees Description gets
the room it needs when Qty + Markup +
Processed + Update-price columns take
their fixed widths. Without this the
table-layout algorithm squeezes
Description down to ~250px on a
1025px container. */}
<TableHead className="min-w-[360px]">Description</TableHead>
<TableHead className="text-center w-[60px]">Qty</TableHead>
{/* NOTE: keep this header count in lock-step
with the TableCell count in the body row
below. A stray duplicate "Description"
header used to sit here, giving 9 headers
against 8 cells: every column rendered one
position off its label, and the
`min-w-[360px]` meant for Description
landed on Qty — so a long description was
crushed into ~99px and wrapped one word
per line while Qty sat in 360px of empty
space.
`min-w-[360px]` guarantees Description gets
the room it needs when Qty + Markup +
Processed + Update-price columns take
their fixed widths. Without this the
table-layout algorithm squeezes
Description down to ~250px on a
1025px container. */}
<TableHead className="min-w-[360px]">Description</TableHead>
<TableHead className="text-center w-[60px]">Qty</TableHead>
<TableHead>Supplier</TableHead>
<TableHead className="text-right">Cost</TableHead>
<TableHead className="text-right">Selling</TableHead>
@ -2308,7 +2319,7 @@ export default function QuoteDetailPage({ params }: { params: Promise<{ id: stri
</span>
</TableHead>
<TableHead className="text-center w-[80px]">Processed</TableHead>
<TableHead className="text-right w-[110px]"></TableHead>
<TableHead className="text-right w-[56px]"></TableHead>
</TableRow>
</TableHeader>
<TableBody>
@ -2342,15 +2353,22 @@ export default function QuoteDetailPage({ params }: { params: Promise<{ id: stri
</Badge>
</TableCell>
<TableCell className="text-right align-top">
{/* Icon-only: this table is already
wider than the 2/3 column it sits
in, so the "Update price" label was
costing ~55px of horizontal scroll
for a button whose pencil icon and
tooltip already say what it does. */}
<Button
size="xs"
size="icon"
variant="outline"
className="h-7 w-7"
onClick={() => setPriceUpdateItem(item)}
disabled={priceUpdateSaving}
title="Update cost and selling price for this item"
aria-label={`Update price for ${item.description || "this item"}`}
>
<Pencil className="mr-1 h-3 w-3" />
Update price
<Pencil className="h-3 w-3" />
</Button>
</TableCell>
</TableRow>