From 524e1e9a4d64e3c78906f25282ef4eb04fb4397f Mon Sep 17 00:00:00 2001 From: Steve Simonson <144349219+SteveSimonson@users.noreply.github.com> Date: Thu, 30 Jul 2026 23:12:23 -0500 Subject: [PATCH 1/2] fix: make limited-time shop filter impossible to miss When This week is on, show a high-visibility banner (count vs full house + Show full collection), removable filter chips, pressed toggle label, and header/top bar that flip to Full collection exit paths. --- src/components/CategoryHero.tsx | 3 +- src/components/Layout.tsx | 77 +++++++--- src/pages/Shop.tsx | 240 +++++++++++++++++++++++++------- 3 files changed, 244 insertions(+), 76 deletions(-) diff --git a/src/components/CategoryHero.tsx b/src/components/CategoryHero.tsx index 77848a5..91b3600 100644 --- a/src/components/CategoryHero.tsx +++ b/src/components/CategoryHero.tsx @@ -35,7 +35,7 @@ export function CategoryHero({ {limited && ( - This week in {content.title} + Filter on · This week only )} @@ -51,6 +51,7 @@ export function CategoryHero({ {' '} · {productCount} {productCount === 1 ? 'piece' : 'pieces'} + {limited ? ' this week' : ''} ) : null}

diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index aa751c0..f81b37a 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -1,4 +1,4 @@ -import { Link, Outlet, useLocation } from 'react-router-dom' +import { Link, Outlet, useLocation, useSearchParams } from 'react-router-dom' import { Menu, X } from 'lucide-react' import { useState } from 'react' import { formatExpiry, limitedTimeCopy } from '../data/catalog' @@ -24,26 +24,48 @@ function navClass(active: boolean) { export function Layout() { const [open, setOpen] = useState(false) const { pathname } = useLocation() - const limited = limitedTimeCopy() - const until = formatExpiry(limited.expiresAt ?? undefined) + const [searchParams] = useSearchParams() + const drop = limitedTimeCopy() + const until = formatExpiry(drop.expiresAt ?? undefined) + const onShop = pathname === '/shop' || pathname.startsWith('/shop') + const limitedMode = onShop && searchParams.get('limited') === '1' + // When already filtering to this week, offer escape — not another trap door + const weekCta = limitedMode + ? { to: '/shop', label: 'Full collection', primary: false as const } + : { to: '/shop?limited=1', label: 'This week', primary: true as const } return (
-
- - This week’s selection - {limited.count > 0 ? ` · ${limited.count} pieces` : ''} - {until ? ` · Until ${until}` : ''} - - {' '} - · {BRAND.mottoEn} - - -
+ {limitedMode ? ( +
+ Filter on · This week only + {drop.count > 0 ? ` · ${drop.count} pieces` : ''} + · not the full house + {' · '} + + Show full collection + +
+ ) : ( +
+ + This week’s selection + {drop.count > 0 ? ` · ${drop.count} pieces` : ''} + {until ? ` · Until ${until}` : ''} + + {' '} + · {BRAND.mottoEn} + + +
+ )}
@@ -74,10 +96,15 @@ export function Layout() {
- This week + {weekCta.label} +
+ )} + + {/* Active filter chips */} + {hasFilters && ( +
+ + Filtering + + {limited && ( + updateParams({ limited: null })} + /> )} - + {catLabel && ( + updateParams({ cat: null })} + /> + )} + {q && ( + updateParams({ q: null })} + /> + )} + +
)}
- updateParams({ q: e.target.value || null })} - placeholder="Search products…" - className="w-full max-w-md rounded-2xl border border-line bg-card px-4 py-3.5 text-sm font-medium outline-none focus:border-focus:ring-2 focus:ring-bamboo/15" - /> +
+ + updateParams({ q: e.target.value || null })} + placeholder="Search the house…" + className="w-full rounded-2xl border border-line bg-card pl-10 pr-4 py-3.5 text-sm font-medium outline-none focus:border-bamboo focus:ring-2 focus:ring-bamboo/15" + /> +
@@ -166,7 +241,7 @@ export function Shop() { : 'bg-card border border-line hover:border-bamboo/40' }`} > - All categories + All rooms {CATEGORY_OPTIONS.map((c) => ( )}
@@ -214,16 +303,29 @@ export function Shop() { {filtered.length === 0 ? (

No matches

-

- Try another room or clear search / limited filter. +

+ {limited + ? 'Nothing in this week’s list matches. Turn off “This week” or clear filters to see the full house.' + : 'Try another room or clear search.'}

- +
+ {limited && ( + + )} + +
) : ( ) } + +function FilterChip({ + label, + onRemove, + tone = 'default', +}: { + label: string + onRemove: () => void + tone?: 'default' | 'limited' +}) { + const limited = tone === 'limited' + return ( + + ) +} From c5d8d3d81adde8118053e532b5c351207a7ed2ff Mon Sep 17 00:00:00 2001 From: Steve Simonson <144349219+SteveSimonson@users.noreply.github.com> Date: Thu, 30 Jul 2026 23:13:48 -0500 Subject: [PATCH 2/2] fix: align limited-mode exit labels and a11y --- src/components/Layout.tsx | 1 - src/pages/Shop.tsx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index f81b37a..10a30b2 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -102,7 +102,6 @@ export function Layout() { ? 'btn-primary !px-3.5 sm:!px-4 !py-2.5 text-xs' : 'inline-flex items-center justify-center rounded-full border-2 border-[#9a3412] text-[#9a3412] bg-white px-3.5 sm:px-4 py-2.5 text-xs font-bold hover:bg-[#fff7ed] transition' } - aria-current={limitedMode ? 'page' : undefined} > {weekCta.label} diff --git a/src/pages/Shop.tsx b/src/pages/Shop.tsx index 1aea54b..31b4a1f 100644 --- a/src/pages/Shop.tsx +++ b/src/pages/Shop.tsx @@ -150,7 +150,7 @@ export function Shop() { className="shrink-0 inline-flex items-center justify-center gap-1.5 rounded-full bg-[#9a3412] text-white px-4 py-2.5 text-sm font-bold hover:bg-[#7c2d12] transition" > - Show full collection + Turn off This week
)}