diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..804eaaa --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,157 @@ +# Design System — ZarinPal Merchant Analytics + +- Status: Draft baseline for approval +- Version: 0.1.0 +- Last updated: 2026-08-20 +- Direction: Persian-first RTL + +## Design intent + +Match the recognizable product language of ZarinPal without copying inaccessible proprietary assets: calm financial confidence, generous whitespace, crisp white surfaces, strong blue actions, restrained yellow accents, dark ink sections, rounded geometry, and dense data presented in plain language. + +The authenticated panel screenshots are the primary behavioral reference: fixed right navigation on desktop, right-side drawer on narrow screens, light gray workspace, white cards, compact outlined controls, blue active states, and direct numerical summaries. The public-site screenshots inform larger radius, dark promotional surfaces, and spacing—but the dashboard prioritizes speed and legibility over marketing spectacle. + +## Foundations + +### Color tokens + +| Token | Value | Use | +|---|---:|---| +| `--color-brand-600` | `#0A33FF` | Primary actions, active navigation, links, selected chart series | +| `--color-brand-700` | `#0828CC` | Hover/pressed brand state | +| `--color-accent-400` | `#FFD400` | Small ZarinPal-like accent, highlights; never body text on white | +| `--color-ink-950` | `#19191A` | Primary text, dark panels | +| `--color-ink-700` | `#3D3D42` | Secondary strong text | +| `--color-ink-500` | `#6B6B73` | Supporting text | +| `--color-canvas` | `#F1F1F3` | Application background | +| `--color-surface` | `#FFFFFF` | Cards, drawer, dialogs | +| `--color-surface-muted` | `#F7F7F8` | Nested panels, table headers | +| `--color-border` | `#E3E3E7` | Dividers and neutral outlines | +| `--color-success-600` | `#248061` | Success states and positive semantic data | +| `--color-warning-600` | `#A86700` | Warnings; paired with text/icon, never color alone | +| `--color-danger-500` | `#FF5C5D` | Errors and destructive actions | +| `--color-info-surface` | `#E7F2FF` | Informational callouts | + +All text/background pairs must meet WCAG 2.2 AA contrast. Chart palettes require patterns, labels, or shapes in addition to hue. + +### Typography + +- Preferred Persian UI family: a legally distributable Yekan-family webfont if supplied/licensed for this project. +- Safe open fallback: `Vazirmatn`, then `Tahoma`, system sans-serif. +- Use tabular numerals for tables/KPIs where supported. +- Body: 14–16 px, line-height 1.7–1.9 for Persian. +- Labels/meta: 12–14 px; never below 12 px. +- Section heading: 20–24 px, weight 700. +- Page heading: 28–32 px desktop, 24–28 px mobile, weight 700–800. +- Avoid ultralight weights and excessive bolding. Keep Persian punctuation and half-spaces correct. + +### Spacing, shape, elevation + +- Base spacing unit: 4 px; common sequence `4, 8, 12, 16, 24, 32, 48, 64`. +- Control height: 40 px desktop; interactive touch target at least 44×44 px on touch layouts. +- Card radius: 12 px for dense dashboard cards; 16–20 px for feature/empty-state surfaces. +- Button/input radius: 8–10 px; pill radius only for compact statuses and segmented controls. +- Card border is preferred over shadow. Default elevation is subtle (`0 1px 3px rgb(25 25 26 / 0.08)`); overlays may use stronger elevation. +- Content width is bounded for scanning; tables/charts may use the full available dashboard column. + +## Layout and responsiveness + +### Desktop (≥ 1024 px) + +- Fixed right sidebar, approximately 248–272 px wide. +- Top utility bar remains visually quiet. +- Main content uses a centered, fluid container with 24–32 px gutters. +- Overview uses a 12-column grid. Primary analytics get 8 columns; secondary summaries get 4 where useful. +- Do not create large empty regions merely to mimic the reference screenshot; use the density required by real content. + +### Tablet (768–1023 px) + +- Sidebar becomes an overlay drawer from the right. +- Two-column cards collapse according to content, not arbitrary device labels. +- Tables may scroll horizontally only after priority columns and responsive alternatives are considered. + +### Mobile (< 768 px) + +- Single-column content, 16 px outer gutter. +- Right-side navigation drawer traps focus, closes with Escape/backdrop, restores focus to its trigger, and locks background scroll. +- KPI pairs stack; charts remain at least 240 px tall and expose an accessible data table/summary. +- Sticky actions must not cover content or browser safe areas. + +## Navigation and information architecture + +Initial authenticated routes: + +1. ورود (login) +2. پیشخوان (overview) +3. عملکرد پرداخت (success, retries, failures, timing) +4. کارمزد و درآمد (relative fee/cost analytics, clearly qualified) +5. مقایسه با هم‌گروه‌ها (anonymized category/cohort benchmark) +6. کیفیت داده / درباره شاخص‌ها (definitions, freshness, limitations) +7. حساب کاربری / خروج + +Navigation labels should describe merchant tasks, not internal database concepts. Active location is conveyed by color plus a bar/background and `aria-current`. + +## Core component contracts + +- **App shell:** sidebar/drawer, utility header, page title, merchant identity, freshness indicator. +- **Metric card:** label, formatted value/unit, comparison and period, semantic trend, definition link, states. +- **Chart card:** title, period/filter controls, concise takeaway, plot, legend, accessible tabular alternative, provenance link. +- **Insight card:** deterministic finding, numeric evidence, suggested merchant action, confidence/limitation; AI-generated copy is visibly labeled later. +- **Data table:** semantic headers, server pagination/sorting, row actions named for screen readers, responsive priority, empty/error states. +- **Filter bar:** URL-backed state, explicit apply/reset behavior, Persian date/time semantics. +- **Status badge:** text plus icon/shape; color reinforces but never carries meaning alone. +- **Feedback:** inline field errors, page-level error boundary, skeleton only when layout is known, retry action for recoverable failures. + +## Data visualization + +- Lead with a written takeaway and exact KPI; charts support the conclusion rather than decorate it. +- Default comparisons: current period vs previous equivalent period and merchant vs eligible anonymized cohort. +- Always show unit, timezone/calendar, date window, sample size, freshness, and missing-data caveat where material. +- Success/failure colors remain semantic and consistent. Never use a rainbow categorical palette for ordered values. +- Tooltips are keyboard reachable and not the sole location of important values. +- Charts have a textual summary and downloadable/visible data table when practical. +- Zero, unavailable, suppressed, and not-yet-calculated are visually and linguistically distinct. + +## Motion + +- Functional motion only: drawer/dialog transitions, focus/selection feedback, and short chart/filter state changes. +- Typical duration 120–220 ms; enter may be slightly slower than exit. +- Prefer opacity and transform. Avoid layout-heavy animation and dashboard-wide scroll reveals. +- Honor `prefers-reduced-motion` by removing nonessential movement. +- No third-party scroll-reveal library is planned for the authenticated panel. Reconsider only for a separately scoped marketing surface. + +## Persian, direction, and formatting + +- Root UI is `lang="fa" dir="rtl"`. +- Technical identifiers, URLs, hashes, and mixed Latin values use isolated LTR spans (`dir="ltr"`) to prevent bidi corruption. +- Use `Intl.NumberFormat`/`Intl.DateTimeFormat`; specifications must choose Persian vs Latin digits, Jalali vs Gregorian display, timezone, and Rial/Toman terminology before implementation. +- Do not concatenate translated fragments. Write complete Persian strings with correct نیم‌فاصله. +- Authentication errors must not reveal whether a username exists. + +## Accessibility and interaction + +- WCAG 2.2 AA target. +- Visible `:focus-visible` ring on every interactive element. +- Semantic buttons/links/forms before ARIA; icons have accessible names or are hidden when decorative. +- All functionality is keyboard operable. Dialogs/drawers manage focus correctly. +- Validation is associated with fields and announced; asynchronous updates use restrained live regions. +- Loading indicators expose status text; avoid endless skeletons. +- Destructive or consequential actions require clear confirmation and recovery where possible. + +## Current decisions and change log + +| Version | Date | Decision | +|---|---|---| +| 0.1.0 | 2026-08-20 | Established ZarinPal-inspired RTL foundation from supplied public/panel screenshots; fixed SvelteKit/Svelte/TypeScript/Tailwind stack; defined responsive shell, core components, accessibility, chart, and motion rules. | + +Any material token/component/interaction change increments this version and adds a row describing why it changed. A surprising or difficult-to-reverse change also receives an ADR. + +## Open design decisions before approval + +1. Licensed Yekan-family assets vs open `Vazirmatn` fallback. +2. Persian or Latin digits for dashboard values. +3. Jalali display with Gregorian API values, and the authoritative reporting timezone. +4. Rial-only vs Toman display and conversion wording. +5. Exact information architecture and MVP metric set after the analytics spec. +6. Whether a dark theme is required; it is not assumed merely because the public site uses dark feature sections. +