---
description: UI 框架使用规范和无障碍访问要求
globs: ["**/*.vue", "**/components/**/*"]
alwaysApply: false
---

# UI 框架使用规范

## 🧩 Shadcn Vue 组件规范

### 组件生成和使用
```bash
# ✅ 必须使用 CLI 工具生成组件
npx shadcn-vue@latest add button
npx shadcn-vue@latest add input
npx shadcn-vue@latest add dialog

# ❌ 禁止手动复制组件代码
```

### 组件正确使用示例
```vue
<template>
  <!-- ✅ 基础 Button 组件使用 -->
  <Button variant="default" size="md" @click="handleClick">
    点击按钮
  </Button>

  <!-- ✅ Button 变体 -->
  <Button variant="destructive">删除</Button>
  <Button variant="outline">取消</Button>
  <Button variant="ghost">重置</Button>

  <!-- ✅ Button 尺寸 -->
  <Button size="sm">小按钮</Button>
  <Button size="lg">大按钮</Button>
</template>

<script setup lang="ts">
import { Button } from "@/components/ui/button";

const handleClick = () => {
  console.log("按钮被点击");
};
</script>
```

## 🎯 Radix Vue 无障碍性规范

### asChild 属性使用
```vue
<template>
  <!-- ✅ 正确使用 asChild 属性 -->
  <DialogRoot>
    <DialogTrigger as-child>
      <button>打开对话框</button>
    </DialogTrigger>

    <DialogContent>
      <DialogHeader>
        <DialogTitle>用户确认</DialogTitle>
        <DialogDescription>
          您确定要执行此操作吗？
        </DialogDescription>
      </DialogHeader>

      <DialogFooter>
        <DialogClose as-child>
          <Button variant="outline">取消</Button>
        </DialogClose>

        <DialogClose as-child>
          <Button variant="default">确认</Button>
        </DialogClose>
      </DialogFooter>
    </DialogContent>
  </DialogRoot>
</template>
```

### ARIA 标签和可访问性
```vue
<template>
  <!-- ✅ 添加适当的 ARIA 标签 -->
  <button
    aria-label="删除用户"
    aria-describedby="delete-help"
    @click="handleDelete"
  >
    🗑️
  </button>

  <div id="delete-help" class="sr-only">
    点击此按钮将删除选中的用户
  </div>

  <!-- ✅ 表单标签关联 -->
  <div>
    <label for="userId">用户 ID</label>
    <input
      id="userId"
      aria-labelledby="userId"
      aria-describedby="userId-help"
      type="text"
    />
    <div id="userId-help">请输入有效的用户标识符</div>
  </div>

  <!-- ✅ 键盘导航支持 -->
  <div role="menu" aria-label="用户操作菜单">
    <button role="menuitem" tabindex="0">编辑</button>
    <button role="menuitem" tabindex="0">查看详情</button>
    <button role="menuitem" tabindex="0">删除</button>
  </div>

  <!-- ✅ 动态内容更新 -->
  <div role="alert" aria-live="assertive" :aria-label="operationStatus">
    {{ statusMessage }}
  </div>
</template>
```

## 🎨 Tailwind CSS 原子类规范

### 原子类使用最佳实践
```vue
<template>
  <!-- ✅ 使用原子类组合 -->
  <div
    class="flex flex-col items-center justify-center min-h-screen bg-gray-50"
  >
    <div class="w-full max-w-md p-6 bg-white rounded-lg shadow-lg">
      <h1 class="text-2xl font-bold text-gray-900 text-center mb-6">
        用户注册
      </h1>

      <form class="space-y-4">
        <div>
          <label class="block text-sm font-medium text-gray-700 mb-1">
            用户名
          </label>
          <input
            class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
            type="text"
          />
        </div>

        <button
          class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
          type="submit"
        >
          注册
        </button>
      </form>
    </div>
  </div>

  <!-- ❌ 避免冗长和重复的类名 -->
  <div class="flex flex-row items-center justify-between space-x-4 p-4 m-4">
    <!-- 过多的空间类可以简化为一个组件 -->
  </div>
</template>
```

## 🔧 VueUse 函数使用规范

### 正确导入和使用
```vue
<script setup lang="ts">
// ✅ 从 @vueuse/core 导入
import { useLocalStorage, useDebounce, useEventListener } from '@vueuse/core'
import { ref, computed } from 'vue'

// ✅ 符合条件的类型参数
const searchKeyword = ref<string>('')
const debouncedKeyword = useDebounce(searchKeyword, 500)

// ✅ 处理副作用和自动清理
useEventListener(
  window,
  'resize',
  (event) => {
    // 在组件拆卸时自动清理事件监听器
    handleResize(event)
  }
)

// ✅ localStorage 类型安全
const userPreferences = useLocalStorage<UserPreferences>(
  'user-preferences',
  {
    theme: 'light',
    language: 'zh-CN',
    notifications: true
  }
)
</script>
```