10 KiB
phase, slug, status, shadcn_initialized, preset, created
| phase | slug | status | shadcn_initialized | preset | created |
|---|---|---|---|---|---|
| 33 | currency-system | draft | false | none | 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-fullcontainer, 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-200off /bg-blue-500on - 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
globeicon, 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-400in parentheses - "Other Markets" collapsible:
text-sm text-gray-500 cursor-pointer hover:text-gray-700 - Chevron: Lucide
chevron-right(rotates tochevron-downwhen 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,160intext-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
priceCentsfield 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