# Z-Index 层级规范文档

## 📋 概述

本文档定义了项目中所有 z-index 的使用规范，确保层级关系清晰、一致、可维护。

## 🎯 设计原则

1. **分层管理**：将 z-index 划分为 5 个主要层级，每层预留充足空间
2. **语义化命名**：使用有意义的变量名，而非魔法数字
3. **统一来源**：所有 z-index 值统一定义在 `z-index.css` 中
4. **易于扩展**：每层之间至少预留 100 的空间，方便插入新层级

## 📊 层级划分

### 1️⃣ 基础层 (0-99)
用于页面背景、基础布局等底层元素

| 变量名 | 值 | 用途 |
|--------|-----|------|
| `--z-background` | 0 | 最底层 - 背景装饰 |
| `--z-base-content` | 1 | 基础内容层 - 普通文本、图片 |
| `--z-divider` | 10 | 分割线、边框装饰 |

**使用场景：**
- 页面背景渐变
- 基础卡片容器
- 列表项默认状态

---

### 2️⃣ 组件层 (100-999)
用于常规 UI 组件，如下拉菜单、悬浮提示等

| 变量名 | 值 | 用途 |
|--------|-----|------|
| `--z-top-bar` | 100 | TopBar 导航栏 |
| `--z-sidebar` | 100 | 侧边栏容器 |
| `--z-dropdown-menu` | 1000 | 下拉菜单（预设操作、世界书选择） |
| `--z-sort-panel` | 1100 | 排序设置面板 |
| `--z-tooltip` | 1200 | 悬浮提示 Tooltip |
| `--z-chat-actions` | 1000 | 聊天消息操作按钮 |
| `--z-character-preview` | 1000 | 角色卡预览弹窗 |

**使用场景：**
- 点击按钮弹出的下拉菜单
- 鼠标悬停显示的提示信息
- 聊天消息的快捷操作按钮

---

### 3️⃣ 弹窗层 (10000-19999)
用于模态对话框、编辑面板等需要覆盖整个页面的元素

| 变量名 | 值 | 用途 |
|--------|-------|------|
| `--z-modal-overlay` | 10000 | 对话框遮罩层背景 |
| `--z-modal-content` | 10100 | 对话框内容（API配置、预设保存等） |
| `--z-edit-panel-overlay` | 10200 | 世界书编辑面板遮罩层 |
| `--z-edit-panel-content` | 10300 | 世界书编辑面板内容 |

**使用场景：**
- API 配置对话框
- 预设保存/编辑对话框
- 世界书条目编辑面板
- 任何需要全屏遮罩的模态窗口

**层级关系：**
```
编辑面板内容 (10300)
  ↓
编辑面板遮罩 (10200)
  ↓
对话框内容 (10100)
  ↓
对话框遮罩 (10000)
```

---

### 4️⃣ 通知层 (20000-29999)
用于全局通知、Toast 提示等

| 变量名 | 值 | 用途 |
|--------|-------|------|
| `--z-toast-container` | 20000 | Toast 通知容器 |
| `--z-toast-item` | 20100 | Toast 通知项 |

**使用场景：**
- 操作成功/失败的提示
- 系统通知
- 警告信息

---

### 5️⃣ 系统层 (30000+)
用于系统级元素，如加载动画、错误边界等

| 变量名 | 值 | 用途 |
|--------|-------|------|
| `--z-loading-spinner` | 30000 | 全局加载动画 |
| `--z-error-boundary` | 30100 | 错误边界覆盖层 |

**使用场景：**
- 页面加载时的旋转动画
- 错误捕获后的全屏提示
- 系统级遮罩

---

## 💡 使用指南

### CSS 中使用

```css
/* ✅ 推荐：使用 CSS 变量 */
.dropdown-menu {
  z-index: var(--z-dropdown-menu);
}

.modal-overlay {
  z-index: var(--z-modal-overlay);
}

.edit-panel {
  z-index: var(--z-edit-panel-content);
}
```

### TypeScript/JavaScript 中使用

```typescript
// ✅ 推荐：导入常量
import { Z_INDEX } from '../styles/z-index';

const style = {
  zIndex: Z_INDEX.DROPDOWN_MENU,
};
```

### ❌ 避免的做法

```css
/* ❌ 不要使用魔法数字 */
.dropdown-menu {
  z-index: 1000;  /* 难以理解，不易维护 */
}

/* ❌ 不要使用过大的数值 */
.modal {
  z-index: 99999;  /* 不合理，可能导致层级混乱 */
}
```

---

## 🔧 添加新层级

如果需要添加新的 z-index 层级，请遵循以下步骤：

1. **确定所属层级**：根据元素类型选择合适的层级范围
2. **选择合适数值**：在该层级范围内选择一个未使用的值（预留 100 间隔）
3. **更新定义文件**：
   - 在 `z-index.css` 中添加 CSS 变量
   - 在 `z-index.ts` 中添加 TypeScript 常量
4. **更新文档**：在本文档中添加说明

**示例：添加一个新的工具提示层级**

```css
/* z-index.css */
:root {
  --z-help-tooltip: 1300;  /* 在 tooltip (1200) 之上 */
}
```

```typescript
// z-index.ts
export const Z_INDEX = {
  // ...
  HELP_TOOLTIP: 1300,
} as const;
```

---

## 📝 常见问题

### Q: 为什么弹窗层从 10000 开始？
A: 为了与组件层（100-999）保持足够的距离，避免未来在组件层添加更多层级时产生冲突。

### Q: 如果两个元素都需要弹窗层怎么办？
A: 使用不同的子层级，例如：
- 第一个弹窗：`--z-modal-content` (10100)
- 第二个弹窗：`--z-modal-content + 10` (10110)

### Q: 可以在 inline style 中使用吗？
A: 可以，但推荐使用 CSS 类。如果必须使用 inline style：

```jsx
<div style={{ zIndex: 'var(--z-dropdown-menu)' }}>
```

---

## 📚 相关文件

- **CSS 变量定义**：`frontend/src/styles/z-index.css`
- **TypeScript 常量**：`frontend/src/styles/z-index.ts`
- **全局样式引入**：`frontend/src/index.css`

---

## 🔄 更新历史

| 日期 | 版本 | 更新内容 |
|------|------|----------|
| 2026-05-04 | 1.0 | 初始版本，建立完整的 z-index 层级体系 |
