From 691d8aa9da431b026f2efe7326ffec3a348fae27 Mon Sep 17 00:00:00 2001 From: Saravana Achu Mac Date: Sat, 9 May 2026 14:20:59 -0700 Subject: [PATCH] docs: expand UX guide to comprehensive implementation guide Expanded from testing-focused guide to comprehensive UX implementation guide covering all UX work from last 2 days: Part 1: Common Platform UI Integration - Product Adapter Pattern with type-safe extensions - Centralized import point for all UI components - Product-specific variants without modifying common platform Part 2: Design Token Usage - CSS variable integration patterns - Component token patterns - Token migration checklist Part 3: Component Normalization - Badge normalization (commit: 94ce743) - Alert banner unification (commit: d4846b7) - Table controls standardization - Control normalization pattern with 5-step process Part 4: Accessibility Improvements - Keyboard navigation patterns (commits: 3c52593, a65d726) - ARIA labels for buttons, status indicators, forms - Focus indicators and focus order Part 5: Responsive Design - Shell breakpoints (commit: c51544a) - Viewport matrix testing - Mobile-first patterns Part 6: Testing Infrastructure - Playwright setup (commit: 8db23bd) - Test suite structure (commit: 79f0021) - Test runner with server lifecycle (commits: df7c57e, a572293, 2bd38e1) - AI-friendly report generation - Storybook setup Part 7: Cipher Design System Integration - Design principles: hierarchy, spacing, typography, color, accessibility - Component patterns: cards, buttons, alerts - WCAG AA compliance Part 8: Implementation Roadmap - 10-week phased approach - Clear verification commands at each phase - Commit references for specific patterns Part 9: Verification Commands - UI audit, type checking, build verification - Test execution commands - Storybook commands Part 10: Troubleshooting - Common issues and solutions - Playwright, design tokens, component imports Part 11: Best Practices - Component development, code organization - Testing strategy, documentation Part 12: References - Common platform, Cipher design system, testing tools This guide enables other products to replicate the exact same UX implementation approach with 40+ commits of UX work documented. --- docs/UX_TESTING_SETUP_GUIDE.md | 1492 +++++++++++++++++++++++--------- 1 file changed, 1069 insertions(+), 423 deletions(-) diff --git a/docs/UX_TESTING_SETUP_GUIDE.md b/docs/UX_TESTING_SETUP_GUIDE.md index 74efaf2..b03f81e 100644 --- a/docs/UX_TESTING_SETUP_GUIDE.md +++ b/docs/UX_TESTING_SETUP_GUIDE.md @@ -1,155 +1,600 @@ -# UX Testing Setup Guide +# UX Implementation Guide -> **Purpose:** Comprehensive guide for setting up UX testing infrastructure across ByteLyst products using common platform UI packages, design tokens, and Cipher design system integration. +> **Purpose:** Comprehensive guide for UX implementation across ByteLyst products using common platform UI packages, design tokens, and Cipher design system integration. -> **Target Audience:** Product teams implementing E2E testing for their applications. +> **Target Audience:** Product teams implementing UX improvements and testing infrastructure. --- ## Overview -This guide documents the complete UX testing infrastructure setup for the trading dashboard, which can be replicated across all ByteLyst products. The approach leverages: +This guide documents the complete UX implementation approach for the trading dashboard, which can be replicated across all ByteLyst products. The approach covers: -- **Playwright** for end-to-end testing -- **Common Platform UI packages** (`@bytelyst/ui`) -- **Design Tokens** from `@bytelyst/design-tokens` -- **Cipher Design System** principles -- **AI-friendly reporting** for automated analysis +- **Common Platform UI Integration** - Leveraging `@bytelyst/ui` shared primitives +- **Design Token Usage** - Using `@bytelyst/design-tokens` for consistent styling +- **Component Normalization** - Replacing one-off components with shared primitives +- **Accessibility Improvements** - Keyboard navigation, ARIA labels, focus management +- **Responsive Design** - Viewport matrix testing, shell breakpoints +- **Testing Infrastructure** - Playwright E2E tests, Storybook, AI-friendly reports +- **Cipher Design System** - Visual hierarchy, spacing, typography principles --- -## Prerequisites +## Part 1: Common Platform UI Integration -### Common Platform Integration +### Product Adapter Pattern -Ensure your product is integrated with the common platform: +Create a product adapter to normalize imports and extend shared primitives with product-specific variants: -```bash -# Use local packages by default -BYTELYST_PACKAGE_SOURCE=common-plat - -# Install common platform packages -pnpm install @bytelyst/ui @bytelyst/design-tokens -``` - -### Design Tokens - -Design tokens should be consumed from the common platform: +**File:** `web/src/components/ui/Primitives.tsx` ```typescript -// Use CSS variables from design tokens +import * as React from 'react'; +import { + Badge as CommonBadge, + Button as CommonButton, + Field, + FieldContent, + FieldDescription, + FieldError, + FieldGroup, + FieldLabel, + FieldTitle, + Input as CommonInput, + Select as CommonSelect, + Textarea as CommonTextarea, + type BadgeProps as CommonBadgeProps, + type ButtonProps as CommonButtonProps, + type InputProps as CommonInputProps, + type SelectProps as CommonSelectProps, + type TextareaProps as CommonTextareaProps, +} from '@bytelyst/ui'; + +// Re-export all shared primitives +export { + ActionMenu, + AlertBanner, + DataList, + DataTable, + Drawer, + EmptyState, + EntityCard, + FieldGrid, + FilterBar, + FormSection, + MetricCard, + Modal, + PageHeader, + Panel, + Skeleton, + Timeline, + Toolbar, + // ... all other @bytelyst/ui components +} from '@bytelyst/ui'; + +// Define product-specific variants +type ProductButtonVariant = NonNullable | 'link'; +type ProductButtonSize = NonNullable | 'icon'; +type ProductFieldVariant = 'surface' | 'muted'; +type ProductFieldSize = 'sm' | 'md'; +type ProductBadgeVariant = NonNullable | 'danger'; +type ProductStatusTone = 'success' | 'warning' | 'error' | 'info' | 'neutral'; + +// Extend interfaces with product-specific props +export interface ButtonProps extends Omit { + variant?: ProductButtonVariant; + size?: ProductButtonSize; +} + +export interface IconButtonProps extends Omit { + icon: React.ReactNode; + label: string; +} + +export interface InputProps extends CommonInputProps { + controlSize?: ProductFieldSize; + variant?: ProductFieldVariant; +} + +// Product status mapping for badges +export type ProductStatus = + | 'active' | 'approved' | 'blocked' | 'buy' | 'cancelled' + | 'connected' | 'danger' | 'degraded' | 'disabled' | 'error' + | 'failed' | 'idle' | 'info' | 'live' | 'neutral' | 'off' + | 'ok' | 'paper' | 'pending' | 'rejected' | 'sell' | 'success' + | 'synced' | 'warning'; + +const productStatusTone: Record = { + active: 'success', + approved: 'success', + blocked: 'error', + buy: 'success', + cancelled: 'neutral', + connected: 'success', + danger: 'error', + degraded: 'warning', + disabled: 'neutral', + error: 'error', + failed: 'error', + idle: 'neutral', + info: 'info', + live: 'warning', + neutral: 'neutral', + off: 'neutral', + ok: 'success', + paper: 'info', + pending: 'warning', + rejected: 'error', + sell: 'error', + success: 'success', + synced: 'success', + warning: 'warning', +}; + +// Helper function to map product status to tone +export function statusToneFor(status: ProductStatus | string | null | undefined): ProductStatusTone { + if (!status) return 'neutral'; + const normalized = status.trim().toLowerCase().replace(/[\s_]+/g, '-') as ProductStatus; + return productStatusTone[normalized] ?? 'neutral'; +} + +// Product-specific component implementations +export const Button = React.forwardRef( + ({ variant = 'primary', size = 'md', className, ...props }, ref) => ( + + ), +); + +export const IconButton = React.forwardRef( + ({ icon, label, variant = 'ghost', size = 'icon', className, ...props }, ref) => ( + + ), +); + +export const Input = React.forwardRef( + ({ controlSize = 'md', variant = 'surface', className, ...props }, ref) => ( + + ), +); + +export function ProductStatusBadge({ + status, + children, +}: { + status: ProductStatus | string | null | undefined; + children?: React.ReactNode; +}) { + return ( + + {children ?? status ?? 'Unknown'} + + ); +} +``` + +**Benefits of Product Adapter Pattern:** +- Centralized import point for all UI components +- Product-specific variants without modifying common platform +- Consistent styling across the application +- Easy to migrate to new common platform versions +- Type-safe extensions with TypeScript + +--- + +## Part 2: Design Token Usage + +### CSS Variable Integration + +Use design tokens from `@bytelyst/design-tokens` via CSS custom properties: + +```css +/* Surface colors */ background: var(--bl-surface-card); +background: var(--bl-surface-muted); +background: var(--bl-surface-overlay); + +/* Text colors */ +color: var(--bl-text-primary); +color: var(--bl-text-secondary); +color: var(--bl-text-muted); + +/* Border colors */ +border-color: var(--bl-border); +border-color: var(--bl-border-muted); + +/* Input styling */ +background: var(--bl-input); color: var(--bl-text-primary); border-color: var(--bl-border); + +/* Focus states */ +border-color: var(--bl-focus-ring); +box-shadow: 0 0 0 2px var(--bl-focus-ring-muted); + +/* Semantic colors */ +color: var(--bl-accent); +background: var(--bl-success); +background: var(--bl-warning); +background: var(--bl-error); + +/* Spacing */ +padding: var(--bl-spacing-sm); +padding: var(--bl-spacing-md); +padding: var(--bl-spacing-lg); +padding: var(--bl-spacing-xl); + +/* Border radius */ +border-radius: var(--bl-radius-control); +border-radius: var(--bl-radius-md); +border-radius: var(--bl-radius-lg); + +/* Typography */ +font-size: var(--bl-text-sm); +font-size: var(--bl-text-base); +font-size: var(--bl-text-lg); +font-weight: var(--bl-font-medium); +font-weight: var(--bl-font-semibold); +``` + +### Component Token Patterns + +**Example: Badge Component** + +```typescript +// Using design tokens for badge styling +const badgeStyles = { + success: { + background: 'var(--bl-success-light)', + color: 'var(--bl-success-dark)', + borderColor: 'var(--bl-success)', + }, + warning: { + background: 'var(--bl-warning-light)', + color: 'var(--bl-warning-dark)', + borderColor: 'var(--bl-warning)', + }, + error: { + background: 'var(--bl-error-light)', + color: 'var(--bl-error-dark)', + borderColor: 'var(--bl-error)', + }, +}; +``` + +### Token Migration Checklist + +When migrating to design tokens: + +1. **Identify hardcoded colors** - Search for hex codes and named colors +2. **Map to semantic tokens** - Use semantic names (success, warning, error) not literal colors +3. **Replace with CSS variables** - Use `var(--bl-*)` syntax +4. **Test across themes** - Ensure tokens work in light/dark modes +5. **Audit for missed tokens** - Use `audit:ui` to find remaining hardcoded values + +--- + +## Part 3: Component Normalization + +### Badge Normalization + +**Before:** One-off CSS classes for different badge styles + +```css +/* Old approach - one-off classes */ +.stat-chip { + background: #f0f0f0; + padding: 4px 8px; + border-radius: 4px; + font-size: 12px; +} + +.saved-setup-id-chip { + background: #e0e0e0; + padding: 6px 12px; + border-radius: 6px; +} + +.health-pill { + background: #d0d0d0; + padding: 5px 10px; + border-radius: 20px; +} +``` + +**After:** Shared Badge component from product adapter + +```typescript +import { Badge, ProductStatusBadge } from '../components/ui/Primitives'; + +// Replace .stat-chip with Badge +Active + +// Replace .saved-setup-id-chip with Badge +Setup #123 + +// Replace .health-pill with ProductStatusBadge + +``` + +**Commit:** `94ce743` - refactor(ui): replace one-off visual language with shared Badge components + +### Alert Banner Unification + +**Before:** Different alert implementations across components + +```typescript +// HistoryTab.tsx - custom alert +
+ ⚠️ + Warning message +
+ +// PositionsTab.tsx - different alert +
+
!
+
Warning text
+
+``` + +**After:** Shared AlertBanner component + +```typescript +import { AlertBanner } from '../components/ui/Primitives'; + +// Both components now use shared AlertBanner + + Warning message + + + + Error message + +``` + +**Commit:** `d4846b7` - refactor(ui): unify operational alert banners + +### Table Controls Standardization + +**Before:** Custom table controls with inconsistent styling + +```typescript +// Different button styles across tables + + + +``` + +**After:** Standardized Button component + +```typescript +import { Button, IconButton } from '../components/ui/Primitives'; + +// Consistent button styles + + +} label="Run" /> +``` + +**Commits:** +- `3951767` - refactor(ui): standardize operations table badges +- `fd64fec` - refactor(ui): refine positions table controls +- `bfd7d3b` - refactor(ui): align history filters controls + +### Control Normalization Pattern + +**Step 1:** Identify one-off controls +```bash +# Search for custom CSS classes +grep -r "className.*chip" web/src/ +grep -r "className.*btn" web/src/ +grep -r "className.*pill" web/src/ +``` + +**Step 2:** Map to shared primitives +- Chips → Badge +- Custom buttons → Button +- Custom inputs → Input +- Custom selects → Select +- Custom alerts → AlertBanner + +**Step 3:** Replace component by component +```typescript +// Before +
Text
+ +// After +Text +``` + +**Step 4:** Remove old CSS +```css +/* Delete one-off CSS classes */ +.custom-chip { /* delete */ } +.custom-btn { /* delete */ } +``` + +**Step 5:** Verify with audit +```bash +pnpm run audit:ui ``` --- -## Step 1: Playwright Setup +## Part 4: Accessibility Improvements -### Install Dependencies +### Keyboard Navigation -```bash -cd web -pnpm add -D @playwright/test -pnpm exec playwright install chromium -``` - -### Create Playwright Config - -Create `web/playwright.config.ts`: +**Focus Management** ```typescript -import { defineConfig, devices } from '@playwright/test'; - -export default defineConfig({ - testDir: './e2e', - fullyParallel: true, - forbidOnly: !!process.env.CI, - retries: process.env.CI ? 2 : 0, - workers: process.env.CI ? 1 : undefined, - reporter: 'html', - use: { - baseURL: 'http://localhost:3050', - trace: 'on-first-retry', - screenshot: 'only-on-failure', - }, - projects: [ - { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, - }, - { - name: 'firefox', - use: { ...devices['Desktop Firefox'] }, - }, - { - name: 'webkit', - use: { ...devices['Desktop Safari'] }, - }, - { - name: 'Mobile Chrome', - use: { ...devices['Pixel 5'] }, - }, - { - name: 'Mobile Safari', - use: { ...devices['iPhone 12'] }, - }, - { - name: 'Desktop Chrome HiDPI', - use: { ...devices['Desktop Chrome HiDPI'] }, - }, - ], - // webServer is disabled - tests should run against already-running server - // Test runner script handles server lifecycle -}); +// Ensure interactive elements are focusable + ``` -### Add Test Scripts to package.json +**Keyboard Toggles** -```json -{ - "scripts": { - "test:e2e": "playwright test", - "test:e2e:ui": "playwright test --ui", - "test:e2e:viewport": "playwright test e2e/viewport-matrix.spec.ts", - "test:e2e:overflow": "playwright test e2e/horizontal-overflow.spec.ts" +```typescript +// Commit: a65d726 - test(ui): cover profile rule keyboard toggles +
{ + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + toggle(); + } + }} + aria-pressed={isActive} +> + Toggle Option +
+``` + +**Commit:** `3c52593` - fix(ui): improve profile rule keyboard access + +### ARIA Labels + +**Button Labels** + +```typescript +// Icon buttons need explicit labels +} + label="Edit item" + aria-label="Edit item" +/> +``` + +**Status Indicators** + +```typescript +// Status badges need descriptive labels + + Active + +``` + +**Form Labels** + +```typescript +// All inputs need associated labels + + Email + + Enter your email address + +``` + +### Focus Indicators + +**Visible Focus States** + +```css +/* Ensure focus is visible */ +*:focus-visible { + outline: 2px solid var(--bl-focus-ring); + outline-offset: 2px; +} + +/* Or use design token */ +*:focus-visible { + outline: 2px solid var(--bl-focus-ring); + box-shadow: 0 0 0 2px var(--bl-focus-ring-muted); +} +``` + +**Focus Order** + +```typescript +// Ensure logical tab order +
+ + + +
+ +// Use tabIndex to control order if needed + + +``` + +--- + +## Part 5: Responsive Design + +### Shell Breakpoints + +**Responsive Shell Testing** + +```typescript +// Commit: c51544a - test(ui): lock responsive shell breakpoints +const breakpoints = { + mobile: 'max-width: 560px', + tablet: 'max-width: 768px', + desktop: 'min-width: 769px', +}; + +// Shell adapts at these breakpoints +@media (max-width: 560px) { + .dashboard-main { + margin-left: 0; + } + .dashboard-right-panel { + display: none; + } + .trading-sidebar { + position: fixed; + bottom: 0; + width: 100%; + height: 60px; } } ``` ---- +### Viewport Matrix Testing -## Step 2: Create Test Suite Structure - -### Test Categories - -Create tests in `web/e2e/` directory following this structure: - -``` -web/e2e/ -├── viewport-matrix.spec.ts # Viewport compliance -├── horizontal-overflow.spec.ts # Overflow detection -├── alert-positioning.spec.ts # Critical alerts positioning -├── assistant-positioning.spec.ts # Assistant widget positioning -├── destructive-actions.spec.ts # Destructive actions confirmation -├── feedback.spec.ts # Save/delete/update feedback -├── page-states.spec.ts # Loading/empty/error/success states -├── form-validation.spec.ts # Form validation -└── keyboard-navigation.spec.ts # Keyboard navigation -``` - ---- - -## Step 3: Test Implementation Patterns - -### Viewport Matrix Test - -Tests that all routes pass viewport matrix for desktop, tablet, and mobile: +**Test all routes across viewports** ```typescript -import { test, expect } from '@playwright/test'; - +// Commit: 79f0021 - test(ui): add comprehensive Playwright E2E test suite const routes = ['/', '/portfolio', '/research', '/plans', '/markets']; const viewports = [ { name: 'Desktop', width: 1200, height: 800 }, @@ -175,133 +620,103 @@ routes.forEach((route) => { }); ``` -### Alert Positioning Test +### Mobile-First Patterns -Tests that critical alerts don't cover primary content: +**Responsive Components** ```typescript -import { test, expect } from '@playwright/test'; - -test.describe('Critical Alerts Positioning', () => { - test('AlertBanner does not cover primary content', async ({ page }) => { - await page.goto('/'); - - // Find alert banners - const alerts = page.locator('[role="alert"], .alert, [class*="alert"]'); - const alertCount = await alerts.count(); - - if (alertCount > 0) { - const alert = alerts.first(); - const alertBox = await alert.boundingBox(); - const mainContent = page.locator('main'); - const mainBox = await mainContent.boundingBox(); - - // Alert should be inline, not covering main content - expect(alertBox).toBeTruthy(); - } - }); - - test('AlertBanner has proper z-index', async ({ page }) => { - await page.goto('/'); - const alerts = page.locator('[role="alert"]'); - - if (await alerts.count() > 0) { - const zIndex = await alerts.first().evaluate((el) => { - return window.getComputedStyle(el).zIndex; - }); - expect(parseInt(zIndex)).toBeLessThan(1000); - } - }); -}); +// Use responsive design tokens +
+ Content +
``` -### Form Validation Test - -Tests that forms have labels, hints, validation, and disabled-state explanations: +**Conditional Rendering** ```typescript -import { test, expect } from '@playwright/test'; +// Show/hide based on viewport +const isMobile = useMediaQuery('(max-width: 560px)'); -test.describe('Form Validation', () => { - test('Forms have labels for inputs', async ({ page }) => { - await page.goto('/plans'); - - const inputs = page.locator('input, select, textarea'); - const inputCount = await inputs.count(); - - if (inputCount > 0) { - for (let i = 0; i < Math.min(inputCount, 10); i++) { - const input = inputs.nth(i); - const isVisible = await input.isVisible(); - - if (isVisible) { - const id = await input.getAttribute('id'); - let hasLabel = false; - - if (id) { - const label = page.locator(`label[for="${id}"]`); - hasLabel = await label.count() > 0; - } - - const ariaLabel = await input.getAttribute('aria-label'); - const ariaLabelledby = await input.getAttribute('aria-labelledby'); - const hasAriaLabel = ariaLabel !== null || ariaLabelledby !== null; - - expect(hasLabel || hasAriaLabel).toBeTruthy(); - } - } - } - }); -}); -``` - -### Keyboard Navigation Test - -Tests that primary workflows pass keyboard navigation: - -```typescript -import { test, expect } from '@playwright/test'; - -test.describe('Keyboard Navigation', () => { - test('Tab order is logical', async ({ page }) => { - await page.goto('/'); - - const focusableElements = await page.evaluate(() => { - const focusable = ['button', '[href]', 'input', 'select', 'textarea', '[tabindex]:not([tabindex="-1"])']; - return Array.from(document.querySelectorAll(focusable.join(','))) - .filter(el => { - const style = window.getComputedStyle(el); - return style.display !== 'none' && style.visibility !== 'hidden'; - }) - .length; - }); - - expect(focusableElements).toBeGreaterThan(0); - }); - - test('Enter and Space activate buttons', async ({ page }) => { - await page.goto('/'); - - const button = page.locator('button').first(); - const buttonCount = await button.count(); - - if (buttonCount > 0) { - await button.focus(); - await page.keyboard.press('Space'); - await page.waitForTimeout(500); - - const isVisible = await button.isVisible(); - expect(isVisible).toBeTruthy(); - } - }); -}); +{isMobile ? ( + +) : ( + +)} ``` --- -## Step 4: Test Runner Script +## Part 6: Testing Infrastructure -### Create Test Runner Script +### Playwright Setup + +**Install Dependencies** + +```bash +cd web +pnpm add -D @playwright/test +pnpm exec playwright install chromium +``` + +**Create Playwright Config** + +Create `web/playwright.config.ts`: + +```typescript +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + testDir: './e2e', + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + reporter: 'html', + use: { + baseURL: 'http://localhost:3050', + trace: 'on-first-retry', + screenshot: 'only-on-failure', + }, + projects: [ + { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, + { name: 'firefox', use: { ...devices['Desktop Firefox'] } }, + { name: 'webkit', use: { ...devices['Desktop Safari'] } }, + { name: 'Mobile Chrome', use: { ...devices['Pixel 5'] } }, + { name: 'Mobile Safari', use: { ...devices['iPhone 12'] } }, + { name: 'Desktop Chrome HiDPI', use: { ...devices['Desktop Chrome HiDPI'] } }, + ], +}); +``` + +**Commit:** `8db23bd` - test(ui): add Playwright and Storybook testing infrastructure + +### Test Suite Structure + +Create tests in `web/e2e/` directory: + +``` +web/e2e/ +├── viewport-matrix.spec.ts # Viewport compliance +├── horizontal-overflow.spec.ts # Overflow detection +├── alert-positioning.spec.ts # Critical alerts positioning +├── assistant-positioning.spec.ts # Assistant widget positioning +├── destructive-actions.spec.ts # Destructive actions confirmation +├── feedback.spec.ts # Save/delete/update feedback +├── page-states.spec.ts # Loading/empty/error/success states +├── form-validation.spec.ts # Form validation +└── keyboard-navigation.spec.ts # Keyboard navigation +``` + +**Commit:** `79f0021` - test(ui): add comprehensive Playwright E2E test suite + +### Test Runner Script Create `scripts/tests/run-e2e.sh` with server lifecycle management: @@ -333,7 +748,6 @@ kill_port() { local port=$1 local pid=$(lsof -ti:$port 2>/dev/null || echo "") if [ -n "$pid" ]; then - echo -e "${YELLOW}Killing process $pid on port $port...${NC}" kill -9 $pid 2>/dev/null || true sleep 2 fi @@ -343,41 +757,26 @@ kill_port() { wait_for_server() { local max_attempts=30 local attempt=0 - echo -e "${CYAN}Waiting for server to be ready on port $PORT...${NC}" - while [ $attempt -lt $max_attempts ]; do if curl -s http://localhost:$PORT > /dev/null 2>&1; then - echo -e "${GREEN}✅ Server is ready${NC}" return 0 fi attempt=$((attempt + 1)) - echo -e "${YELLOW}Attempt $attempt/$max_attempts...${NC}" sleep 2 done - - echo -e "${RED}❌ Server failed to start after $max_attempts attempts${NC}" return 1 } -# Kill existing server -echo -e "${YELLOW}🔍 Checking for existing server on port $PORT...${NC}" +# Kill existing server, start fresh, run tests, cleanup kill_port $PORT -echo -e "${GREEN}✓ Port $PORT is clear${NC}" - -# Start dev server -echo -e "${CYAN}🚀 Starting dev server...${NC}" pnpm dev --port $PORT --strict-port > "$REPORTS_DIR/server-$TIMESTAMP.log" 2>&1 & SERVER_PID=$! -# Wait for server if ! wait_for_server; then - echo -e "${RED}❌ Server failed to start${NC}" kill_port $PORT exit 1 fi -# Run tests -echo -e "${CYAN}🎭 Running E2E tests...${NC}" pnpm exec playwright test \ --reporter=json \ --reporter=list \ @@ -385,34 +784,26 @@ pnpm exec playwright test \ 2>&1 | tee "$REPORTS_DIR/test-output-$TIMESTAMP.log" TEST_EXIT_CODE=$? -# Cleanup -echo -e "${CYAN}🧹 Cleaning up...${NC}" kill $SERVER_PID 2>/dev/null || true kill_port $PORT -echo -e "${GREEN}✓ Server stopped${NC}" exit $TEST_EXIT_CODE ``` -### Make Script Executable +**Commits:** +- `a572293` - test(ui): enhance E2E test runner with AI-friendly detailed reports +- `df7c57e` - feat(test): add automatic server lifecycle management to run-e2e.sh +- `2bd38e1` - ui(test): enhance script output with visual formatting and colors -```bash -chmod +x scripts/tests/run-e2e.sh -``` - ---- - -## Step 5: AI-Friendly Report Generation - -### Report Structure +### AI-Friendly Report Generation The test runner generates three types of reports: -1. **JSON Report** (`test-report-{timestamp}.json`) - Full machine-readable data -2. **Markdown Report** (`test-report-{timestamp}.md`) - Human-readable summary -3. **AI Summary** (`summary-{timestamp}.json`) - Optimized for AI agents +1. **JSON Report** - Full machine-readable data +2. **Markdown Report** - Human-readable summary +3. **AI Summary** - Optimized for AI agents with actionable next steps -### AI Summary Format +**AI Summary Format:** ```json { @@ -437,195 +828,356 @@ The test runner generates three types of reports: } ``` -### Report README +### Storybook Setup -Create `scripts/tests/reports/README.md`: - -```markdown -# E2E Test Reports - -This directory contains detailed E2E test reports. - -## For AI Agents - -Parse `latest-summary.json` for automated action: +**Install Storybook** ```bash -cat scripts/tests/reports/latest-summary.json | jq .for_ai_agents.next_action +cd web +pnpm add -D @storybook/react @storybook/addon-essentials @storybook/addon-interactions ``` -## Running Tests +**Create Storybook Config** -```bash -./scripts/tests/run-e2e.sh +Create `web/.storybook/main.ts`: + +```typescript +import type { StorybookConfig } from '@storybook/react-vite'; + +const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + addons: [ + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], + framework: { + name: '@storybook/react-vite', + options: {}, + }, + docs: { + autodocs: 'tag', + }, +}; + +export default config; ``` -This will: -- Install dependencies if needed -- Kill existing server on port 3050 -- Start fresh dev server -- Run all E2E tests -- Generate reports -- Cleanup server -``` +**Commit:** `8db23bd` - test(ui): add Playwright and Storybook testing infrastructure --- -## Step 6: Common Platform UI Integration - -### Using Shared Components - -Import UI components from common platform: - -```typescript -import { AlertBanner, Button, Input, Select } from '../components/ui/Primitives'; -``` - -### Design Token Usage - -Use CSS variables from design tokens: - -```css -.my-component { - background: var(--bl-surface-card); - color: var(--bl-text-primary); - border-color: var(--bl-border); - padding: var(--bl-spacing-md); -} -``` - -### Product Adapter Pattern - -Create a product adapter to normalize imports: - -```typescript -// src/components/ui/Primitives.tsx -export { Button } from '@bytelyst/ui/Button'; -export { AlertBanner } from '@bytelyst/ui/AlertBanner'; -export { Input } from '@bytelyst/ui/Input'; -// ... other components -``` - ---- - -## Step 7: Cipher Design System Integration +## Part 7: Cipher Design System Integration ### Design Principles -Follow Cipher design system principles: +Follow Cipher design system principles for consistent UX across products: -1. **Visual Hierarchy** - Clear hierarchy with size, weight, and color -2. **Spacing** - Consistent spacing using design tokens -3. **Typography** - Use design token font sizes and weights -4. **Color** - Use semantic color tokens (success, warning, error) -5. **Accessibility** - WCAG AA compliance with proper contrast ratios +#### 1. Visual Hierarchy -### Implementation Example +**Size and Weight** + +```typescript +// Use design tokens for consistent hierarchy +

+ Primary Heading +

+

+ Secondary Heading +

+

+ Body text +

+``` + +#### 2. Spacing System + +**Consistent Spacing** + +```typescript +// Use design token spacing +
+ Content +
+ +
+ + +
+``` + +#### 3. Typography + +**Font Scales** + +```typescript +// Use design token font sizes +const textStyles = { + xs: 'var(--bl-text-xs)', + sm: 'var(--bl-text-sm)', + base: 'var(--bl-text-base)', + lg: 'var(--bl-text-lg)', + xl: 'var(--bl-text-xl)', + '2xl': 'var(--bl-text-2xl)', +}; + +

Body text

+``` + +#### 4. Color System + +**Semantic Colors** + +```typescript +// Use semantic color tokens, not literal colors +const statusColors = { + success: 'var(--bl-success)', + warning: 'var(--bl-warning)', + error: 'var(--bl-error)', + info: 'var(--bl-info)', +}; + +
Success message
+``` + +#### 5. Accessibility + +**WCAG AA Compliance** + +```typescript +// Ensure contrast ratios meet WCAG AA +// Design tokens already ensure compliance + +``` + +### Component Patterns + +#### Card Pattern ```typescript
- - Content with proper visual hierarchy - +

+ Card Title +

+

+ Card content +

``` ---- +#### Button Pattern -## Step 8: Roadmap Documentation +```typescript + -### Update Launch Readiness Checklist + -Document progress in `docs/inprogress/LAUNCH_READY_UI_UX_ROADMAP.md`: + +``` -```markdown -## Launch Readiness Checklist +#### Alert Pattern -- [x] No production route has accidental horizontal overflow -- [x] Critical alerts never cover primary content -- [x] Assistant widget never covers primary actions -- [x] All destructive actions require confirmation -- [x] All saves/deletes/updates produce feedback -- [x] All pages have loading/empty/error/success states -- [x] All forms have labels, hints, validation, and disabled-state explanations -- [x] All primary workflows pass keyboard navigation -- [x] All routes pass the viewport matrix -- [x] Playwright screenshots and accessibility checks run in CI +```typescript + + Info message + + + + Warning message + + + + Error message + ``` --- -## Step 9: Verification Commands +## Part 8: Implementation Roadmap -### Run All Tests +### Phase 1: Foundation Setup +**Week 1-2** +- [ ] Install common platform packages +- [ ] Create product adapter (`Primitives.tsx`) +- [ ] Set up design token integration +- [ ] Configure Playwright +- [ ] Configure Storybook + +**Verification:** +```bash +pnpm install @bytelyst/ui @bytelyst/design-tokens +pnpm run typecheck +pnpm run build +``` + +### Phase 2: Component Normalization + +**Week 3-4** +- [ ] Replace one-off badges with Badge component +- [ ] Replace custom buttons with Button component +- [ ] Replace custom alerts with AlertBanner component +- [ ] Replace custom inputs with Input component +- [ ] Remove old CSS classes + +**Commits Reference:** +- `94ce743` - Badge normalization +- `d4846b7` - Alert banner unification +- `3951767` - Table badges standardization +- Multiple control normalization commits + +**Verification:** +```bash +pnpm run audit:ui +# Should show 0 raw controls, 0 direct @bytelyst/ui imports +``` + +### Phase 3: Design Token Migration + +**Week 5-6** +- [ ] Identify hardcoded colors +- [ ] Map to semantic tokens +- [ ] Replace with CSS variables +- [ ] Test across themes +- [ ] Audit for missed tokens + +**Verification:** +```bash +# Search for hardcoded colors +grep -r "#[0-9a-fA-F]\{6\}" web/src/ +# Should return minimal results (semantic colors only) +``` + +### Phase 4: Accessibility Improvements + +**Week 7** +- [ ] Add keyboard navigation +- [ ] Add ARIA labels +- [ ] Improve focus indicators +- [ ] Test with screen readers + +**Commits Reference:** +- `3c52593` - Profile rule keyboard access +- `a65d726` - Profile rule keyboard toggles + +**Verification:** +```bash +# Run accessibility tests +pnpm exec playwright test e2e/keyboard-navigation.spec.ts +pnpm exec playwright test e2e/form-validation.spec.ts +``` + +### Phase 5: Responsive Design + +**Week 8** +- [ ] Test viewport matrix +- [ ] Fix horizontal overflow +- [ ] Optimize mobile layout +- [ ] Test breakpoints + +**Commits Reference:** +- `c51544a` - Responsive shell breakpoints +- `31d8932` - Stabilize responsive shell chrome + +**Verification:** +```bash +pnpm exec playwright test e2e/viewport-matrix.spec.ts +pnpm exec playwright test e2e/horizontal-overflow.spec.ts +``` + +### Phase 6: Testing Infrastructure + +**Week 9-10** +- [ ] Create E2E test suite +- [ ] Set up test runner script +- [ ] Configure AI-friendly reports +- [ ] Set up Storybook +- [ ] Integrate with CI + +**Commits Reference:** +- `8db23bd` - Playwright and Storybook setup +- `79f0021` - Comprehensive E2E test suite +- `a572293` - AI-friendly reports +- `df7c57e` - Test runner with server lifecycle + +**Verification:** ```bash ./scripts/tests/run-e2e.sh +# Should pass all tests and generate reports ``` -### Run Specific Test Suites +--- + +## Part 9: Verification Commands + +### UI Audit ```bash +# Check for raw controls and direct imports +pnpm run audit:ui + +# Strict audit (enforces token usage) +pnpm run audit:ui:strict +``` + +### Type Checking + +```bash +# Verify TypeScript types +pnpm run typecheck +``` + +### Build Verification + +```bash +# Ensure build succeeds +pnpm run build +``` + +### Test Execution + +```bash +# Run all E2E tests +./scripts/tests/run-e2e.sh + +# Run specific test suites cd web pnpm test:e2e:viewport pnpm test:e2e:overflow +pnpm test:e2e:ui ``` -### Check AI Summary +### Storybook ```bash -cat scripts/tests/reports/latest-summary.json | jq .for_ai_agents +# Start Storybook +cd web +pnpm storybook ``` --- -## Step 10: CI Integration (Optional) +## Part 10: Troubleshooting -### GitHub Actions Example +### Common Issues -```yaml -- name: Run E2E Tests - run: ./scripts/tests/run-e2e.sh - -- name: Upload Reports - uses: actions/upload-artifact@v3 - with: - name: e2e-test-reports - path: scripts/tests/reports/ -``` - ---- - -## Troubleshooting - -### Server Won't Start - -**Issue:** Port 3050 already in use - -**Solution:** -```bash -lsof -ti:3050 | xargs kill -9 -``` - -### Missing Dependencies - -**Issue:** Playwright or dependencies not installed - -**Solution:** -```bash -pnpm install -pnpm exec playwright install chromium -``` - -### Tests Fail on VM - -**Issue:** Missing dependencies on VM +**Issue: Playwright tests fail on VM** **Solution:** ```bash @@ -633,43 +1185,137 @@ cd web pnpm install ``` ---- +**Issue: Design tokens not working** -## Best Practices +**Solution:** +```bash +# Ensure design tokens package is installed +pnpm install @bytelyst/design-tokens -1. **Test Organization** - Group related tests in describe blocks -2. **Selectors** - Use stable selectors (data-test attributes when needed) -3. **Wait Strategies** - Use Playwright's auto-waiting features -4. **Screenshots** - Capture screenshots on failure for debugging -5. **Reports** - Review HTML reports for detailed timing and coverage -6. **Accessibility** - Include accessibility checks in tests -7. **Maintenance** - Update tests when UI changes +# Check CSS variable usage +grep -r "var(--bl-)" web/src/ +``` + +**Issue: Component imports failing** + +**Solution:** +```bash +# Ensure common platform is accessible +cd ../learning_ai_common_plat +pnpm build + +# In product repo +pnpm install +``` + +**Issue: Audit showing raw controls** + +**Solution:** +```bash +# Find raw controls +grep -r "className.*btn" web/src/ +grep -r "className.*chip" web/src/ + +# Replace with shared primitives +``` --- -## References +## Part 11: Best Practices + +### Component Development + +1. **Use shared primitives first** - Always check `@bytelyst/ui` before creating custom components +2. **Follow product adapter pattern** - Extend shared primitives via product adapter, not direct modification +3. **Use design tokens** - Never hardcode colors, spacing, or typography +4. **Test accessibility** - Include keyboard navigation and ARIA labels +5. **Test responsive** - Verify components work across viewports + +### Code Organization + +1. **Centralize imports** - Use `Primitives.tsx` for all UI component imports +2. **Group related components** - Organize by feature, not by component type +3. **Separate concerns** - Keep presentation logic separate from business logic +4. **Use TypeScript** - Leverage type safety for component props + +### Testing Strategy + +1. **Test critical paths** - Focus on user workflows +2. **Test across browsers** - Use Playwright's multi-browser support +3. **Test accessibility** - Include keyboard and screen reader tests +4. **Test responsive** - Verify viewport matrix compliance +5. **Use AI-friendly reports** - Enable automated analysis + +### Documentation + +1. **Document decisions** - Record why certain patterns were chosen +2. **Update roadmaps** - Keep launch readiness checklist current +3. **Share learnings** - Document patterns for other products +4. **Maintain guides** - Update this guide as patterns evolve + +--- + +## Part 12: References + +### Common Platform + +- **UI Package:** `@bytelyst/ui` - Shared UI components +- **Design Tokens:** `@bytelyst/design-tokens` - Design system tokens +- **Documentation:** Common platform documentation in `learning_ai_common_plat` + +### Cipher Design System + +- **Principles:** Visual hierarchy, spacing, typography, color, accessibility +- **Documentation:** Internal design system documentation +- **Reference:** https://www.usecipher.dev/ + +### Testing + +- **Playwright:** https://playwright.dev +- **Storybook:** https://storybook.js.org +- **Accessibility:** WCAG 2.1 AA guidelines + +### Project Documentation -- **Playwright Documentation:** https://playwright.dev -- **Common Platform UI:** `@bytelyst/ui` package -- **Design Tokens:** `@bytelyst/design-tokens` package -- **Cipher Design System:** Internal design system documentation - **Launch Readiness Roadmap:** `docs/inprogress/LAUNCH_READY_UI_UX_ROADMAP.md` +- **Production Grade UX:** `docs/completed/PRODUCTION_GRADE_UX_REMEDIATION_ROADMAP.md` +- **UI Migration Roadmap:** `docs/completed/UI_UX_PLATFORM_CORE_MIGRATION_ROADMAP.md` --- ## Summary -This guide provides a complete blueprint for setting up UX testing infrastructure across ByteLyst products. By following these steps, products can: +This comprehensive guide documents the complete UX implementation approach for the trading dashboard, covering: -1. Establish comprehensive E2E testing with Playwright -2. Leverage common platform UI packages and design tokens -3. Follow Cipher design system principles -4. Generate AI-friendly reports for automated analysis -5. Ensure consistent UX quality across all products +**Key Achievements (Last 2 Days):** +- 40+ commits focused on UX improvements +- Complete component normalization using shared primitives +- Comprehensive design token integration +- Accessibility improvements across the application +- Responsive design testing and fixes +- Full E2E testing infrastructure with Playwright +- Storybook setup for component development +- AI-friendly reporting for automated analysis -The approach prioritizes: -- **Automation** - Server lifecycle management in test runner -- **Visibility** - Rich, colorful console output -- **Actionability** - AI-friendly reports with next actions -- **Reusability** - Common platform integration -- **Maintainability** - Clear test organization and documentation +**Reproducible Patterns:** +1. **Product Adapter Pattern** - Centralized import point with type-safe extensions +2. **Component Normalization** - Replace one-off components with shared primitives +3. **Design Token Integration** - Use CSS variables for consistent styling +4. **Accessibility First** - Keyboard navigation, ARIA labels, focus management +5. **Responsive by Default** - Viewport matrix testing, mobile-first patterns +6. **Test-Driven UX** - E2E tests verify UX quality automatically + +**Implementation Roadmap:** +- 10-week phased approach from foundation to full testing +- Clear verification commands at each phase +- Commit references for specific patterns +- Troubleshooting guide for common issues + +**Benefits for Other Products:** +- Consistent UX across all ByteLyst products +- Reduced development time with shared primitives +- Improved accessibility and responsive design +- Automated testing ensures quality +- AI-friendly reports enable continuous improvement + +This guide enables other products to replicate the exact same UX implementation approach, leveraging common platform packages, design tokens, and Cipher design system principles.