# Quick Reference: Component Props

> **For AI:** Bookmark this for instant lookup of critical props.

---

## 🚨 ICONS: MUST USE PASCALCASE (v2.0)

**CRITICAL:** Icon names changed in v2.0. Use PascalCase ONLY.

### Top 15 Icons (Memorize These):

| Icon | Name |
|------|------|
| 💳 | `CreditCard` |
| 📅 | `Calendar` |
| 💰 | `DollarSign` |
| 👤 | `User` |
| 👥 | `Users` |
| ℹ️ | `Info` |
| 🔒 | `Lock` |
| ⚠️ | `AlertTriangle` |
| ❌ | `XCircle` |
| ✅ | `CircleCheck` |
| 🔍 | `Search` |
| ⚙️ | `Settings` |
| 🏠 | `Home` |
| ➡️ | `ChevronRight` |
| ⋯ | `MoreHorizontal` |

**Full list:** See `docs/components/icons.md`

**Wrong:** `icon="credit-card"` (shows "?")
**Right:** `icon="CreditCard"` (works!)

---

## 🚨 Most Common Mistakes

### Mistake #1: Using wrong prop name for color/styling

| Component | Color Prop | Style Prop | Notes |
|-----------|-----------|------------|-------|
| **DAlert** | `color` | - | No variant/theme prop |
| **DBadge** | `color` | - | No variant/theme prop |
| **DButton** | `color` | `variant` | color = color, variant = style |
| **DIcon** | `theme` | - | Uses theme, not color |

```tsx
// ✅ CORRECT
<DAlert color="danger">Error</DAlert>
<DBadge text="Status" color="success" />
<DButton text="Save" color="primary" variant="outline" />
<DIcon icon="Check" theme="success" />

// ❌ WRONG
<DAlert variant="danger">Error</DAlert>      // No variant
<DBadge text="Status" theme="success" />     // No theme
<DButton text="Save" variant="primary" />    // variant is for style
<DIcon icon="Check" color="success" />    // Use theme
```

---

### Mistake #2: Text vs Children

| Component | Uses Text Prop | Uses Children | Notes |
|-----------|---------------|---------------|-------|
| **DButton** | ✅ `text` | ✅ `children` | ✨ NEW v2.0: Both supported (either/or) |
| **DBadge** | ✅ `text` | ❌ | Uses text prop only |
| **DAlert** | ❌ | ✅ `children` | Uses children only |
| **DCard** | ❌ | ✅ `children` | Uses children only |
| **DModal** | ❌ | ✅ `children` | Uses children only |

```tsx
// ✅ CORRECT
<DButton text="Click me" />
<DButton>Click me</DButton>               // ✨ NEW v2.0: children supported
<DButton color="primary">
  <DIcon icon="Check" /> Confirm          // Complex content
</DButton>
<DBadge text="New" />
<DAlert color="info">
  <p>Info message</p>
</DAlert>

// ❌ WRONG
<DBadge>New</DBadge>                     // Text won't show
<DAlert color="info" text="message" />   // No text prop
<DButton text="Save" pill />             // ⚠️ REMOVED: pill prop no longer exists
```

---

### Mistake #3: Handler Signatures

| Component | Handler Type | Example |
|-----------|-------------|---------|
| **All Dynamic UI Inputs** | `(value: T) => void` | `onChange={(value) => setValue(value)}` |
| **DSelect** | `(option: any) => void` | `onChange={(opt) => setValue(opt?.value)}` |
| **DTabs** | `(tab: DTabOption) => void` | `onChange={(tab) => setTab(tab)}` |
| **DDatePicker** | `(date: Date \| null) => void` | `onChange={(date) => setDate(date)}` |

```tsx
// ✅ CORRECT
<DInput
  value={text}
  onChange={(value) => setText(value)}  // value directly
/>

<DSelect
  value={options.find(o => o.value === selected)}
  onChange={(option) => setSelected(option?.value)}  // option object
/>

// ❌ WRONG
<DInput
  value={text}
  onChange={(e) => setText(e.target.value)}  // No e.target
/>

<DSelect
  value={selected}  // Wrong: needs option object
  onChange={(value) => setSelected(value)}  // Wrong signature
/>
```

---

### Mistake #4: Label Prop Names

| Component | Label Prop | Hint Prop | Notes |
|-----------|-----------|-----------|-------|
| **DInput** | `label` | `hint` | Standard naming |
| **DSelect** | `label` | - | Standard naming |
| **DDatePicker** | `inputLabel` | `inputHint` | Different! |

```tsx
// ✅ CORRECT
<DInput
  label="Name"
  hint="Enter your full name"
/>

<DDatePicker
  inputLabel="Birth Date"    // inputLabel, not label
  inputHint="Must be 18+"    // inputHint, not hint
/>

// ❌ WRONG
<DDatePicker
  label="Birth Date"    // Wrong prop name
  hint="Must be 18+"    // Wrong prop name
/>
```

---

### Mistake #5: Value Types

| Component | Value Type | Notes |
|-----------|-----------|-------|
| **DInput** | `string` | Simple string |
| **DInputCurrency** | `number` | Numeric value |
| **DSelect** | `{label, value}` | Full option object |
| **DDatePicker** | `Date \| null` | Date object (store as ISO string) |
| **DInputSwitch** | `boolean` | Uses checked prop |

```tsx
// ✅ CORRECT
<DInput value={text} />                    // string
<DInputCurrency value={amount} />          // number
<DSelect value={options.find(...)} />      // object
<DDatePicker selected={new Date(iso)} />   // Date
<DInputSwitch checked={enabled} />         // boolean

// ❌ WRONG
<DSelect value={selectedValue} />          // Wrong: needs object
<DDatePicker selected={isoString} />       // Wrong: needs Date
```

---

## 📋 Critical Patterns

### Pattern: DSelect Value Conversion

```tsx
// State stores string
const [selected, setSelected] = useState<string>('');

// Options array
const options = [
  { label: 'Option 1', value: '1' },
  { label: 'Option 2', value: '2' },
];

// Component
<DSelect
  options={options}
  value={options.find(opt => opt.value === selected)}  // String → Object
  onChange={(option: any) => setSelected(option?.value || '')}  // Object → String
/>
```

---

### Pattern: DDatePicker Value Conversion

```tsx
// State stores ISO string (serializable)
const [dateStr, setDateStr] = useState<string>('');

// Component
<DDatePicker
  selected={dateStr ? new Date(dateStr) : null}  // String → Date
  onChange={(date: Date | null) => {
    setDateStr(date ? date.toISOString().split('T')[0] : '');  // Date → String
  }}
/>
```

---

### Pattern: Modal Registration

```tsx
// 1. Create modal component
function MyModal() {
  const { closePortal } = useDPortalContext();
  return <DModal name="my-modal">...</DModal>;
}

// 2. Register in index.tsx
<DContextProvider
  availablePortals={{
    'my-modal': MyModal,  // Key matches portal name
  }}
>

// 3. Open from anywhere
function MyComponent() {
  const { openPortal } = useDPortalContext();

  const handleOpen = () => {
    openPortal('my-modal', {});  // 2 arguments required
  };
}
```

---

### Pattern: DStepper Step Mapping

```tsx
// State uses semantic names
type Step = 'personal' | 'address' | 'payment';
const [currentStep, setCurrentStep] = useState<Step>('personal');

// Create numeric mapping for DStepper
const stepMapping = {
  personal: 1,
  address: 2,
  payment: 3,
};

// Component
<DStepper
  options={[
    { label: 'Personal', value: 1 },
    { label: 'Address', value: 2 },
    { label: 'Payment', value: 3 },
  ]}
  currentStep={stepMapping[currentStep]}  // Convert to number
/>
```

---

### Pattern: Lucide Icons (PascalCase)

```tsx
// Dynamic UI 2.0 uses Lucide icons with PascalCase names
<DIcon icon="CheckCircle" size="24px" />
<DButton text="Add" iconStart="Plus" />

// Constants use the same PascalCase names
const ICONS = {
  success: 'CheckCircle',
  error: 'XCircle',
  add: 'Plus',
};

<DIcon icon={ICONS.success} />  // Renders CheckCircle icon
```

---

## 🔍 Component Finder

**I need...** → **Use this component** → **Read this file**

- Text input → `DInput` → `inputs.md`
- Dropdown → `DSelect` → `selects.md`
- Date picker → `DDatePicker` → `date-time.md`
- Button → `DButton` → `buttons.md`
- Modal → `DModal` + `useDPortalContext` → `modals.md` + `hooks.md`
- Alert → `DAlert` → `feedback.md`
- Badge/label → `DBadge` → `feedback.md`
- Icon → `DIcon` → `icons.md`
- Tabs → `DTabs` → `navigation.md`
- Wizard steps → `DStepper` → `navigation.md`
- Card → `DCard` → `layout.md`
- Spinner → Bootstrap HTML → `feedback.md`

---

## ⚠️ Components That DON'T Exist

Dynamic UI v2.0 does NOT have these components. Use alternatives instead:

| ❌ You Might Look For | ✅ Use Instead | Example | Notes |
|---------------------|---------------|---------|-------|
| `DInputSearch` | `DInput` with `iconStart="Search"` | `<DInput iconStart="Search" />` | Removed in v2.0 |
| `DContainer` | `DBox` with `.container` | `<DBox className="container">` | DBox is the wrapper |
| `DTable` | Native `<table>` + Bootstrap classes | `<table className="table table-hover">` | No table wrapper |
| `DForm` | Native `<form>` | `<form onSubmit={handleSubmit}>` | No form wrapper |
| `DGrid` | `DRow` + `DCol` or flexbox | `<DRow><DCol>...</DCol></DRow>` | Use Bootstrap grid |
| `DSpinner` | Bootstrap spinner HTML | `<div className="spinner-border" />` | No component wrapper |
| `DDropdown` | Native `<select>` or `DSelect` | `<DSelect options={items} />` | Use DSelect for custom styling |

### Pattern Examples

#### ❌ Wrong: Looking for DContainer

```tsx
import { DContainer } from '@dynamic-framework/ui-react';  // Doesn't exist

<DContainer>
  <h1>My Widget</h1>
</DContainer>
```

#### ✅ Correct: Use DBox with .container

```tsx
import { DBox } from '@dynamic-framework/ui-react';

<div className="bg-light min-vh-100 py-4">
  <DBox className="container">
    <h1>My Widget</h1>
  </DBox>
</div>
```

**Why:** DBox is the general-purpose wrapper. Add `.container` class for Bootstrap responsive width.

---

#### ❌ Wrong: Looking for DTable

```tsx
import { DTable } from '@dynamic-framework/ui-react';  // Doesn't exist

<DTable hover>
  <thead>
    <tr><th>Name</th></tr>
  </thead>
  <tbody>
    {/* rows */}
  </tbody>
</DTable>
```

#### ✅ Correct: Use Native Table with Bootstrap

```tsx
// No import needed - native HTML

<table className="table table-hover mb-0">
  <thead>
    <tr>
      <th>{t('table.name')}</th>
      <th>{t('table.value')}</th>
    </tr>
  </thead>
  <tbody>
    {data.map(item => (
      <tr key={item.id}>
        <td>{item.name}</td>
        <td>{item.value}</td>
      </tr>
    ))}
  </tbody>
</table>
```

**Why:** Dynamic UI v2.0 doesn't wrap tables. Use Bootstrap's excellent native table classes.

**Available Bootstrap Table Classes:**
- `.table` - Base table styling
- `.table-hover` - Hover effect on rows
- `.table-striped` - Alternating row colors
- `.table-bordered` - Borders around cells
- `.table-sm` - Compact padding

---

#### ❌ Wrong: Looking for DInputSearch

```tsx
import { DInputSearch } from '@dynamic-framework/ui-react';  // Removed in v2.0

<DInputSearch
  placeholder="Search..."
  onSearch={handleSearch}
/>
```

#### ✅ Correct: Use DInput with Search Icon

```tsx
import { DInput } from '@dynamic-framework/ui-react';

<DInput
  placeholder={t('search.placeholder')}
  value={searchQuery}
  onChange={(value) => setSearchQuery(value)}
  iconStart="Search"  // Note: String, not <DIcon />
/>
```

**Why:** DInputSearch was removed in v2.0. DInput with iconStart="Search" provides the same functionality.

---

### When to Use Component vs Bootstrap Class?

| Use Case | Solution | Reason |
|----------|----------|--------|
| Simple container | `<DBox>` | Provides theme context |
| Responsive container | `<DBox className="container">` | Combines component + Bootstrap |
| Table | `<table className="table">` | No wrapper needed |
| Form | `<form>` | Native HTML sufficient |
| Input | `<DInput>` | Use component for consistency |
| Button | `<DButton>` | Use component for theming |
| Card | `<DCard>` | Use component for structure |

**General Rule:** Use Dynamic UI components when they exist. Fall back to Bootstrap classes for layout/utilities.

---

**Last Updated:** October 2025
**Use this for:** Quick prop lookup during code generation
