# Design System Quick Reference ## Component Imports ```typescript import { StatCard, PriceDelta, MarketIndex, DataTable, CompactHeader, DashboardLayout, TickerStrip, } from '@/components/design-system'; ``` ## Quick Examples ### StatCard - KPI Display ```tsx } /> ``` ### PriceDelta - Change Indicator ```tsx {/* +5.20% ↑ Green */} {/* -2.10% ↓ Red */} {/* 0.00% - Yellow */} ``` ### MarketIndex - Hero Metric ```tsx ``` ### DataTable - Sortable Data ```tsx const columns: DataTableColumn[] = [ { id: 'name', header: 'District', cell: (row) => row.name, sortable: true, sortValue: (row) => row.name, }, { id: 'price', header: 'Price/m²', cell: (row) => `${row.avgPrice} tr`, align: 'right', numeric: true, sortable: true, sortValue: (row) => row.avgPrice, }, ]; ``` ### TickerStrip - Scrolling Ticker ```tsx ``` ### DashboardLayout - Full Page Frame ```tsx } sidebar={} ticker={} sidebarCollapsed={collapsed} >
{/* Main content */}
``` ## Design Tokens ### Colors (CSS Variables) **Light Mode** (`:root`) - `--foreground: 220 20% 12%` — Dark navy text - `--background: 0 0% 97%` — Off-white background - `--background-elevated: 0 0% 100%` — Pure white cards - `--primary: 142 72% 42%` — Green (up) - `--signal-down: 0 84% 55%` — Red (down) - `--signal-neutral: 45 93% 45%` — Yellow (neutral) **Dark Mode** (`.dark`) - `--foreground: 210 20% 90%` — Off-white text - `--background: 220 20% 4%` — Very dark background - Same primary/signal colors (brightness-adjusted) ### Typography ```css /* Font families */ font-sans /* Inter */ font-mono /* JetBrains Mono (tabular-nums) */ /* Data-specific sizes */ text-ticker /* 0.8125rem — ticker animation */ text-data-sm /* 0.75rem — compact stats */ text-data-md /* 0.875rem — default metric */ text-data-lg /* 1.25rem — large KPI values */ ``` ### Spacing ```css h-row /* 2.25rem (36px) — table row height */ h-ticker-bar /* 2rem (32px) — ticker height */ h-header-compact /* 3rem (48px) — dashboard header */ ``` ### Utilities ```css [data-numeric] /* Applies font-variant-numeric: tabular-nums */ elevation-1 /* Subtle shadow: 0 1px 2px rgba(0,0,0,0.3) */ elevation-2 /* Prominent shadow: 0 4px 12px rgba(0,0,0,0.4) */ ``` ## Analytics API ```typescript import { analyticsApi } from '@/lib/analytics-api'; import { useMarketReport, useHeatmap, usePriceTrend, useDistrictStats, } from '@/lib/hooks/use-analytics'; // Raw API calls const report = await analyticsApi.getMarketReport('Ho Chi Minh', 'month'); const heatmap = await analyticsApi.getHeatmap('Ho Chi Minh', 'month'); // React Query hooks const { data: districts } = useDistrictStats('Ho Chi Minh', 'month'); const { data: trend } = usePriceTrend('Quan 1', 'Ho Chi Minh', 'apartment', ['month-1', 'month']); ``` ## Charts (Recharts) ```typescript import { PriceTrendChart } from '@/components/charts/price-trend-chart'; import { DistrictBarChart } from '@/components/charts/district-bar-chart'; import { AgentPerformance } from '@/components/charts/agent-performance'; // Line chart with dual Y-axis // Bar chart // Mixed dashboard (with mock data) ``` ## Maps (Mapbox) ```typescript import { DistrictHeatmap } from '@/components/charts/district-heatmap'; import { ListingMap } from '@/components/map/listing-map'; import { LocationPicker } from '@/components/map/location-picker'; // Heatmap console.log(name)} /> // Listing markers navigate(`/listing/${listing.id}`)} /> // Interactive location picker { // resolved.city, resolved.district, resolved.ward available setCoords({ lat, lng }); }} height="400px" /> ``` ## Best Practices 1. **Always use `[data-numeric]` or `font-mono` for numbers** — ensures proper alignment 2. **Signal colors:** Green (up), Red (down), Yellow (neutral) 3. **Spacing:** Use Tailwind gap classes; `gap-4` for cards, `gap-6` for sections 4. **Sticky headers:** `sticky top-0 z-10` pattern 5. **Responsive:** Mobile-first; `md:` for tablet breakpoints 6. **Dark mode:** CSS variables handle both modes automatically 7. **No hardcoded colors:** Use `hsl(var(--primary))` pattern for dynamic theming ## Environment Setup ```bash # Required for maps NEXT_PUBLIC_MAPBOX_TOKEN=your_token_here # Optional NEXT_PUBLIC_ANALYTICS_ENDPOINT=... ```