--- phase: 33 slug: currency-system status: draft shadcn_initialized: false preset: none created: 2026-04-13 --- # Phase 33 — UI Design Contract > Visual and interaction contract for the Currency System phase. Covers market/currency selector, dual price display, converted price labels, community price aggregation display, and candidate research price fields. --- ## Design System | Property | Value | |----------|-------| | Tool | none | | Preset | not applicable | | Component library | none (custom Tailwind components) | | Icon library | Lucide via `LucideIcon` from `lib/iconData` | | Font | System font stack (Tailwind default) | --- ## Spacing Scale Declared values (must be multiples of 4): | Token | Value | Usage | |-------|-------|-------| | xs | 4px | Icon gaps, inline padding | | sm | 8px | Compact element spacing, pill toggle gaps | | md | 16px | Default element spacing, card padding | | lg | 24px | Section padding within cards | | xl | 32px | Layout gaps between sections | | 2xl | 48px | Major section breaks | | 3xl | 64px | Page-level spacing | Exceptions: none --- ## Typography | Role | Size | Weight | Line Height | |------|------|--------|-------------| | Body | 14px (text-sm) | 400 (normal) | 1.5 | | Label | 12px (text-xs) | 500 (medium) | 1.5 | | Heading | 20px (text-xl) | 600 (semibold) | 1.4 | | Display | 14px (text-sm) | 600 (semibold) | 1.5 | Matches existing app typography (settings page, detail pages). --- ## Color | Role | Value | Usage | |------|-------|-------| | Dominant (60%) | #ffffff | Page background, card surfaces | | Secondary (30%) | #f9fafb / #f3f4f6 | Gray-50/100 — pill backgrounds, inactive states, card borders | | Accent (10%) | #3b82f6 | Blue-500 — conversion indicator icon, "best price" highlight | | Destructive | #ef4444 | Red-500 — not used in this phase | Accent reserved for: conversion indicator dots, "best price" cell highlight (green-50 for price, blue-50 for weight — existing pattern from ComparisonTable) ### Phase-Specific Colors | Element | Color | Tailwind Class | |---------|-------|----------------| | Converted price text | gray-400 | `text-gray-400` | | Conversion tilde prefix | gray-400 | `text-gray-400` | | Market price label | gray-500 | `text-gray-500` | | Community price aggregate | gray-700 | `text-gray-700` | | Community report count | gray-400 | `text-gray-400` | | Auto-suggestion banner background | blue-50 | `bg-blue-50` | | Auto-suggestion banner text | blue-700 | `text-blue-700` | --- ## Component Specifications ### 1. Market/Currency Selector (Settings Page) Evolves the existing currency pill toggle. Same visual pattern, updated copy. **Layout:** ``` ┌──────────────────────────────────────────────────────────┐ │ Market & Currency │ │ Sets your market region and currency for price display │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ [$ USD] [€ EUR] [£ GBP] [¥ JPY] [CA$ CAD] [A$ AUD] │ │ │ └────────────────────────────────────────────────┘ │ │ │ │ ── separator ── │ │ │ │ Show Converted Prices [toggle]│ │ Display approximate conversions when local price │ │ is not available │ └──────────────────────────────────────────────────────────┘ ``` **Specs:** - Pill toggle: same `bg-gray-100 rounded-full` container, same button styles as existing - Selected pill: `bg-white text-gray-700 shadow-sm font-medium` - Unselected pill: `text-gray-400 hover:text-gray-600` - New toggle for "Show Converted Prices": standard toggle switch, `bg-gray-200` off / `bg-blue-500` on - Section heading: `text-sm font-medium text-gray-900` - Description: `text-xs text-gray-500 mt-0.5` ### 2. Auto-Suggestion Banner (First Visit) Shown once when no currency preference is set. Appears above the settings card. **Layout:** ``` ┌──────────────────────────────────────────────────────────┐ │ 🌍 Based on your location, we suggest EUR (€) [Use €] │ └──────────────────────────────────────────────────────────┘ ``` **Specs:** - Container: `bg-blue-50 border border-blue-100 rounded-xl px-4 py-3` - Text: `text-sm text-blue-700` - Button: `text-sm font-medium text-blue-700 hover:text-blue-800 underline` - Globe icon: Lucide `globe` icon, 16px, `text-blue-500` - Dismissible: clicking "Use €" sets the setting and hides the banner ### 3. Dual Price Display Format (D-14) When a price is converted from another currency, display both. **Inline format:** `€2,000 (~$2,160)` **Specs:** - Source price: `text-sm font-medium text-gray-900` (existing style) - Converted price: `text-xs text-gray-400 ml-1` - Tilde prefix: included in converted text as literal `~` - No line break between source and converted — inline on same line - If no conversion needed (local price exists): show only the local price, no parenthetical ### 4. Global Item Detail — Market Prices Section (D-17) New section on the catalog item detail page, below existing specs. **Layout:** ``` ┌──────────────────────────────────────────────────────────┐ │ Price │ │ │ │ €2,199.00 MSRP (EU) │ │ │ │ Community (DE): €1,680 median (14 reports) │ │ │ │ ▸ Other Markets │ │ $2,499.00 MSRP (US) │ │ £1,999.00 MSRP (UK) │ │ Community (US): $2,100 median (8 reports) │ └──────────────────────────────────────────────────────────┘ ``` **Specs:** - Section heading: `text-sm font-medium text-gray-900` - Primary market price: `text-lg font-semibold text-gray-900` - Market label: `text-xs text-gray-500 ml-2` - Community line: `text-sm text-gray-700` - Report count: `text-xs text-gray-400` in parentheses - "Other Markets" collapsible: `text-sm text-gray-500 cursor-pointer hover:text-gray-700` - Chevron: Lucide `chevron-right` (rotates to `chevron-down` when expanded), 14px - Collapsed by default - Inner market rows: same styling, indented with `pl-4` ### 5. Comparison Table — Currency Normalization (D-20) Extends existing ComparisonTable component. **Existing behavior preserved.** Additional specs: - When candidate price is in a different currency than user's preference, show dual format in the price cell - Converted prices show `~` prefix: `~$2,160` in `text-gray-400` - Best-price highlighting (existing `bg-green-50`) still applies after conversion - New "Found Price" row in comparison table for candidate research prices (D-06) ### 6. Candidate "Price I Found" Field (D-06, D-07) New fields in the candidate edit form. **Layout:** ``` ┌──────────────────────────────────────────────────────────┐ │ Price I Found │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐│ │ │ $ _____.__ │ │ USD ▾ │ │ 2026-04-13 ││ │ └──────────────┘ └──────────────┘ └──────────────────┘│ │ Research price — when you found it at this price │ └──────────────────────────────────────────────────────────┘ ``` **Specs:** - Field row: three inputs inline (`flex gap-2`) - Price input: standard number input matching existing `priceCents` field style - Currency select: small dropdown matching existing form select style, `text-xs` - Date input: standard date input, `text-xs` - Helper text: `text-xs text-gray-400 mt-1` --- ## Copywriting Contract | Element | Copy | |---------|------| | Market selector heading | "Market & Currency" | | Market selector description | "Sets your market region and currency for price display" | | Conversion toggle heading | "Show Converted Prices" | | Conversion toggle description | "Display approximate conversions when local price is not available" | | Auto-suggestion text | "Based on your location, we suggest {CURRENCY} ({SYMBOL})" | | Auto-suggestion CTA | "Use {SYMBOL}" | | Converted price label | "~{SYMBOL}{amount}" (inline, no separate label) | | Community price line | "Community ({MARKET}): {SYMBOL}{median} median ({N} reports)" | | Other markets toggle | "Other Markets" | | Found price label | "Price I Found" | | Found price helper | "Research price — when you found it at this price" | | No market price fallback | "No local price — showing converted estimate" | | Price section heading | "Price" | --- ## Registry Safety | Registry | Blocks Used | Safety Gate | |----------|-------------|-------------| | No registries | N/A | N/A | This phase uses only custom Tailwind components matching existing codebase patterns. --- ## Checker Sign-Off - [ ] Dimension 1 Copywriting: PASS - [ ] Dimension 2 Visuals: PASS - [ ] Dimension 3 Color: PASS - [ ] Dimension 4 Typography: PASS - [ ] Dimension 5 Spacing: PASS - [ ] Dimension 6 Registry Safety: PASS **Approval:** pending