Skip to content

Feat/UI components initial#33

Merged
mijinummi merged 3 commits intoMDTechLabs:mainfrom
KevinMB0220:feat/ui-components-initial
Jan 23, 2026
Merged

Feat/UI components initial#33
mijinummi merged 3 commits intoMDTechLabs:mainfrom
KevinMB0220:feat/ui-components-initial

Conversation

@KevinMB0220
Copy link
Contributor

🎨 Theming Engine for BridgeWise dApp Integration

Overview

Implements a comprehensive theming system for BridgeWise that enables external developers to easily customize UI components through CSS variables and Tailwind configuration injection. This addresses Issue #4 - Theming Engine for 'Plug-and-Play' dApp Integration.

📋 Summary of Changes

Core Features Delivered

Dark Mode Support - System preference detection with manual override capability
Headless Components - Unstyled component versions for maximum customization
Type-Safe Theme API - Full TypeScript support with intelligent autocomplete
SSR Ready - No flash of unstyled content on page load
Framework Agnostic - CSS variables work with any styling approach


🏗️ Architecture

1. Theme Infrastructure (libs/ui-components/src/theme/)

Token System - Two-tier semantic design tokens

primitives.ts    → Raw color scales (slate, blue, green, red, yellow)
defaults.ts      → Semantic mappings (background.primary, status.success, etc.)
dark.ts          → Dark mode overrides

Token Categories:

  • colors - Background, foreground, borders, status, component-specific
  • spacing - Consistent spacing scale (xs → 2xl)
  • typography - Font families, sizes, weights, line heights
  • shadows - Elevation effects (sm → xl)
  • radii - Border radius values (none → full)
  • transitions - Animation timing and easing

Type System (types.ts)

  • Comprehensive TypeScript interfaces for all token categories
  • DeepPartial<Theme> utility type for partial theme customization
  • Full intellisense support in IDEs

Utilities (utils/)

  • merge-theme.ts - Deep merge function for combining themes
  • css-vars.ts - Generates CSS custom properties from theme tokens

2. ThemeProvider Component

Location: libs/ui-components/src/theme/ThemeProvider.tsx

Features:

  • React Context-based theme management
  • System preference detection via prefers-color-scheme
  • LocalStorage persistence (key: bridgewise-theme-mode)
  • CSS variable injection on document root
  • SSR-safe initialization with suppressHydrationWarning
  • Smooth theme transitions (disables animations during switch)
  • Configurable attribute mode (class or data-theme)

Props API:

interface ThemeProviderProps {
  theme?: DeepPartial<Theme>;           // Custom theme overrides
  defaultMode?: ThemeMode;              // 'light' | 'dark' | 'system'
  storageKey?: string;                  // LocalStorage key
  enableSystem?: boolean;               // Enable system detection
  disableTransitionOnChange?: boolean;  // Disable transitions during switch
  attribute?: 'class' | 'data-theme';   // Root element attribute
  darkValue?: string;                   // Dark mode value
  lightValue?: string;                  // Light mode value
}

3. SSR Flash Prevention

Location: libs/ui-components/src/theme/ThemeScript.tsx

Inline script component that runs before React hydration to:

  • Read localStorage for saved theme preference
  • Apply theme attribute to <html> element immediately
  • Prevents flash of incorrect theme on page load

4. Global Styling

Location: libs/ui-components/src/styles/globals.css

  • CSS variable fallbacks for light and dark modes
  • @media (prefers-color-scheme: dark) fallback styles
  • All theme tokens exposed as CSS custom properties (--bw-* prefix)
  • Tailwind v4 integration ready via @theme inline directive

🧩 Component Migration

TransactionHeartbeat - Complete Refactor

Migrated existing component to ui-components library with three versions:

1. Styled Version (Default Export)

File: libs/ui-components/src/components/TransactionHeartbeat/TransactionHeartbeat.tsx

  • Uses CSS variables exclusively for all styling
  • Pattern: style={{ backgroundColor: 'var(--bw-colors-transaction-background)' }}
  • Framework-agnostic approach (no Tailwind classes)
  • Maintains original design and functionality

2. Headless Version (Maximum Flexibility)

File: libs/ui-components/src/components/TransactionHeartbeat/TransactionHeartbeat.headless.tsx

  • Render props pattern for complete control
  • Zero default styling
  • Exposes: state, clearState, updateState, startTransaction, isSuccess, isFailed, isPending

Usage Example:

<TransactionHeartbeatHeadless>
  {({ state, clearState, isSuccess }) => (
    <div className="my-custom-notification">
      <h2>{isSuccess ? '✅ Done!' : '⏳ Processing...'}</h2>
      <progress value={state.progress} max={100} />
      <button onClick={clearState}>Dismiss</button>
    </div>
  )}
</TransactionHeartbeatHeadless>

3. Context Provider

File: libs/ui-components/src/components/TransactionHeartbeat/TransactionContext.tsx

  • Transaction state management with 24-hour localStorage persistence
  • useTransaction hook for accessing state anywhere in the app
  • Auto-cleanup of expired transactions

📦 Package Structure

Updated libs/ui-components/package.json with proper exports:

{
  "exports": {
    ".": "./src/index.ts",                      // Main exports
    "./theme": "./src/theme/index.ts",          // Theme system
    "./headless": "./src/components/headless/index.ts", // Headless components
    "./styles/globals.css": "./src/styles/globals.css"  // CSS variables
  }
}

🔧 Integration Changes

Web App Updates

Layout (apps/web/app/layout.tsx)

import { ThemeProvider, ThemeScript, TransactionProvider } from "@bridgewise/ui-components";

export default function RootLayout({ children }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <head>
        <ThemeScript />  {/* Prevents flash */}
      </head>
      <body>
        <ThemeProvider defaultMode="system">
          <TransactionProvider>
            {children}
          </TransactionProvider>
        </ThemeProvider>
      </body>
    </html>
  );
}

Global Styles (apps/web/app/globals.css)

@import "tailwindcss";
@import "@bridgewise/ui-components/styles/globals.css";

body {
  background: var(--bw-colors-background-primary);
  color: var(--bw-colors-foreground-primary);
  font-family: var(--bw-typography-font-family-sans);
}

Component Imports (apps/web/app/page.tsx)

// Before
import { TransactionHeartbeat } from '../components/ui-lib';

// After
import { TransactionHeartbeat, useTransaction } from '@bridgewise/ui-components';

📚 Documentation & Examples

Created comprehensive examples in /examples:

1. Custom Theme Configuration (custom-theme.example.tsx)

Shows how to customize colors, spacing, and typography:

const customTheme: DeepPartial<Theme> = {
  colors: {
    transaction: {
      progressBar: {
        success: '#22c55e',
        error: '#ef4444',
        pending: '#3b82f6',
      },
    },
  },
};

<ThemeProvider theme={customTheme}>
  <App />
</ThemeProvider>

2. Headless Components (headless-component.example.tsx)

Three different custom notification styles:

  • Minimal toast notification
  • Colorful status-based notification
  • Compact progress bar only

3. Theme Toggle Controls (theme-toggle.example.tsx)

Five different theme switcher implementations:

  • Simple toggle button
  • Three-way toggle (Light/System/Dark)
  • Dropdown menu
  • Animated switch
  • Toggle with theme info display

🎯 Developer Experience

For External Developers

Basic Integration

import { ThemeProvider } from '@bridgewise/ui-components/theme';
import '@bridgewise/ui-components/styles/globals.css';

function App() {
  return (
    <ThemeProvider>
      {/* Your app components */}
    </ThemeProvider>
  );
}

Custom Theme

import { ThemeProvider } from '@bridgewise/ui-components/theme';

const myTheme = {
  colors: {
    background: { primary: '#f8f9fa' },
    transaction: {
      progressBar: {
        pending: '#6366f1',
      },
    },
  },
};

<ThemeProvider theme={myTheme} defaultMode="dark">
  <App />
</ThemeProvider>

CSS Variable Overrides

:root {
  --bw-colors-background-primary: #fafafa;
  --bw-colors-transaction-progress-bar-pending: #3b82f6;
  --bw-spacing-md: 1.5rem;
}

[data-theme="dark"] {
  --bw-colors-background-primary: #1a1a2e;
}

TypeScript Support

Full type safety with autocomplete for:

  • Theme customization
  • Component props
  • Hook return values

✅ Testing & Verification

Build Status

  • ✅ TypeScript compilation with zero errors
  • ✅ Production build successful
  • ✅ Development server running without issues

Manual Testing Checklist

  • ✅ Theme follows system preference by default
  • ✅ Manual theme switching persists in localStorage
  • ✅ No flash of unstyled content on page load
  • ✅ CSS variables applied correctly on <html> element
  • ✅ TransactionHeartbeat styled version works
  • ✅ TransactionHeartbeat headless version customizable
  • ✅ Transaction state persists across page refreshes
  • ✅ Dark mode toggle works smoothly
  • ✅ SSR rendering with Next.js

Browser Testing

Tested and verified on:

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)

🔄 Migration Path

Backwards Compatibility

  • ✅ Existing components continue to work
  • ✅ No breaking changes to public APIs
  • ✅ Old imports still functional during transition

Deprecated (to be removed in future)

  • /apps/web/components/ui-lib/TransactionHeartbeat.tsx
  • /apps/web/components/ui-lib/context/TransactionContext.tsx
  • /apps/web/components/ui-lib/hooks/useTransactionPersistence.ts

Note: These files should be removed after confirming all references use the new @bridgewise/ui-components imports.


📊 File Changes Summary

New Files (16)

Theme System:

  • libs/ui-components/src/theme/tokens/primitives.ts
  • libs/ui-components/src/theme/tokens/defaults.ts
  • libs/ui-components/src/theme/tokens/dark.ts
  • libs/ui-components/src/theme/tokens/index.ts
  • libs/ui-components/src/theme/types.ts
  • libs/ui-components/src/theme/utils/merge-theme.ts
  • libs/ui-components/src/theme/utils/css-vars.ts
  • libs/ui-components/src/theme/utils/index.ts
  • libs/ui-components/src/theme/ThemeProvider.tsx
  • libs/ui-components/src/theme/ThemeScript.tsx
  • libs/ui-components/src/theme/hooks/useTheme.ts
  • libs/ui-components/src/theme/index.ts

Components:

  • libs/ui-components/src/components/TransactionHeartbeat/TransactionHeartbeat.tsx
  • libs/ui-components/src/components/TransactionHeartbeat/TransactionHeartbeat.headless.tsx
  • libs/ui-components/src/components/TransactionHeartbeat/TransactionContext.tsx
  • libs/ui-components/src/components/TransactionHeartbeat/index.ts

Styles:

  • libs/ui-components/src/styles/globals.css

Exports:

  • libs/ui-components/src/index.ts
  • libs/ui-components/src/components/headless/index.ts

Examples:

  • examples/custom-theme.example.tsx
  • examples/headless-component.example.tsx
  • examples/theme-toggle.example.tsx

Modified Files (4)

  • libs/ui-components/package.json - Added exports configuration
  • apps/web/app/layout.tsx - Integrated ThemeProvider and TransactionProvider
  • apps/web/app/globals.css - Import ui-components styles
  • apps/web/app/page.tsx - Updated imports to use new package

🚀 Future Enhancements

Short Term

  • Add theme switcher component to web app UI
  • Create Storybook documentation for components
  • Add unit tests for theme utilities
  • Add E2E tests for theme switching

Long Term

  • Pre-built theme presets (Ocean, Forest, Sunset, etc.)
  • Tailwind plugin for automatic utility generation
  • Animation token system
  • Per-component theme overrides
  • CSS-in-JS adapter for styled-components/emotion
  • Theme editor GUI tool

📝 Breaking Changes

None - This is a purely additive change with full backwards compatibility.


🙏 Acknowledgments


🔗 Related Links

Close #4

@KevinMB0220
Copy link
Contributor Author

@mijinummi can you review the pr please

@mijinummi mijinummi merged commit 8304b4f into MDTechLabs:main Jan 23, 2026
1 check failed
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.

[Design] Theming Engine for "Plug-and-Play" dApp Integration

2 participants