162 lines
10 KiB
Markdown
162 lines
10 KiB
Markdown
# Design System — ZarinPal Merchant Analytics
|
||
|
||
- Status: Draft baseline for approval
|
||
- Version: 0.1.6
|
||
- 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, analytics-cache status. First access shows an explicit calculation state. A current cached revision shows its calculated time; a source-revision mismatch or failed recalculation shows the previous result only with an explicit stale warning.
|
||
- **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, and approved daily, weekly, Jalali-month, and Persian-season periods with unambiguous comparison baselines.
|
||
- **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 an eligible anonymized cohort. Peer values appear only when at least 10 other merchants and 1,000 combined peer sessions contribute; otherwise show a clear insufficient-data state.
|
||
- Always show unit, timezone/calendar, exact reporting period, comparison baseline, 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.
|
||
- Only source status `Verified` is presented as a confirmed successful payment. `Paid` is a separate operational state and is never merged into success or failure without a later approved metric-definition change.
|
||
|
||
## 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`. Display merchant-facing dates in the Jalali calendar and `Asia/Tehran`; API instants remain ISO-8601 UTC. Specifications must still choose Persian vs Latin digits 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.6 | 2026-08-20 | Replaced time-based analytics freshness with lazy first-access calculation and revision-based merchant/cohort cache states; defined Saturday–Friday weeks. |
|
||
| 0.1.5 | 2026-08-20 | Removed holiday/event reporting; limited period controls to daily, weekly, Jalali-month, and Persian-season views. |
|
||
| 0.1.4 | 2026-08-20 | Kept `Paid` separate from confirmed `Verified` success. |
|
||
| 0.1.2 | 2026-08-20 | Added the insufficient-data state and visibility threshold for anonymized peer comparisons. |
|
||
| 0.1.1 | 2026-08-20 | Fixed merchant-facing time presentation to the Jalali calendar in `Asia/Tehran`, with explicit UTC API instants. |
|
||
| 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. Rial-only vs Toman display and conversion wording.
|
||
4. Exact information architecture and MVP metric set after the analytics spec.
|
||
5. Whether a dark theme is required; it is not assumed merely because the public site uses dark feature sections.
|