Files
TrueGrowth/docs/Z_INDEX_GUIDE.md

9.9 KiB
Raw Permalink Blame History

Z-Index 层级管理规范

当前问题分析

经过代码审查发现以下z-index混乱问题

  1. unified-toolbar (1000) 遮挡了弹窗和popover
  2. popup/popover (1000) 与toolbar使用相同层级
  3. AI弹窗 (2000) 被unified-toolbar遮挡
  4. 多个组件使用1000 导致层级冲突
  5. 临时修复层出现9999、10000等随意值

Z-Index 层级规范

采用分层设计每层预留100个单位空间

┌─────────────────────────────────────────────┐
│ Layer 9: Critical Overlays (9000+)         │  全局最高层
├─────────────────────────────────────────────┤
│ Layer 8: Image Viewer (8000-8999)          │  图片查看器
├─────────────────────────────────────────────┤
│ Layer 7: Auth Dialogs (7000-7999)          │  认证弹窗
├─────────────────────────────────────────────┤
│ Layer 6: Notifications (6000-6999)         │  通知提示
├─────────────────────────────────────────────┤
│ Layer 5: Modals (5000-5999)                │  模态弹窗
├─────────────────────────────────────────────┤
│ Layer 4: Drawers/Panels (4000-4999)        │  抽屉/面板
├─────────────────────────────────────────────┤
│ Layer 3: Popovers (3000-3999)              │  弹出层
├─────────────────────────────────────────────┤
│ Layer 2: Toolbars (2000-2999)              │  工具栏
├─────────────────────────────────────────────┤
│ Layer 1: Canvas Elements (1000-1999)       │  画布元素
├─────────────────────────────────────────────┤
│ Layer 0: Base (0-999)                      │  基础层
└─────────────────────────────────────────────┘

详细层级定义

Layer 0: Base (0-999)

  • 0-99: 默认文档流
  • 100-199: 画布内部元素selection, drag handlers
  • 200-299: 预留

Layer 1: Canvas Elements (1000-1999)

  • 1000-1099: 画布装饰元素(网格、辅助线)
  • 1100-1199: 临时元素resize handles, anchors
  • 1200-1299: 预留

Layer 2: Toolbars (2000-2999)

  • 2000: unified-toolbar (主工具栏)
  • 2010: creation-toolbar
  • 2020: popup-toolbar
  • 2030: zoom-toolbar
  • 2040: app-toolbar
  • 2050: pencil-mode-toolbar
  • 2100-2199: 其他工具栏

Layer 3: Popovers (3000-3999)

  • 3000: 工具栏popover (freehand-panel, shape-picker, arrow-picker)
  • 3010: feedback-button popover
  • 3020: zoom-toolbar popover
  • 3030: app-toolbar popover
  • 3100-3199: 其他popover
  • 3500: Tooltip (始终在popover之上)

Layer 4: Drawers/Panels (4000-4999)

  • 4000: task-queue-panel
  • 4010: chat-drawer
  • 4020: generation-history drawer
  • 4100-4199: 其他侧边栏

Layer 5: Modals (5000-5999)

  • 5000: 普通Dialog (ttd-dialog)
  • 5010: clean-confirm
  • 5020: settings-dialog
  • 5100: AI Image Generation Dialog (react-rnd窗口)
  • 5110: AI Video Generation Dialog (react-rnd窗口)
  • 5200-5299: Dialog内部元素header, footer等
  • 5500-5599: Dialog内的popover/select

Layer 6: Notifications (6000-6999)

  • 6000: active-task-warning
  • 6100: Toast通知
  • 6200: 成功/错误提示

Layer 7: Auth Dialogs (7000-7999)

  • 7000: API key auth dialog
  • 7100: 登录/注册弹窗

Layer 8: Image Viewer (8000-8999)

  • 8000: Image viewer overlay
  • 8010: Image viewer toolbar
  • 8020: Image viewer close button

Layer 9: Critical Overlays (9000+)

  • 9000: Loading spinner (全屏)
  • 9100: 系统级错误提示
  • 9999: 开发调试层

实施规则

1. 使用CSS变量

// styles/variables.scss
$z-index: (
  // Layer 0: Base
  'canvas-internal': 100,
  
  // Layer 1: Canvas Elements  
  'canvas-decoration': 1000,
  'canvas-temporary': 1100,
  
  // Layer 2: Toolbars
  'unified-toolbar': 2000,
  'creation-toolbar': 2010,
  'popup-toolbar': 2020,
  'zoom-toolbar': 2030,
  'app-toolbar': 2040,
  'pencil-toolbar': 2050,
  
  // Layer 3: Popovers
  'popover': 3000,
  'popover-feedback': 3010,
  'popover-zoom': 3020,
  'popover-app': 3030,
  'tooltip': 3500,
  
  // Layer 4: Drawers
  'task-queue-panel': 4000,
  'chat-drawer': 4010,
  'generation-history': 4020,
  
  // Layer 5: Modals
  'dialog': 5000,
  'dialog-clean-confirm': 5010,
  'dialog-settings': 5020,
  'dialog-ai-image': 5100,
  'dialog-ai-video': 5110,
  'dialog-inner': 5200,
  'dialog-popover': 5500,
  
  // Layer 6: Notifications
  'active-task-warning': 6000,
  'toast': 6100,
  'message': 6200,
  
  // Layer 7: Auth
  'auth-dialog': 7000,
  
  // Layer 8: Image Viewer
  'image-viewer': 8000,
  'image-viewer-toolbar': 8010,
  'image-viewer-close': 8020,
  
  // Layer 9: Critical
  'loading': 9000,
  'system-error': 9100,
  'debug': 9999,
);

// 辅助函数
@function z($layer) {
  @return map-get($z-index, $layer);
}

2. TypeScript常量

// constants/z-index.ts
export const Z_INDEX = {
  // Layer 0: Base
  CANVAS_INTERNAL: 100,
  
  // Layer 1: Canvas Elements
  CANVAS_DECORATION: 1000,
  CANVAS_TEMPORARY: 1100,
  
  // Layer 2: Toolbars
  UNIFIED_TOOLBAR: 2000,
  CREATION_TOOLBAR: 2010,
  POPUP_TOOLBAR: 2020,
  ZOOM_TOOLBAR: 2030,
  APP_TOOLBAR: 2040,
  PENCIL_TOOLBAR: 2050,
  
  // Layer 3: Popovers
  POPOVER: 3000,
  POPOVER_FEEDBACK: 3010,
  POPOVER_ZOOM: 3020,
  POPOVER_APP: 3030,
  TOOLTIP: 3500,
  
  // Layer 4: Drawers
  TASK_QUEUE_PANEL: 4000,
  CHAT_DRAWER: 4010,
  GENERATION_HISTORY: 4020,
  
  // Layer 5: Modals
  DIALOG: 5000,
  DIALOG_CLEAN_CONFIRM: 5010,
  DIALOG_SETTINGS: 5020,
  DIALOG_AI_IMAGE: 5100,
  DIALOG_AI_VIDEO: 5110,
  DIALOG_INNER: 5200,
  DIALOG_POPOVER: 5500,
  
  // Layer 6: Notifications
  ACTIVE_TASK_WARNING: 6000,
  TOAST: 6100,
  MESSAGE: 6200,
  
  // Layer 7: Auth
  AUTH_DIALOG: 7000,
  
  // Layer 8: Image Viewer
  IMAGE_VIEWER: 8000,
  IMAGE_VIEWER_TOOLBAR: 8010,
  IMAGE_VIEWER_CLOSE: 8020,
  
  // Layer 9: Critical
  LOADING: 9000,
  SYSTEM_ERROR: 9100,
  DEBUG: 9999,
} as const;

export type ZIndexKey = keyof typeof Z_INDEX;

3. 使用示例

SCSS中使用

@import 'styles/variables';

.unified-toolbar {
  z-index: z('unified-toolbar'); // 2000
}

.my-popover {
  z-index: z('popover'); // 3000
}

TSX中使用

import { Z_INDEX } from '@/constants/z-index';

<Rnd style={{ zIndex: Z_INDEX.DIALOG_AI_IMAGE }}>
  {/* AI Image Dialog */}
</Rnd>

<PopoverContent style={{ zIndex: Z_INDEX.POPOVER }}>
  {/* Popover content */}
</PopoverContent>

禁止事项

禁止随意使用魔术数字

// ❌ 错误
.my-component {
  z-index: 9999; // 不要使用随意的大数字
}

.another {
  z-index: 10001; // 临时修复会破坏层级体系
}

正确做法

// ✅ 正确
@import 'styles/variables';

.my-component {
  z-index: z('dialog'); // 使用预定义的层级
}

禁止在同一层级随意加减

// ❌ 错误
.toolbar {
  z-index: 2000;
}
.toolbar-fixed {
  z-index: 2001; // 破坏了层级结构
}

正确做法

// ✅ 正确 - 如果需要层内排序使用DOM顺序或position
.toolbar {
  z-index: z('unified-toolbar');
}
.toolbar-fixed {
  z-index: z('unified-toolbar');
  position: relative; // DOM顺序决定层级
}

Code Review检查清单

在代码审查时,检查以下项目:

  • 所有z-index使用都通过变量/常量引用
  • 没有硬编码的魔术数字
  • 新增组件的z-index符合层级规范
  • 没有超过9999的z-index值
  • Popover/Tooltip使用对应层级(3000+)
  • Dialog/Modal使用对应层级(5000+)
  • 临时修复已转换为规范用法

迁移计划

Phase 1: 创建变量文件

  • 创建 styles/z-index.scss
  • 创建 constants/z-index.ts

Phase 2: 修复关键冲突

  • unified-toolbar: 1000 → 2000
  • popovers: 1000 → 3000
  • task-queue-panel: 999 → 4000
  • AI dialogs: 2000 → 5100

Phase 3: 全面迁移

  • 替换所有SCSS中的硬编码z-index
  • 替换所有TSX中的内联z-index
  • 移除临时修复(9999, 10000等)

Phase 4: 文档和测试

  • 更新CODEBUDDY.md
  • 添加层级可视化测试页面
  • 团队培训

常见问题

Q: 如果需要在两个预定义层级之间插入新层级怎么办?
A: 每层预留了100个单位空间。例如在popover(3000)和drawer(4000)之间可以使用3100-3999。

Q: TDesign组件的z-index怎么处理?
A: 通过组件的style或className属性覆盖或使用TDesign的zIndex prop。

Q: react-rnd的默认z-index是多少?
A: 默认没有z-index需要显式设置。统一使用Z_INDEX.DIALOG_*系列。

Q: 如何调试z-index问题?
A:

  1. 使用浏览器DevTools的3D视图
  2. 临时添加不同背景色区分层级
  3. 使用 debug: 9999 层进行调试,完成后移除

参考资料