Replace order-filter chip wall with 3 compact selects; subgrid-align trust badges

OrderFilters.tsx: filter chips (7 status + 5 payment-status + N year
options as pills) read as cluttered and ate a lot of vertical space.
Replaced with 3 native <select>s in a row (a small Client Component
just for the onChange→router.push navigation) — same URL-search-param
filtering underneath, just a much more compact control.

TrustRow.tsx: replaced the hardcoded min-h-[3.2rem] title reservation
(a guess, and it visibly over-reserved space for single-line titles)
with a real CSS Grid + `grid-template-rows: subgrid` — every badge's
icon+title box shares the same row-track height (auto-sized to
whichever title actually needs 2 lines), so descriptions align
without any hardcoded value. The two structurally different layouts
(icon-above-title below lg vs. icon-beside-a-title/description-stack
at lg) now render as two separate blocks instead of fighting one
shared shape.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Marco
2026-07-30 22:11:12 +00:00
parent c8cf6ae10d
commit 475ee3fa16
3 changed files with 133 additions and 109 deletions
+44 -32
View File
@@ -11,41 +11,53 @@ export async function TrustRow() {
if (items.length === 0) return null;
return (
// Below lg (1024px): badges sit side by side as one row (never wrap,
// never stack to one-per-row) with icon ABOVE text, centered — icon
// beside text (the lg: layout below) is what made a full row of 3
// badges too wide below ~1024px in the first place (see git history:
// originally lg:-gated for exactly this, then briefly tried flex-wrap,
// which put an odd 3rd item alone on its own wrapped line and read as
// disorganized). Putting the icon above the text instead shrinks each
// badge down to just its text column's width, and — combined with
// dropping whitespace-nowrap on the title/description below lg: so
// long copy wraps within its own narrow column instead of forcing
// overflow — a real row of 3 now fits without wrapping at all, so
// there's no odd-item-out case to worry about. lg:+ reverts to the
// original icon-beside-text row-with-dividers layout unchanged.
<div className="w-full bg-bg-base flex justify-center py-8 px-[var(--layout-padding-x)]">
<div className="flex flex-row justify-center gap-6 lg:gap-12 items-start lg:items-center w-full lg:w-auto">
{items.map((item, i) => (
<div key={item.id} className="flex flex-1 lg:flex-none items-center gap-6 lg:gap-12 min-w-0">
{i > 0 && <div className="hidden lg:block h-10 w-px bg-border" />}
<div className="flex flex-col items-center text-center gap-2 w-full min-w-0 lg:flex-row lg:items-center lg:text-left lg:gap-4 lg:w-auto">
<div className="w-full bg-bg-base py-8 px-[var(--layout-padding-x)]">
{/* Below lg (1024px): a CSS Grid with `grid-template-rows: subgrid` —
not a fixed min-height guess — so every badge's "icon+title" box
shares the SAME row track height (auto-sized to whichever
badge's title actually needs 2 lines), and every description
starts exactly at that row's bottom edge regardless of how many
lines its own title happens to wrap to. Icon beside text (the
lg: layout below) is what made a full row of 3 badges too wide
below ~1024px in the first place (see git history: originally
lg:-gated for exactly this, then briefly tried flex-wrap, which
put an odd 3rd item alone on its own wrapped line and read as
disorganized) — icon above text instead shrinks each badge down
to just its text column's width, letting a real row of 3 fit
without wrapping at all. Two structurally different layouts
(icon-above-title here vs. icon-beside-a-title/description-
stack at lg:) don't share one flexible markup shape cleanly, so
this renders as two separate blocks (lg:hidden / hidden lg:flex)
rather than fighting one shape across both breakpoints. */}
<div
className="lg:hidden grid justify-center gap-x-6 gap-y-1"
style={{ gridTemplateColumns: `repeat(${items.length}, auto)`, gridTemplateRows: "repeat(2, auto)" }}
>
{items.map((item) => (
<div key={item.id} className="grid row-span-2 justify-items-center" style={{ gridTemplateRows: "subgrid" }}>
<div className="flex flex-col items-center gap-2">
<div className="relative size-8 shrink-0">
<Image alt="" src={item.icon} fill sizes="32px" className="object-contain" />
</div>
<div className="flex flex-col gap-0.5 items-center min-w-0 lg:items-start">
{/* min-h reserves 2 lines worth of height (text-body's
line-height is 1.6rem) below lg: — titles are short
enough that some wrap to 2 lines in their narrow
stacked column and some don't, and without a reserved
height the description below started at a different
y-position from one badge to the next depending on
whether its own title happened to wrap. Reset to
min-h-0 at lg: (whitespace-nowrap there forces a
single line anyway, so the reservation would just add
unwanted empty space). */}
<p className="font-semibold text-body text-text-primary min-h-[3.2rem] lg:min-h-0 lg:whitespace-nowrap">{item.title}</p>
<p className="text-body-sm text-text-muted lg:whitespace-nowrap">{item.description}</p>
<p className="font-semibold text-body text-text-primary text-center">{item.title}</p>
</div>
<p className="text-body-sm text-text-muted text-center">{item.description}</p>
</div>
))}
</div>
{/* lg+: original icon-beside-text row with dividers, unchanged. */}
<div className="hidden lg:flex justify-center gap-12 items-center">
{items.map((item, i) => (
<div key={item.id} className="flex items-center gap-12">
{i > 0 && <div className="h-10 w-px bg-border" />}
<div className="flex items-center gap-4">
<div className="relative size-8 shrink-0">
<Image alt="" src={item.icon} fill sizes="32px" className="object-contain" />
</div>
<div className="flex flex-col gap-0.5 items-start">
<p className="font-semibold text-body text-text-primary whitespace-nowrap">{item.title}</p>
<p className="text-body-sm text-text-muted whitespace-nowrap">{item.description}</p>
</div>
</div>
</div>