PackageDetail: toggle pattern for Compare button inCart state

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>
This commit is contained in:
2026-04-23 11:02:30 +10:00
parent 13bd245872
commit 7ecf309459
2 changed files with 28 additions and 43 deletions

View File

@@ -21,11 +21,13 @@ export function PackagesRoute() {
if (!provider || !bundle) return <Navigate to="/" replace />;
// Compare CTA on the PackageDetail panel just adds the selection to the
// basket. The floating CompareBar (mounted in App.tsx) handles navigation
// and removal once the user has 2+ packages selected.
// Compare CTA on the PackageDetail panel toggles the selection in the
// basket — adds when absent, removes when present. The button's visible
// state (Compare / Added + ✓) reflects `isSelectedInCart` below. The
// floating CompareBar (mounted in App.tsx) handles navigation once the
// user has 2+ packages selected.
const handleCompare = () => {
if (selectedId) basket.add(makeBasketKey(provider.id, selectedId));
if (selectedId) basket.toggle(makeBasketKey(provider.id, selectedId));
};
// When the selected package is already in the basket, PackageDetail swaps