# Theming Guide for Widget Development

## Overview

Dynamic UI uses CSS Custom Properties (design tokens) with the `--bs-` prefix. This guide covers how to analyze a design reference and create effective theme files.

### Architecture

```
src/
└── styles/
    ├── base.scss      # Widget customizations + imports theme
    └── theme.scss     # Brand variables (excluded from production build)
```

**Local development:** `base.scss` imports `theme.scss` → widget renders with client branding
**Production build:** `theme.scss` excluded via Vite build → widget uses site variables

---

## Quick Start

1. **Analyze the design** - Identify color hierarchy (CTAs vs titles vs links)
2. **Create theme.scss** - Set primary palette and any color overrides
3. **Add to base.scss** - Import theme + any CSS additions
4. **Test locally** - Verify visual match with design reference
5. **Iterate** - Adjust tokens based on visual comparison

---

## Analyzing a Design Reference

1. **Identify color hierarchy**: CTA buttons vs links vs titles. Common patterns: single-color, two-color (CTA differs from titles), traditional (bright CTAs + dark titles).

2. **Map to tokens**:

| Design observation | Token to configure |
|---|---|
| CTAs and links same color | `--bs-primary-rgb` only |
| CTAs cyan, links blue | Override `--bs-link-color-rgb` |
| Titles navy, CTAs bright | `--bs-heading-color` to secondary |
| Light CTA needs dark text | `--bs-btn-primary-color` |
| Monospace amounts | `font-monospace` class |
| Custom brand font | `--bs-font-sans-serif` |

---

## Token Reference

### Color Hierarchy

```scss
:root {
  --bs-primary-rgb: R, G, B;           // CTA/button color
  --bs-link-color-rgb: R, G, B;        // Link color (separate from primary if needed)
  --bs-link-hover-color-rgb: R, G, B;
  --bs-heading-color: var(--bs-secondary-700);  // Titles independent of primary
  --bs-btn-primary-color: var(--bs-secondary-700);  // Button text (for light primary)
  --bs-btn-primary-hover-color: var(--bs-secondary-800);
}
```

### Typography

`--bs-font-sans-serif` (default: `"Jost", sans-serif`), `--bs-font-monospace`, `--bs-body-font-size` (default: `1rem`). Use `font-monospace` class for amounts.

### Primary Palette

Always generate full palette (25-900) for consistent hover/active states. Format: `--bs-primary-{shade}-rgb: R, G, B;` where 500 = base, 600 = hover, 700 = active.

---

## Common Theming Patterns

**A: Brand for CTAs only** — Set `--bs-primary-rgb` (bright), override `--bs-link-color-rgb` (blue), `--bs-heading-color` (navy), `--bs-btn-primary-color` (dark text on light CTA).

**B: Single color** — Just set `--bs-primary-rgb` + generate full 25-900 palette.

**C: High contrast buttons** — Light primary (yellow/gold) + `--bs-btn-primary-color: var(--bs-gray-900)` for dark text.

---

## Button Variants for Visual Hierarchy

| Action | Approach |
|--------|----------|
| Primary CTA | `<DButton text="Invest" />` (default primary) |
| Secondary action | `bg-secondary` class or `variant="secondary"` |
| Subtle action | `variant="link"` |

---

## CSS Additions (base.scss)

For customizations beyond tokens:

```scss
// Select chevron color
.d-select__dropdown-indicator .d-icon { --bs-icon-color: var(--bs-info); }
// Monospace for amounts
.amount-value, [data-currency] { font-family: var(--bs-font-monospace); }
// Section title color
.section-title, .card-header h5 { color: var(--bs-secondary-700); }
```

---

## Complete Example: Two-Color Brand Theme

```scss
// theme.scss
:root {
  // Primary: Teal (CTAs) — generate full 25-900 palette
  --bs-primary-rgb: 34, 196, 196;
  --bs-primary-25-rgb: 243, 253, 253;
  // ... (50 through 400)
  --bs-primary-500-rgb: 34, 196, 196;  // = base
  --bs-primary-600-rgb: 27, 157, 157;  // hover
  --bs-primary-700-rgb: 20, 118, 118;  // active
  // ... (800, 900)

  // Secondary: Navy (titles) — same palette pattern
  --bs-secondary-rgb: 30, 58, 95;
  // ... (25 through 900)

  // Hierarchy overrides
  --bs-link-color-rgb: 32, 104, 213;
  --bs-link-hover-color-rgb: 26, 83, 170;
  --bs-heading-color: rgb(var(--bs-secondary-700-rgb));
  --bs-btn-primary-color: rgb(var(--bs-secondary-700-rgb));
  --bs-btn-primary-hover-color: rgb(var(--bs-secondary-800-rgb));
}
```

```scss
// base.scss
@import "theme";
@import "@dynamic-framework/ui-react/src/style/abstracts/+import";
// Widget-specific CSS overrides...
```

---

## Troubleshooting

### Colors not applying

1. Check `theme.scss` is imported in `base.scss`
2. Verify RGB format: `R, G, B` (not `rgb(R, G, B)`)
3. Check CSS specificity in DevTools

### Button text contrast wrong

Generate full palette (25-900) or override `--bs-btn-primary-color` directly.

### Links still using primary color

Ensure you override both:
- `--bs-link-color-rgb`
- `--bs-link-hover-color-rgb`

### Headings not changing color

Use `rgb()` wrapper if needed:
```scss
--bs-heading-color: rgb(var(--bs-secondary-700-rgb));
```

---

## Token Quick Reference

| Need | Token |
|------|-------|
| CTA/button color | `--bs-primary-rgb` |
| Link color | `--bs-link-color-rgb` |
| Title/heading color | `--bs-heading-color` |
| Button text color | `--bs-btn-primary-color` |
| Body text | `--bs-body-color-rgb` |
| Background | `--bs-body-bg-rgb` |
| Border radius | `--bs-border-radius` |
| Font family | `--bs-font-sans-serif` |
| Monospace | `font-monospace` class |

---

## Primary Color Usage

**Use for:** buttons, selected items (`active`), active tabs/steps, links, accent icons on neutral backgrounds.

**Do NOT use for:** card headers (looks clickable), banners (competes with actions), multiple elements (confuses hierarchy), static elements (implies interactivity).

> **Rule:** "If it's not clickable or selected, don't use `bg-primary`."

```tsx
// ❌ bg-primary on static card — looks selectable
<DCard className="bg-primary text-white"><DCard.Body><h2>Balance</h2></DCard.Body></DCard>

// ✅ Neutral background + primary accent icon
<DCard><DCard.Body>
  <DIcon icon="Wallet" color="primary" hasCircle size="2rem" />
  <p className="h1 mb-0">$3.300.000</p>
</DCard.Body></DCard>
```

---

## Limitations

These require CSS additions (not just tokens):

| Element | Limitation | Workaround |
|---------|------------|------------|
| Select chevron | SVG hardcoded to gray | CSS override on `.d-icon` |
| Specific element fonts | No per-element token | CSS class or rule |
| Component-specific titles | Use generic heading color | CSS targeting |

---

**Last Updated:** December 5, 2025
