The unverified-tier "similar packages" section previously rendered a list
of NearbyPackageCards — one per package. Swap to MiniCard, showing the
provider itself: image, verified badge, location, rating, "From $X".
2-col on sm+, 1-col on xs, capped at 4. Heading dropped "nearby" to
"Similar packages from verified providers".
Data shape renamed NearbyVerifiedPackage → NearbyVerifiedProvider;
`verified` is implicit (the section is verified-only by definition).
Callback renamed onNearbyPackageClick → onNearbyProviderClick, routing
directly on provider id. Demo fixture now derives the list from the
main providers fixture (filtered to verified + imageUrl).
NearbyPackageCard is now orphaned — kept in place pending registry
cleanup in a follow-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the earlier inert selected-state treatment. Now:
- Button keeps its default soft/secondary chrome in both states — no
separate brand-tinted visual.
- When `inCart=true`, a leading CheckRoundedIcon is added and the
label swaps from "Compare" to "Added".
- Button remains clickable; `onCompare` is invoked in both states.
Caller treats it as a toggle — add when absent, remove when present.
- aria-pressed reflects the state for SR users; aria-label spells
"Add to comparison" / "Remove from comparison" explicitly.
Demo route swaps `basket.add()` for `basket.toggle()` on the handler
so a second click removes the package from the comparison basket.
Simpler visual (less space, one chrome to maintain) and a clearer
interaction — the user can undo directly from the detail panel
rather than hunting for CompareBar.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a package is already in the comparison basket, the Compare button
swaps to a "In comparison" selected-state: soft brand-50 fill +
brand-300 border + brand-700 text + leading check icon. Technically
disabled (aria-disabled + no onClick) but sx-overrides the default
greyed Mui-disabled look so it reads as "selected/added," not
"unavailable."
Pattern: e-commerce "Added to cart" state. Removal happens via the
floating CompareBar (already owns basket mutation), not this button —
keeps the responsibility split clean.
API:
- PackageDetail: new `inCart?: boolean` prop.
- PackagesStep: forwarded as `isSelectedPackageInCart?: boolean`.
- Demo route (Packages.tsx): computes `basket.has(key)` for the
current selection and passes it through.
Storybook: new PackageDetail story `InCart` alongside the existing
`Default` and `CompareLoading` states.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a self-contained demo build target for the Providers → Packages →
Comparison flow, deployable as a static SPA at /arrangement/.
- vite.demo.config.ts: per-slice build via --mode, base path flips for
dev vs prod, output to dist-demo/<slice>/
- src/demo/: shared fixtures (7 providers across verified/tier3/tier2
with real venue photography from brandassets) + Zustand basket store
with ?compare= URL persistence
- Verified-provider packages now share the nine canonical Essentials
line items per FA convention; only Optionals/Extras vary
- App-level CompareBar surfaces "Already added" / "Maximum 3" feedback
via transient store error
- ProviderCard logo objectFit cover→contain so wide logos don't crop
- npm scripts demo:dev / demo:build, deps zustand + react-router-dom