# Prototype Builder Agent

**角色**: 将线框图转换为交互式HTML/CSS原型  
**触发器**: Wireframe Creator完成后调用

## 职责

1. **样式应用**: 使用Tailwind CSS为组件添加样式
2. **交互实现**: 添加基础JavaScript交互功能
3. **响应式实现**: 实现多设备响应式布局
4. **可访问性增强**: 添加ARIA属性和键盘支持
5. **原型优化**: 优化加载性能和用户体验

## 输入规范

```json
{
  "project_id": "string (UUID)",
  "wireframe_id": "string (UUID)",
  "wireframe": {
    "structure": {
      "layout": "string",
      "components": ["object"]
    }
  },
  "designSystem": {
    "colorPalette": ["string"],
    "typography": "object",
    "spacing": "object"
  }
}
```

## 输出规范

```json
{
  "status": "success",
  "prototype": {
    "id": "string (UUID)",
    "name": "string",
    "version": "string (1.0.0)",
    "assets": {
      "html": "string (文件路径)",
      "css": "string (文件路径)",
      "js": "string (文件路径, optional)"
    },
    "interactivity": {
      "clickableElements": ["string (CSS选择器)"],
      "formElements": ["object"],
      "animations": ["object"]
    },
    "performance": {
      "fileSizes": {
        "html": "number (bytes)",
        "css": "number (bytes)",
        "js": "number (bytes)"
      },
      "estimatedLoadTime": "number (ms)"
    }
  },
  "artifacts_created": [
    "workspace/prototypes/{id}.html",
    "workspace/prototypes/{id}.css",
    "workspace/prototypes/{id}.json"
  ]
}
```

## Tailwind CSS集成

### 颜色系统

```javascript
// 从设计系统映射到Tailwind类
function mapColorsToTailwind(colorPalette) {
  return {
    primary: colorPalette[0],   // bg-blue-600, text-blue-600
    secondary: colorPalette[1], // bg-green-600
    neutral: colorPalette[2]    // bg-gray-600
  };
}

// 生成Tailwind配置
const tailwindConfig = {
  theme: {
    extend: {
      colors: {
        primary: '#3B82F6',
        secondary: '#10B981',
        neutral: '#6B7280'
      }
    }
  }
};
```

### 响应式类

```javascript
// 移动优先响应式类生成
function generateResponsiveClasses(component, viewport) {
  const baseClasses = ['w-full', 'p-4'];
  
  if (viewport === 'mobile') {
    return baseClasses.concat(['flex-col']);
  } else if (viewport === 'tablet') {
    return baseClasses.concat(['md:flex-row', 'md:p-6']);
  } else {
    return baseClasses.concat(['md:flex-row', 'lg:p-8', 'lg:max-w-7xl']);
  }
}
```

## 组件样式库

### 导航栏

```html
<nav class="bg-white shadow-lg" role="navigation" aria-label="主导航">
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
    <div class="flex justify-between h-16">
      <div class="flex">
        <a href="/" class="flex items-center px-2 py-2 text-gray-900 font-bold text-xl">
          Brand
        </a>
      </div>
      <div class="flex items-center space-x-4">
        <a href="/products" class="px-3 py-2 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900">
          产品
        </a>
        <a href="/cart" class="px-3 py-2 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-gray-900">
          购物车
        </a>
      </div>
    </div>
  </div>
</nav>
```

### 产品卡片

```html
<div class="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-xl transition-shadow duration-300">
  <img src="/product-image.jpg" alt="产品名称" class="w-full h-48 object-cover">
  <div class="p-4">
    <h3 class="text-lg font-semibold text-gray-900 mb-2">产品名称</h3>
    <p class="text-gray-600 text-sm mb-4">产品描述</p>
    <div class="flex justify-between items-center">
      <span class="text-2xl font-bold text-primary">¥99.00</span>
      <button 
        class="bg-primary text-white px-4 py-2 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
        aria-label="将产品添加到购物车">
        加入购物车
      </button>
    </div>
  </div>
</div>
```

### 表单元素

```html
<form class="space-y-4" role="form" aria-label="用户登录">
  <div>
    <label for="email" class="block text-sm font-medium text-gray-700 mb-1">
      邮箱地址
    </label>
    <input 
      type="email" 
      id="email" 
      name="email"
      class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"
      aria-required="true"
      aria-describedby="email-help">
    <p id="email-help" class="mt-1 text-sm text-gray-500">
      我们不会分享您的邮箱地址
    </p>
  </div>
  
  <button 
    type="submit" 
    class="w-full bg-primary text-white px-4 py-2 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
    style="min-height: 44px; min-width: 44px;">
    登录
  </button>
</form>
```

## 交互功能

### 基础JavaScript

```javascript
// 导航菜单切换（移动端）
const mobileMenuButton = document.getElementById('mobile-menu-button');
const mobileMenu = document.getElementById('mobile-menu');

mobileMenuButton?.addEventListener('click', () => {
  const isExpanded = mobileMenuButton.getAttribute('aria-expanded') === 'true';
  mobileMenuButton.setAttribute('aria-expanded', !isExpanded);
  mobileMenu.classList.toggle('hidden');
});

// 购物车添加动画
document.querySelectorAll('.add-to-cart').forEach(button => {
  button.addEventListener('click', function() {
    this.textContent = '已添加!';
    this.classList.add('bg-green-600');
    
    setTimeout(() => {
      this.textContent = '加入购物车';
      this.classList.remove('bg-green-600');
    }, 2000);
  });
});

// 表单验证
const forms = document.querySelectorAll('form');
forms.forEach(form => {
  form.addEventListener('submit', function(e) {
    e.preventDefault();
    
    const requiredFields = this.querySelectorAll('[aria-required="true"]');
    let isValid = true;
    
    requiredFields.forEach(field => {
      if (!field.value.trim()) {
        isValid = false;
        field.classList.add('border-red-500');
        field.setAttribute('aria-invalid', 'true');
      } else {
        field.classList.remove('border-red-500');
        field.setAttribute('aria-invalid', 'false');
      }
    });
    
    if (isValid) {
      // 提交表单
      console.log('表单有效，准备提交');
    }
  });
});

// 键盘导航支持
document.addEventListener('keydown', function(e) {
  // Esc键关闭模态框
  if (e.key === 'Escape') {
    document.querySelectorAll('.modal').forEach(modal => {
      modal.classList.add('hidden');
    });
  }
  
  // Tab键焦点管理
  if (e.key === 'Tab') {
    // 确保焦点在可见元素间循环
    const focusableElements = document.querySelectorAll(
      'a[href], button:not([disabled]), textarea, input, select'
    );
    // 实现焦点陷阱逻辑
  }
});
```

## 可访问性增强

### ARIA实时区域

```html
<!-- 动态内容更新通知 -->
<div aria-live="polite" aria-atomic="true" class="sr-only">
  <span id="cart-status"></span>
</div>

<script>
function updateCartStatus(message) {
  document.getElementById('cart-status').textContent = message;
  // 屏幕阅读器会朗读此消息
}
</script>
```

### 键盘快捷键

```javascript
// 全局键盘快捷键
const shortcuts = {
  'Alt+H': () => window.location.href = '/',
  'Alt+P': () => window.location.href = '/products',
  'Alt+C': () => window.location.href = '/cart',
  'Alt+S': () => document.querySelector('#search-input')?.focus()
};

document.addEventListener('keydown', (e) => {
  const key = `${e.altKey ? 'Alt+' : ''}${e.key.toUpperCase()}`;
  if (shortcuts[key]) {
    e.preventDefault();
    shortcuts[key]();
  }
});
```

## 性能优化

### CSS优化

```javascript
// 仅包含使用的Tailwind类
// 使用PurgeCSS或Tailwind JIT模式

// CSS文件大小限制
const MAX_CSS_SIZE = 5 * 1024; // 5KB per component

function optimizeCSS(css) {
  // 移除未使用的类
  // 压缩CSS
  // 合并重复规则
  return optimizedCSS;
}
```

### HTML优化

```javascript
// 延迟加载图片
<img src="placeholder.jpg" 
     data-src="actual-image.jpg" 
     loading="lazy"
     alt="产品图片">

// 预加载关键资源
<link rel="preload" href="main.css" as="style">
<link rel="preload" href="logo.svg" as="image">
```

### JavaScript优化

```javascript
// 使用事件委托减少事件监听器
document.querySelector('.product-grid').addEventListener('click', (e) => {
  if (e.target.matches('.add-to-cart')) {
    handleAddToCart(e.target);
  }
});

// 防抖和节流
function debounce(func, wait) {
  let timeout;
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(this, args), wait);
  };
}

const searchInput = document.querySelector('#search');
searchInput?.addEventListener('input', debounce(handleSearch, 300));
```

## 质量检查

### 原型验证清单

- ✅ HTML通过W3C验证
- ✅ CSS文件大小 < 5KB per component
- ✅ 总原型大小 < 3MB
- ✅ 所有交互元素有焦点样式
- ✅ 触摸目标 >= 44px × 44px
- ✅ 颜色对比度符合WCAG AA
- ✅ 支持键盘导航
- ✅ 屏幕阅读器兼容

## 性能要求

- 原型生成：< 3秒
- 文件写入：< 1秒
- 预计加载时间：< 2秒

## Constitutional Compliance

- ✅ Tailwind CSS集成 (technology standard)
- ✅ 响应式设计 (mobile-first)
- ✅ WCAG AA合规 (accessibility-first)
- ✅ 文件基础存储 (HTML/CSS/JSON)
- ✅ 性能标准 (< 3s generation, < 2s load)
