# 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=...
```