# Appearance Prop Implementation Plan

## Current Status: NOT IMPLEMENTED

The `appearance` prop with `theme` and `variables` customization was documented but **never implemented** in the codebase.

### Documented API (Does NOT Work)

```tsx
<OnePayment
  appearance={{
    theme: 'light', // or 'dark'
    variables: {
      colorPrimary: '#6366f1',
      colorBackground: '#ffffff',
      colorText: '#1f2937',
      colorDanger: '#ef4444',
      fontFamily: 'Inter, sans-serif',
      borderRadius: '8px',
      spacingUnit: '4px',
    }
  }}
/>
```

### Current Props (Actually Exist)

| Prop | Type | Exists |
|------|------|--------|
| `config` | `SDKConfig` | ✅ |
| `adapters` | `Adapters` | ✅ |
| `amount` | `number` | ✅ |
| `currency` | `string` | ✅ |
| `orderId` | `string` | ✅ |
| `firstName` | `string` | ✅ |
| `lastName` | `string` | ✅ |
| `email` | `string` | ✅ |
| `excludePaymentMethods` | `string[]` | ✅ |
| `width` | `string` | ✅ |
| `maxWidth` | `string` | ✅ |
| `appearance` | `AppearanceOptions` | ❌ **NOT IMPLEMENTED** |

---

## Why This Was Missed

1. **Documentation-First Approach**: The API was designed/documented before implementation
2. **Scope Creep Prevention**: Core payment functionality was prioritized over theming
3. **Time Constraints**: Feature was deferred but documentation wasn't updated
4. **No Validation**: No automated check to verify documented features exist

---

## Implementation Plan

### Phase 1: Type Definitions (Core Package)

**File**: `packages/core/src/types/appearance.ts`

```typescript
/**
 * Theme mode for the payment element
 */
export type ThemeMode = 'light' | 'dark' | 'auto';

/**
 * CSS variable customizations
 */
export interface AppearanceVariables {
  /** Primary brand color (buttons, links, focus states) */
  colorPrimary?: string;

  /** Background color of the payment element */
  colorBackground?: string;

  /** Primary text color */
  colorText?: string;

  /** Secondary/muted text color */
  colorTextSecondary?: string;

  /** Error/danger state color */
  colorDanger?: string;

  /** Success state color */
  colorSuccess?: string;

  /** Warning state color */
  colorWarning?: string;

  /** Border color for inputs */
  colorBorder?: string;

  /** Border color on focus */
  colorBorderFocus?: string;

  /** Font family for all text */
  fontFamily?: string;

  /** Base font size */
  fontSize?: string;

  /** Border radius for inputs and cards */
  borderRadius?: string;

  /** Base spacing unit (multiplied for margins/padding) */
  spacingUnit?: string;

  /** Box shadow for cards/elevated elements */
  boxShadow?: string;
}

/**
 * Appearance configuration for the payment element
 */
export interface AppearanceOptions {
  /** Theme mode: 'light', 'dark', or 'auto' (follows system preference) */
  theme?: ThemeMode;

  /** CSS variable overrides */
  variables?: AppearanceVariables;

  /** Custom CSS rules (advanced) */
  rules?: Record<string, Record<string, string>>;
}
```

---

### Phase 2: Web Components Implementation

**File**: `packages/web-components/src/one-payment.ts`

#### 2.1 Add Property

```typescript
// Add to class properties
@property({ type: Object }) appearance?: AppearanceOptions;
```

#### 2.2 Add CSS Custom Properties (Default Values)

```css
:host {
  /* Theme Colors - Light Mode Defaults */
  --op-color-primary: #6366f1;
  --op-color-primary-hover: #4f46e5;
  --op-color-background: #ffffff;
  --op-color-surface: #f9fafb;
  --op-color-text: #1f2937;
  --op-color-text-secondary: #6b7280;
  --op-color-danger: #ef4444;
  --op-color-success: #10b981;
  --op-color-warning: #f59e0b;
  --op-color-border: #e5e7eb;
  --op-color-border-focus: #6366f1;

  /* Typography */
  --op-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --op-font-size: 16px;

  /* Spacing & Layout */
  --op-border-radius: 8px;
  --op-spacing-unit: 4px;
  --op-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* Dark Mode */
:host([data-theme="dark"]) {
  --op-color-background: #1f2937;
  --op-color-surface: #374151;
  --op-color-text: #f9fafb;
  --op-color-text-secondary: #9ca3af;
  --op-color-border: #4b5563;
}
```

#### 2.3 Apply Variables Method

```typescript
private applyAppearance(): void {
  if (!this.appearance) return;

  const { theme, variables } = this.appearance;

  // Apply theme
  if (theme) {
    if (theme === 'auto') {
      const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
      this.dataset.theme = prefersDark ? 'dark' : 'light';
    } else {
      this.dataset.theme = theme;
    }
  }

  // Apply CSS variables
  if (variables) {
    const varMap: Record<keyof AppearanceVariables, string> = {
      colorPrimary: '--op-color-primary',
      colorBackground: '--op-color-background',
      colorText: '--op-color-text',
      colorTextSecondary: '--op-color-text-secondary',
      colorDanger: '--op-color-danger',
      colorSuccess: '--op-color-success',
      colorWarning: '--op-color-warning',
      colorBorder: '--op-color-border',
      colorBorderFocus: '--op-color-border-focus',
      fontFamily: '--op-font-family',
      fontSize: '--op-font-size',
      borderRadius: '--op-border-radius',
      spacingUnit: '--op-spacing-unit',
      boxShadow: '--op-box-shadow',
    };

    for (const [key, cssVar] of Object.entries(varMap)) {
      const value = variables[key as keyof AppearanceVariables];
      if (value) {
        this.style.setProperty(cssVar, value);
      }
    }
  }
}
```

#### 2.4 Update Lifecycle

```typescript
override updated(changedProperties: Map<string, unknown>): void {
  super.updated(changedProperties);

  // Apply appearance when it changes
  if (changedProperties.has('appearance')) {
    this.applyAppearance();
  }

  // ... existing code
}

override firstUpdated(): void {
  this.applyAppearance();
  // ... existing code
}
```

#### 2.5 Update All CSS to Use Variables

Replace all hardcoded colors/values with CSS variables:

```css
/* Before */
.pay-button {
  background-color: #2a2327;
  color: #ffbe32;
  border-radius: 40px;
}

/* After */
.pay-button {
  background-color: var(--op-color-primary);
  color: var(--op-color-background);
  border-radius: var(--op-border-radius);
}
```

---

### Phase 3: Framework Wrapper Updates

#### 3.1 React (`packages/react/src/OnePayment.tsx`)

```typescript
export interface OnePaymentProps {
  // ... existing props
  appearance?: AppearanceOptions;
}
```

#### 3.2 Vue (`packages/vue/src/OnePayment.vue`)

```typescript
interface Props {
  // ... existing props
  appearance?: AppearanceOptions;
}
```

#### 3.3 Angular (`packages/angular/src/one-payment.component.ts`)

```typescript
@Input() appearance?: AppearanceOptions;
```

#### 3.4 React Native (`packages/react-native/src/components/OnePaymentView.tsx`)

```typescript
interface OnePaymentViewProps {
  // ... existing props
  appearance?: AppearanceOptions;
}

// Pass to WebView HTML template
const html = generatePaymentHTML({
  ...props,
  appearance: props.appearance,
});
```

Update `payment.html` template to apply appearance:

```javascript
// In initialization script
if (props.appearance) {
  const { theme, variables } = props.appearance;

  if (theme) {
    document.documentElement.setAttribute('data-theme',
      theme === 'auto'
        ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
        : theme
    );
  }

  if (variables) {
    const root = document.documentElement;
    if (variables.colorPrimary) root.style.setProperty('--op-color-primary', variables.colorPrimary);
    if (variables.colorBackground) root.style.setProperty('--op-color-background', variables.colorBackground);
    // ... etc
  }
}
```

---

### Phase 4: Testing

1. **Unit Tests**: Test appearance application logic
2. **Visual Tests**: Storybook stories for different themes
3. **Integration Tests**: Verify props flow through wrappers
4. **Cross-browser Tests**: CSS variable support

---

### Phase 5: Documentation

1. Update README files
2. Add Storybook examples
3. Create migration guide
4. Update API reference

---

## Files to Modify

| File | Changes |
|------|---------|
| `packages/core/src/types/appearance.ts` | **NEW** - Type definitions |
| `packages/core/src/types/index.ts` | Export appearance types |
| `packages/web-components/src/one-payment.ts` | Add property, CSS vars, apply method |
| `packages/react/src/OnePayment.tsx` | Add to props interface |
| `packages/vue/src/OnePayment.ts` | Add to props |
| `packages/angular/src/one-payment.component.ts` | Add Input |
| `packages/react-native/src/components/OnePaymentView.tsx` | Add prop, pass to template |
| `packages/react-native/src/templates/payment.html` | Apply appearance in JS |
| `packages/react-native/src/templates/payment-template.ts` | Add to PaymentProps |

---

## Estimated Effort

| Phase | Effort | Priority |
|-------|--------|----------|
| Phase 1: Type Definitions | 1 hour | High |
| Phase 2: Web Components | 4-6 hours | High |
| Phase 3: Framework Wrappers | 2-3 hours | High |
| Phase 4: Testing | 2-3 hours | Medium |
| Phase 5: Documentation | 1-2 hours | Medium |

**Total Estimated Time**: 10-15 hours

---

## CSS Variables Reference

| Variable | Default (Light) | Default (Dark) | Description |
|----------|-----------------|----------------|-------------|
| `--op-color-primary` | `#6366f1` | `#818cf8` | Primary brand color |
| `--op-color-primary-hover` | `#4f46e5` | `#6366f1` | Primary hover state |
| `--op-color-background` | `#ffffff` | `#1f2937` | Main background |
| `--op-color-surface` | `#f9fafb` | `#374151` | Card/surface background |
| `--op-color-text` | `#1f2937` | `#f9fafb` | Primary text |
| `--op-color-text-secondary` | `#6b7280` | `#9ca3af` | Secondary text |
| `--op-color-danger` | `#ef4444` | `#f87171` | Error states |
| `--op-color-success` | `#10b981` | `#34d399` | Success states |
| `--op-color-warning` | `#f59e0b` | `#fbbf24` | Warning states |
| `--op-color-border` | `#e5e7eb` | `#4b5563` | Input borders |
| `--op-color-border-focus` | `#6366f1` | `#818cf8` | Focus ring |
| `--op-font-family` | System fonts | System fonts | Typography |
| `--op-font-size` | `16px` | `16px` | Base font size |
| `--op-border-radius` | `8px` | `8px` | Corner radius |
| `--op-spacing-unit` | `4px` | `4px` | Base spacing |
| `--op-box-shadow` | `0 1px 3px rgba(0,0,0,0.1)` | `0 1px 3px rgba(0,0,0,0.3)` | Elevation |

---

## Usage Examples (After Implementation)

### Light Theme (Default)

```tsx
<OnePayment
  config={config}
  adapters={adapters}
  amount={5000}
  currency="USD"
  orderId="order-123"
  // ... other required props
/>
```

### Dark Theme

```tsx
<OnePayment
  appearance={{ theme: 'dark' }}
  // ... other props
/>
```

### Custom Brand Colors

```tsx
<OnePayment
  appearance={{
    theme: 'light',
    variables: {
      colorPrimary: '#6366f1',
      colorBackground: '#fafafa',
      borderRadius: '12px',
    }
  }}
  // ... other props
/>
```

### Auto Theme (System Preference)

```tsx
<OnePayment
  appearance={{ theme: 'auto' }}
  // ... other props
/>
```

---

*Document created: December 3, 2024*
*Status: PLANNING - Implementation not started*
