# Accessibility & Best Practices

## TYPESCRIPT INTERFACES (MANDATORY)

**ALWAYS define explicit TypeScript interfaces for component props.**

```typescript
// CORRECT - Explicit interface with all props typed
interface UserCardProps {
  user: User;
  onSelect?: (user: User) => void;
  isSelected?: boolean;
  variant?: 'default' | 'compact';
}

export const UserCard: React.FC<UserCardProps> = ({
  user,
  onSelect,
  isSelected = false,
  variant = 'default'
}) => {
  // ...
};

// WRONG - Missing interface, inline types, or any
export const UserCard = ({ user, onSelect }: any) => { ... }
export const UserCard = (props: { user: any }) => { ... }
```

### State Typing
```typescript
// CORRECT - Explicit state types
const [users, setUsers] = useState<User[]>([]);
const [selectedId, setSelectedId] = useState<string | null>(null);
const [status, setStatus] = useState<'idle' | 'loading' | 'error'>('idle');

// WRONG - Implicit or missing types
const [users, setUsers] = useState([]);
const [data, setData] = useState();
```

## SEMANTIC HTML (ACCESSIBILITY)

**ALWAYS use semantic HTML elements instead of divs with roles.**

```tsx
// CORRECT - Native button element
<button type="button" onClick={handleClick} disabled={isDisabled}>
  Click me
</button>

// WRONG - div with role (S6819)
<div role="button" onClick={handleClick} tabIndex={0}>
  Click me
</div>
```

### Interactive Elements Mapping

| Use Case | Correct Element | Wrong Pattern |
|----------|----------------|---------------|
| Clickable action | `<button type="button">` | `<div role="button">` |
| Navigation link | `<a href="...">` or `<Link>` | `<div onClick={navigate}>` |
| Form submission | `<button type="submit">` | `<div onClick={submit}>` |
| Expandable section | `<details><summary>` | `<div onClick={toggle}>` |
| List of items | `<ul><li>` with `<button>` inside | `<div role="listitem">` |

### Clickable Cards Pattern
```tsx
// CORRECT - Card with button inside
<div className="rounded-[var(--radius-card)] border ...">
  <div className="p-4">
    <h3>{title}</h3>
    <p>{description}</p>
  </div>
  <button
    type="button"
    onClick={() => onSelect(item)}
    className="w-full px-4 py-2 border-t ..."
  >
    Select
  </button>
</div>

// CORRECT - Entire card as link
<Link to={`/items/${item.id}`} className="block rounded-[var(--radius-card)] ...">
  <div className="p-4">...</div>
</Link>

// WRONG - div with click handler
<div onClick={() => onSelect(item)} className="cursor-pointer ...">
  ...
</div>
```

## PERFORMANCE OPTIMIZATION

### React.memo for Pure Components
```tsx
import { memo, useCallback, useMemo } from 'react';

// CORRECT - Memoized component for lists
export const UserCard = memo(({ user, onSelect }: UserCardProps) => {
  return (
    <div className="...">
      <h3>{user.name}</h3>
      <button onClick={() => onSelect(user)}>Select</button>
    </div>
  );
});
UserCard.displayName = 'UserCard';
```

### useCallback for Event Handlers
```tsx
// CORRECT - Stable callback reference
const handleSelect = useCallback((item: Item) => {
  onSelect?.(item);
  setSelectedId(item.id);
}, [onSelect]);

// WRONG - New function on every render
const handleSelect = (item: Item) => {
  onSelect?.(item);
};
```

### useMemo for Expensive Computations
```tsx
// CORRECT - Memoized filtered list
const filteredItems = useMemo(() =>
  items.filter(item => item.status === filter),
  [items, filter]
);

// WRONG - Recomputed on every render
const filteredItems = items.filter(item => item.status === filter);
```

## LIST RENDERING (UNIQUE KEYS)

**NEVER use array index as React key. ALWAYS use unique identifiers.**

```tsx
// CORRECT - Unique ID from data
{items.map(item => (
  <EntityCard key={item.id} {...mapToCardProps(item)} />
))}

// CORRECT - Composite key when needed
{items.map(item => (
  <Row key={`${item.tenantId}-${item.id}`} data={item} />
))}

// WRONG - Array index as key (S6479)
{items.map((item, index) => (
  <EntityCard key={index} {...mapToCardProps(item)} />
))}

// WRONG - Random key
{items.map(item => (
  <EntityCard key={Math.random()} {...mapToCardProps(item)} />
))}
```

### Why Index Keys Are Problematic
- Causes unnecessary re-renders when list order changes
- Breaks component state (inputs, animations)
- Causes visual glitches with drag-and-drop
- Makes reconciliation inefficient
