Skip to content

Conversation

@jhellerstein
Copy link
Contributor

🎨 Add Semantic Color Tokens, Dark Mode Support, and UI Scaling

This PR introduces semantic color tokens for edges, enhances dark mode support with runtime detection and theme-aware styling, and adds UI scaling capabilities for IDE integrations.

✨ Features

  1. Semantic Color Tokens for Edges

    • New color-token field in edge semantic mappings
    • Predefined tokens: default, muted, light, highlight-1/2/3, success, warning, danger
    • Runtime theme-aware mapping (different colors in light vs dark mode)
    • Backward compatible with legacy color field
  2. Enhanced Dark Mode Support

    • Automatic theme detection (VS Code, browser preference, computed luminance)
    • Theme-aware edge colors with better contrast in dark mode
    • Pure black safety override for readability
    • Runtime theme change listeners with proper cleanup
    • 100ms caching to optimize performance
  3. UI Scaling for IDE Integration

    • New uiScale prop (0.5-2.0 range with validation)
    • Scales panels while maintaining graph responsiveness
    • Recommended 0.85 for VS Code extensions
  4. Export Improvements

    • High-quality PNG export using html-to-image library
    • Proper React-based SaveDialog component (no memory leaks)
    • Better error handling and user feedback

🔧 Technical Improvements

  • Theme detection with caching and cache invalidation
  • Proper TypeScript types for theme interfaces
  • Development-mode warnings for debugging
  • Validation and constraints for uiScale prop
  • Extract shared button styles to constants
  • Replace DOM manipulation with React components

📚 Documentation

  • Updated JSON_FORMAT.md with color-token examples
  • New UI_SCALING.md guide for IDE integrations
  • Migration script: scripts/update-color-tokens.mjs

✅ Testing

  • All 1410 tests passing (13 skipped)
  • No lint errors
  • Successful builds
  • Backward compatibility verified

⚠️ Breaking Changes

Edge colors will appear different in dark mode (intentional improvement for better visibility and contrast).

📦 Dependencies

  • Added: html-to-image@1.11.13 (production)

Joe Hellerstein added 2 commits October 26, 2025 22:41
BREAKING CHANGE: Edge colors now use semantic tokens instead of hex values.
Legacy "color" field still supported for backward compatibility.

Features:
- Add semantic color token system for edges (default, muted, light, highlight-1/2/3, success, warning, danger)
- Implement theme-aware token mapping with automatic dark mode detection
- Add runtime edge color resolution based on current theme
- Increase dark mode edge contrast (brighter stroke colors for better visibility)
- Add dark mode safety override for legacy pure black colors
- Add UI scaling prop (uiScale) for IDE integrations (0.85 recommended)
- Add Save button to export visualization as PNG or JSON
- Add initialZoom prop to HydroscopeCore for custom initial zoom levels

Theme & Color Improvements:
- Enhanced detectDarkMode() with computed background luminance heuristic
- Added VS Code webview theme detection (.vscode-dark, .vscode-high-contrast)
- Brightened dark mode color palette for better contrast
- Updated dark default stroke colors (#cbd5e1, #e5e7eb)
- Added theme change listeners for dynamic updates
- Force light mode during tests for deterministic results

Visual Improvements:
- Add strokeWidth: 2 to all edge style mappings for consistency
- Update waviness to use "none"/"wavy" string values (backward compatible with boolean)
- Improve edge style validation with domain checking for all visual channels

Documentation:
- Add JSON_FORMAT.md documentation for color-token and theme-aware mappings
- Add UI_SCALING.md guide for IDE integrations
- Add migration script (scripts/update-color-tokens.mjs) for legacy JSONs
- Update examples with save functionality

Sample Data:
- Migrate paxos.json, paxos-flipped.json, paxos-old.json to use color-token
- Migrate simple_cluster.json to use color-token
- Add full backtrace data to simple_cluster nodes

CSS & Styling:
- Add comprehensive VS Code dark theme support in dark-mode.css
- Scale ReactFlow controls, minimap, and custom controls with uiScale
- Add pointer-events handling for scaled panel toggle buttons
- Improve dark mode specificity for all UI components

Architecture:
- StyleProcessor now uses getEdgeColorForToken(token, isDark) for runtime mapping
- Edge colors decoupled from node color palette changes
- Test-safe theme detection (no flakiness from environment differences)

Migration:
Legacy hex colors still work via fallback. To migrate:
  - Replace "color": "#2563eb" with "color-token": "highlight-1"
  - Replace "color": "#000000" with "color-token": "default"
  - Replace "color": "#6b7280" with "color-token": "muted"
  - Run: node scripts/update-color-tokens.mjs

Files Modified:
- src/components/Hydroscope.tsx
- src/components/HydroscopeCore.tsx
- src/shared/config/theme.ts
- src/shared/config/styling.ts
- src/utils/StyleProcessor.ts
- src/styles/dark-mode.css
- src/examples/hydroscope-example.tsx
- test-data/*.json (4 files)
- scripts/update-color-tokens.mjs (new)
- docs/UI_SCALING.md (new)
Addresses high-priority items from PR review:

1. PNG Export Implementation (Issue #1)
   - Replace fragile SVG serialization with html-to-image library
   - Add html-to-image@1.11.13 as production dependency
   - Properly handles CSS styles, fonts, and complex layouts
   - Uses 2x pixel ratio for better quality
   - Improved error handling with user-friendly messages

2. Memory Leak in Modal Creation (Issue #3)
   - Replace DOM manipulation with proper React component
   - New SaveDialog component with proper lifecycle management
   - Handles cleanup on unmount
   - Supports escape key and overlay click to close
   - No more dangling event listeners

3. Theme Detection Caching (Issue #2 partial)
   - Add 100ms cache to avoid repeated theme detection
   - Invalidate cache on actual theme changes
   - Reduces performance overhead

4. UI Scale Validation (Issue #7)
   - Add validation and constraints for uiScale prop
   - Clamp to range [0.5, 2.0]
   - Show warning in development when out of range

5. Error Handling Improvements (Issue #4)
   - Replace silent catches with console.warn in development
   - Better visibility of theme detection edge cases

6. Code Quality (Issue #8)
   - Extract CONTROL_BUTTON_STYLE constant to remove duplication
   - Cleaner button styling in CustomControls

7. TypeScript Strictness (Issue #10)
   - Replace (globalThis as any) with properly typed interface
   - Better type safety in theme detection

Changes:
- Add html-to-image production dependency
- Create SaveDialog component for export format selection
- Improve theme detection with caching and logging
- Add uiScale validation with warnings
- Better error handling throughout
- Code cleanup and type improvements

All tests passing (1410 passed | 13 skipped).
Builds successfully with no lint errors.
@jhellerstein jhellerstein requested a review from Copilot October 28, 2025 05:36
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces semantic color tokens for edges, comprehensive dark mode support with runtime theme detection, and UI scaling capabilities for IDE integrations. Key enhancements include theme-aware edge coloring, improved dark mode contrast, and a new high-quality PNG export feature with a React-based save dialog.

  • Semantic color tokens (color-token) for theme-aware edge styling with backward compatibility
  • Enhanced dark mode detection via VS Code classes, computed luminance, and browser preferences with 100ms caching
  • UI scaling prop (uiScale) for optimal panel sizing in IDE extensions

Reviewed Changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
test-data/simple_cluster.json Updated with additional stack frames and color-token mappings
test-data/paxos.json Migrated from hex colors to semantic tokens; updated backtrace arrow notation
test-data/paxos-old.json Applied color-token migration to legacy test data
test-data/paxos-flipped.json Applied color-token migration to flipped test data
src/utils/StyleProcessor.ts Added color-token support, dark mode color handling, and comprehensive validation
src/styles/dark-mode.css Added VS Code webview theme support with comprehensive dark mode rules
src/shared/config/theme.ts Enhanced theme detection with caching, VS Code support, and edge color token mapping
src/shared/config/styling.ts Added strokeWidth to legacy edge style mappings
src/examples/hydroscope-example.tsx Updated documentation comments for save functionality
src/components/SaveDialog.tsx New React component for format selection dialog
src/components/HydroscopeCore.tsx Added uiScale prop and removed test node count display
src/components/Hydroscope.tsx Integrated save functionality, UI scaling, and SaveDialog component
src/tests/StyleProcessor.test.ts Added test coverage for color-token mapping
scripts/update-color-tokens.mjs Migration script for converting hex colors to tokens
rollup.config.js Code formatting improvements
package.json Added html-to-image dependency
docs/UI_SCALING.md New documentation for UI scaling feature
docs/JSON_FORMAT.md Updated with color-token documentation
CHANGELOG.md Added unreleased save feature entries

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

1. Luminance Calculation Optimization
   - Extract luminance calculation into cached helper function
   - Avoid redundant RGB parsing and floating-point operations
   - Cache background color string to skip recalculation

2. Download URL Cleanup Safety
   - Increase timeout from 100ms to 1000ms for both PNG and JSON
   - More reliable on slower systems and network conditions
   - Better ensures download completes before URL revocation

3. CSS Duplication Elimination
   - Refactor dark-mode.css to use CSS custom properties
   - Eliminate 677 lines of duplicated code (81% reduction)
   - Single source of truth for dark mode colors
   - Reduced from 834 lines to 157 lines
   - Much easier to maintain going forward

4. Type Guard Simplification
   - Remove redundant GlobalWithProcess interface
   - Use optional chaining directly on globalThis.process
   - Cleaner and more concise code

All checks passing:
- TypeScript compilation ✓
- Linting (prod + tests) ✓
- Build ✓
- Tests: 1410 passed | 13 skipped ✓
@jhellerstein jhellerstein merged commit 806e285 into main Oct 28, 2025
2 checks passed
@jhellerstein jhellerstein deleted the feature/semantic-color-tokens branch October 28, 2025 05:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant