# Tag 标签组件

一个灵活的标签组件，用于标注、分类和状态指示。支持多种变体、颜色主题、可移除功能和尺寸选项。非常适合显示分类、过滤器、用户选择和状态指示器。

## 安装

```bash
npm install @ticatec/uniface-element
```

## 导入

```typescript
import Tag from "@ticatec/uniface-element/Tag";
```

## 基本用法

```svelte
<script>
  import Tag from "@ticatec/uniface-element/Tag";
  
  function handleRemove() {
    console.log('标签已移除');
  }
</script>

<Tag text="基本标签" />
<Tag text="可移除标签" removable={true} removeHandler={handleRemove} />
<Tag text="不可移除标签" removable={false} />
```

## 属性

| 属性 | 类型 | 默认值 | 描述 |
|------|------|---------|-------------|
| `text` | `string` | `""` | 标签的文本内容 |
| `size` | `"big" \| "middle" \| "small"` | `"middle"` | 标签尺寸 |
| `variant` | `"borderless" \| "border" \| "round"` | `"border"` | 标签的视觉变体 |
| `removable` | `boolean` | `true` | 标签是否可移除 |
| `removeHandler` | `MouseClickHandler` | `null` | 点击移除图标时的回调函数 |
| `color` | `string` | `null` | 颜色主题（1-12） |
| `style` | `string` | `""` | 附加 CSS 样式 |
| `class` | `string` | `""` | CSS 类名 |

## 示例

### 基本标签

```svelte
<script>
  import Tag from "@ticatec/uniface-element/Tag";
</script>

<div class="tag-demo">
  <h3>基本标签</h3>
  <div class="tag-group">
    <Tag text="默认" />
    <Tag text="技术" />
    <Tag text="设计" />
    <Tag text="开发" />
  </div>
</div>

<style>
  .tag-demo {
    margin: 20px;
  }
  
  .tag-group {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
  }
</style>
```

### 不同尺寸

```svelte
<script>
  import Tag from "@ticatec/uniface-element/Tag";
</script>

<div class="size-demo">
  <h3>标签尺寸</h3>
  
  <div class="size-section">
    <h4>小标签</h4>
    <div class="tag-group">
      <Tag text="小标签" size="small" />
      <Tag text="分类" size="small" color="1" />
      <Tag text="标签" size="small" color="2" />
    </div>
  </div>
  
  <div class="size-section">
    <h4>中等标签（默认）</h4>
    <div class="tag-group">
      <Tag text="中等标签" size="middle" />
      <Tag text="分类" size="middle" color="1" />
      <Tag text="标签" size="middle" color="2" />
    </div>
  </div>
  
  <div class="size-section">
    <h4>大标签</h4>
    <div class="tag-group">
      <Tag text="大标签" size="big" />
      <Tag text="分类" size="big" color="1" />
      <Tag text="标签" size="big" color="2" />
    </div>
  </div>
</div>

<style>
  .size-demo {
    margin: 20px;
  }
  
  .size-section {
    margin-bottom: 20px;
  }
  
  .size-section h4 {
    margin: 12px 0 8px 0;
    font-size: 14px;
    color: #666;
  }
  
  .tag-group {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    align-items: center;
  }
</style>
```

### 不同变体

```svelte
<script>
  import Tag from "@ticatec/uniface-element/Tag";
</script>

<div class="variant-demo">
  <h3>标签变体</h3>
  
  <div class="variant-section">
    <h4>边框变体（默认）</h4>
    <div class="tag-group">
      <Tag text="边框标签" variant="border" />
      <Tag text="JavaScript" variant="border" color="1" />
      <Tag text="React" variant="border" color="2" />
      <Tag text="Vue" variant="border" color="3" />
    </div>
  </div>
  
  <div class="variant-section">
    <h4>圆形变体</h4>
    <div class="tag-group">
      <Tag text="圆形标签" variant="round" />
      <Tag text="JavaScript" variant="round" color="1" />
      <Tag text="React" variant="round" color="2" />
      <Tag text="Vue" variant="round" color="3" />
    </div>
  </div>
  
  <div class="variant-section">
    <h4>无边框变体</h4>
    <div class="tag-group">
      <Tag text="无边框标签" variant="borderless" />
      <Tag text="JavaScript" variant="borderless" color="1" />
      <Tag text="React" variant="borderless" color="2" />
      <Tag text="Vue" variant="borderless" color="3" />
    </div>
  </div>
</div>

<style>
  .variant-demo {
    margin: 20px;
  }
  
  .variant-section {
    margin-bottom: 20px;
  }
  
  .variant-section h4 {
    margin: 12px 0 8px 0;
    font-size: 14px;
    color: #666;
  }
  
  .tag-group {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
  }
</style>
```

### 颜色主题

```svelte
<script>
  import Tag from "@ticatec/uniface-element/Tag";
  
  const colorThemes = [
    { color: "1", name: "蓝色", description: "主要操作" },
    { color: "2", name: "绿色", description: "成功状态" },
    { color: "3", name: "红色", description: "错误状态" },
    { color: "4", name: "黄色", description: "警告状态" },
    { color: "5", name: "粉色", description: "高亮显示" },
    { color: "6", name: "青色", description: "信息提示" },
    { color: "7", name: "橙色", description: "警报" },
    { color: "8", name: "琥珀色", description: "待处理状态" },
    { color: "9", name: "靛蓝", description: "导航" },
    { color: "10", name: "紫色", description: "创意内容" },
    { color: "11", name: "酸橙色", description: "新鲜内容" },
    { color: "12", name: "灰色", description: "中性状态" }
  ];
</script>

<div class="color-demo">
  <h3>颜色主题</h3>
  
  <div class="color-grid">
    {#each colorThemes as theme}
      <div class="color-item">
        <Tag text={theme.name} color={theme.color} />
        <p class="color-description">{theme.description}</p>
      </div>
    {/each}
  </div>
  
  <h4>所有变体与颜色结合</h4>
  <div class="variant-comparison">
    <div class="variant-row">
      <span class="variant-label">边框：</span>
      <Tag text="技术" variant="border" color="1" />
      <Tag text="设计" variant="border" color="2" />
      <Tag text="市场营销" variant="border" color="3" />
    </div>
    
    <div class="variant-row">
      <span class="variant-label">圆形：</span>
      <Tag text="技术" variant="round" color="1" />
      <Tag text="设计" variant="round" color="2" />
      <Tag text="市场营销" variant="round" color="3" />
    </div>
    
    <div class="variant-row">
      <span class="variant-label">无边框：</span>
      <Tag text="技术" variant="borderless" color="1" />
      <Tag text="设计" variant="borderless" color="2" />
      <Tag text="市场营销" variant="borderless" color="3" />
    </div>
  </div>
</div>

<style>
  .color-demo {
    margin: 20px;
  }
  
  .color-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 16px;
    margin-bottom: 24px;
  }
  
  .color-item {
    text-align: center;
  }
  
  .color-description {
    margin: 8px 0 0 0;
    font-size: 12px;
    color: #666;
  }
  
  .variant-comparison h4 {
    margin: 20px 0 12px 0;
  }
  
  .variant-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 8px 0;
  }
  
  .variant-label {
    min-width: 80px;
    font-size: 14px;
    color: #666;
  }
</style>
```

### 可移除标签

```svelte
<script>
  import Tag from "@ticatec/uniface-element/Tag";
  
  let tags = [
    { id: 1, text: "JavaScript", color: "1" },
    { id: 2, text: "React", color: "2" },
    { id: 3, text: "Vue.js", color: "3" },
    { id: 4, text: "Angular", color: "4" },
    { id: 5, text: "Svelte", color: "5" }
  ];
  
  function removeTag(tagId) {
    tags = tags.filter(tag => tag.id !== tagId);
  }
  
  function addTag() {
    const newTagText = prompt("请输入标签名称：");
    if (newTagText) {
      const newTag = {
        id: Date.now(),
        text: newTagText,
        color: String(Math.floor(Math.random() * 12) + 1)
      };
      tags = [...tags, newTag];
    }
  }
</script>

<div class="removable-demo">
  <h3>可移除标签</h3>
  <p>将鼠标悬停在标签上以查看移除图标</p>
  
  <div class="tag-container">
    {#each tags as tag}
      <Tag 
        text={tag.text} 
        color={tag.color}
        removable={true}
        removeHandler={() => removeTag(tag.id)}
      />
    {/each}
    
    <button class="add-tag-btn" on:click={addTag}>+ 添加标签</button>
  </div>
  
  <div class="tag-count">
    标签总数：{tags.length}
  </div>
</div>

<style>
  .removable-demo {
    margin: 20px;
    max-width: 600px;
  }
  
  .removable-demo p {
    margin: 8px 0 16px 0;
    color: #666;
    font-size: 14px;
  }
  
  .tag-container {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    align-items: center;
    margin-bottom: 16px;
  }
  
  .add-tag-btn {
    padding: 4px 12px;
    border: 2px dashed #ccc;
    background: transparent;
    border-radius: 4px;
    cursor: pointer;
    font-size: 12px;
    color: #666;
    line-height: 20px;
  }
  
  .add-tag-btn:hover {
    border-color: #007bff;
    color: #007bff;
  }
  
  .tag-count {
    font-size: 14px;
    color: #666;
  }
</style>
```

### 状态标签

```svelte
<script>
  import Tag from "@ticatec/uniface-element/Tag";
  
  const statusItems = [
    { name: "活跃用户", status: "在线", color: "2", count: 1240 },
    { name: "待处理订单", status: "待处理", color: "4", count: 45 },
    { name: "失败请求", status: "错误", color: "3", count: 12 },
    { name: "已完成任务", status: "成功", color: "2", count: 89 },
    { name: "审核中", status: "审核", color: "1", count: 23 },
    { name: "草稿文章", status: "草稿", color: "12", count: 7 }
  ];
</script>

<div class="status-demo">
  <h3>状态指示器</h3>
  
  <div class="status-grid">
    {#each statusItems as item}
      <div class="status-item">
        <div class="status-header">
          <span class="status-name">{item.name}</span>
          <Tag text={item.status} color={item.color} size="small" variant="round" removable={false} />
        </div>
        <div class="status-count">{item.count}</div>
      </div>
    {/each}
  </div>
</div>

<style>
  .status-demo {
    margin: 20px;
  }
  
  .status-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 16px;
  }
  
  .status-item {
    padding: 16px;
    border: 1px solid #eee;
    border-radius: 8px;
    background: #fafafa;
  }
  
  .status-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
  }
  
  .status-name {
    font-size: 14px;
    color: #333;
  }
  
  .status-count {
    font-size: 24px;
    font-weight: bold;
    color: #333;
  }
</style>
```

### 标签输入组件

```svelte
<script>
  import Tag from "@ticatec/uniface-element/Tag";
  
  let inputTags = ["前端", "javascript"];
  let inputValue = "";
  
  function addTag(event) {
    if (event.key === 'Enter' && inputValue.trim()) {
      const newTag = inputValue.trim().toLowerCase();
      if (!inputTags.includes(newTag)) {
        inputTags = [...inputTags, newTag];
      }
      inputValue = "";
    }
  }
  
  function removeInputTag(tagToRemove) {
    inputTags = inputTags.filter(tag => tag !== tagToRemove);
  }
  
  function clearAllTags() {
    inputTags = [];
  }
</script>

<div class="tag-input-demo">
  <h3>标签输入组件</h3>
  
  <div class="tag-input-container">
    <label for="tag-input">技能：</label>
    <div class="input-wrapper">
      <div class="tag-display">
        {#each inputTags as tag, index}
          <Tag 
            text={tag} 
            color={String((index % 12) + 1)}
            size="small"
            variant="round"
            removable={true}
            removeHandler={() => removeInputTag(tag)}
          />
        {/each}
        
        <input
          id="tag-input"
          type="text"
          bind:value={inputValue}
          on:keydown={addTag}
          placeholder={inputTags.length === 0 ? "输入后按回车添加标签" : "添加更多..."}
          class="tag-input"
        />
      </div>
      
      <div class="input-actions">
        <button on:click={clearAllTags} disabled={inputTags.length === 0}>
          清除所有
        </button>
      </div>
    </div>
    
    <div class="tag-suggestions">
      <span class="suggestions-label">建议：</span>
      {#each ["react", "vue", "angular", "svelte", "typescript"] as suggestion}
        <button 
          class="suggestion-btn"
          on:click={() => {
            if (!inputTags.includes(suggestion)) {
              inputTags = [...inputTags, suggestion];
            }
          }}
          disabled={inputTags.includes(suggestion)}
        >
          {suggestion}
        </button>
      {/each}
    </div>
  </div>
  
  <div class="output">
    <h4>当前标签：</h4>
    <pre>{JSON.stringify(inputTags, null, 2)}</pre>
  </div>
</div>

<style>
  .tag-input-demo {
    margin: 20px;
    max-width: 600px;
  }
  
  .tag-input-container {
    border: 1px solid #ddd;
    border-radius: 8px;
    padding: 16px;
    background: #fafafa;
  }
  
  .tag-input-container label {
    display: block;
    margin-bottom: 8px;
    font-weight: 500;
  }
  
  .input-wrapper {
    display: flex;
    gap: 12px;
    align-items: flex-start;
  }
  
  .tag-display {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    min-height: 32px;
    padding: 8px;
    border: 1px solid #ccc;
    border-radius: 4px;
    background: white;
  }
  
  .tag-input {
    border: none;
    outline: none;
    flex: 1;
    min-width: 120px;
    font-size: 14px;
  }
  
  .tag-input::placeholder {
    color: #999;
  }
  
  .input-actions button {
    padding: 8px 12px;
    border: 1px solid #dc3545;
    background: white;
    color: #dc3545;
    border-radius: 4px;
    cursor: pointer;
    font-size: 12px;
  }
  
  .input-actions button:hover:not(:disabled) {
    background: #dc3545;
    color: white;
  }
  
  .input-actions button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
  
  .tag-suggestions {
    margin-top: 12px;
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
  }
  
  .suggestions-label {
    font-size: 12px;
    color: #666;
    margin-right: 8px;
  }
  
  .suggestion-btn {
    padding: 4px 8px;
    border: 1px solid #007bff;
    background: white;
    color: #007bff;
    border-radius: 12px;
    cursor: pointer;
    font-size: 11px;
  }
  
  .suggestion-btn:hover:not(:disabled) {
    background: #007bff;
    color: white;
  }
  
  .suggestion-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
  
  .output {
    margin-top: 20px;
    padding: 16px;
    background: #f8f9fa;
    border-radius: 4px;
  }
  
  .output h4 {
    margin: 0 0 8px 0;
  }
  
  .output pre {
    margin: 0;
    font-size: 12px;
  }
</style>
```

### 标签分类

```svelte
<script>
  import Tag from "@ticatec/uniface-element/Tag";
  
  const categories = [
    {
      name: "技术",
      color: "1",
      tags: ["JavaScript", "TypeScript", "Python", "React", "Vue.js"]
    },
    {
      name: "技能",
      color: "2", 
      tags: ["前端", "后端", "运维", "UI/UX", "测试"]
    },
    {
      name: "兴趣",
      color: "3",
      tags: ["开源", "AI/ML", "Web3", "移动端", "游戏"]
    },
    {
      name: "工具",
      color: "4",
      tags: ["VS Code", "Git", "Docker", "AWS", "Figma"]
    }
  ];
  
  let selectedTags = [];
  
  function toggleTag(tag) {
    if (selectedTags.includes(tag)) {
      selectedTags = selectedTags.filter(t => t !== tag);
    } else {
      selectedTags = [...selectedTags, tag];
    }
  }
</script>

<div class="category-demo">
  <h3>标签分类</h3>
  
  <div class="categories">
    {#each categories as category}
      <div class="category-section">
        <div class="category-header">
          <Tag text={category.name} color={category.color} removable={false} variant="round" />
          <span class="tag-count">({category.tags.length})</span>
        </div>
        
        <div class="category-tags">
          {#each category.tags as tag}
            <button 
              class="tag-button"
              class:selected={selectedTags.includes(tag)}
              on:click={() => toggleTag(tag)}
            >
              <Tag 
                text={tag} 
                color={selectedTags.includes(tag) ? category.color : "12"}
                size="small"
                removable={false}
              />
            </button>
          {/each}
        </div>
      </div>
    {/each}
  </div>
  
  <div class="selected-summary">
    <h4>已选标签 ({selectedTags.length})</h4>
    <div class="selected-tags">
      {#each selectedTags as tag}
        <Tag 
          text={tag} 
          color="1"
          size="small"
          variant="round"
          removable={true}
          removeHandler={() => toggleTag(tag)}
        />
      {/each}
    </div>
  </div>
</div>

<style>
  .category-demo {
    margin: 20px;
    max-width: 800px;
  }
  
  .categories {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 20px;
    margin-bottom: 24px;
  }
  
  .category-section {
    padding: 16px;
    border: 1px solid #eee;
    border-radius: 8px;
    background: #fafafa;
  }
  
  .category-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
  }
  
  .tag-count {
    font-size: 12px;
    color: #666;
  }
  
  .category-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
  
  .tag-button {
    border: none;
    background: none;
    padding: 0;
    cursor: pointer;
    border-radius: 4px;
  }
  
  .tag-button:hover {
    transform: translateY(-1px);
  }
  
  .tag-button.selected {
    transform: scale(1.05);
  }
  
  .selected-summary {
    padding: 16px;
    background: #f8f9fa;
    border-radius: 8px;
    border-left: 4px solid #007bff;
  }
  
  .selected-summary h4 {
    margin: 0 0 12px 0;
    color: #333;
  }
  
  .selected-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
</style>
```

## 功能

- **多种变体**：支持边框、圆形和无边框样式
- **尺寸选项**：支持小、中、大尺寸
- **颜色主题**：12种预定义颜色主题，带有语义含义
- **可移除功能**：可选的移除图标，带有悬停交互
- **灵活样式**：支持自定义 CSS 类和内联样式
- **响应式设计**：适配不同屏幕尺寸
- **悬停效果**：交互式移除图标

## 颜色主题参考

| 颜色 | 主题 | 使用场景 |
|-------|-------|----------|
| 1 | 蓝色 | 主要操作、链接、导航 |
| 2 | 绿色 | 成功状态、完成动作 |
| 3 | 红色 | 错误状态、关键警报 |
| 4 | 黄色 | 警告状态、注意 |
| 5 | 粉色 | 高亮显示、特殊功能 |
| 6 | 青色 | 信息提示、建议 |
| 7 | 橙色 | 警报、通知 |
| 8 | 琥珀色 | 待处理状态、进行中 |
| 9 | 靛蓝 | 导航、次要操作 |
| 10 | 紫色 | 创意内容、高级功能 |
| 11 | 酸橙色 | 新鲜内容、新项目 |
| 12 | 灰色 | 中性、默认状态 |

## 样式

Tag 组件使用 CSS 自定义属性进行主题化：

```css
:root {
  --uniface-default-text-color: #374151;
  --uniface-primary-border-color: #E2E8F0;
}

/* 自定义标签样式 */
.uniface-tag {
  /* 容器样式 */
}

.uniface-tag > div {
  /* 标签内容样式 */
}

.uniface-tag .uniface-remove-icon {
  /* 移除图标样式 */
}
```

## 可访问性

- 正确的语义化 HTML 结构
- 支持键盘导航的移除功能
- 高对比度颜色主题
- 兼容屏幕阅读器
- 交互元素的焦点指示器

## 最佳实践

1. **颜色使用**：在整个应用中保持颜色一致性
2. **可移除标签**：在移除标签时提供清晰的反馈
3. **标签限制**：考虑限制标签数量以改善用户体验
4. **响应式设计**：在不同屏幕尺寸上测试标签布局
5. **语义含义**：使用与语义含义匹配的颜色主题
6. **性能**：对于大型标签列表，考虑使用虚拟化

## 浏览器支持

- 支持 CSS 自定义属性的现代浏览器
- 兼容 Svelte 5+
- 支持悬停和焦点交互
- 支持 Flexbox 布局
- 完整的 TypeScript 支持

## 相关组件

- `Chip` - 带有交互动作的芯片组件
- `Badge` - 小型状态指示器
- `Label` - 表单字段标签
- `Button` - 交互按钮组件