fix(chat): 修复图片放大与工具详情浮层被覆盖及定位错乱

图片放大(ImageLightbox)与工具详情(ToolDetailModal)渲染在虚拟化消息行内,行元素的 transform 成为 fixed 后代的包含块,导致遮罩只覆盖行区域、工具栏定位偏移、其他内容叠在其上。

改用 createPortal 渲染到 document.body,并将 z-index 提升到 z-[10000] 超过下拉浮层 z-[9999],恢复视口级覆盖与右上角按钮定位。
This commit is contained in:
oudecheng 2026-08-18 23:00:16 +08:00
parent e2841ce791
commit f711948902
2 changed files with 18 additions and 6 deletions

View File

@ -1,4 +1,5 @@
import { useState, useEffect, memo } from 'react'; import { useState, useEffect, memo } from 'react';
import { createPortal } from 'react-dom';
import { import {
CheckCircle, CheckCircle,
ChevronRight, ChevronRight,
@ -319,9 +320,14 @@ function ImageLightbox({
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
}; };
return ( // 必须 portal 到 body本组件渲染在虚拟化消息行内行元素带
// transformtranslateYtransformed 祖先会成为 fixed 后代的包含块,
// 导致遮罩只覆盖该行区域、工具栏定位到行盒而非视口、其他行内容叠在
// 遮罩之上。portal 后 fixed/z-index 相对视口全局生效。
// z-[10000]高于下拉选择器z-[9999])等全局浮层。
return createPortal(
<div <div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/85 backdrop-blur-sm animate-fade-in" className="fixed inset-0 z-[10000] flex items-center justify-center bg-black/85 backdrop-blur-sm animate-fade-in"
onClick={onClose} onClick={onClose}
> >
{/* 顶部工具栏 */} {/* 顶部工具栏 */}
@ -349,7 +355,8 @@ function ImageLightbox({
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
alt="图片预览" alt="图片预览"
/> />
</div> </div>,
document.body,
); );
} }

View File

@ -1,4 +1,5 @@
import { useEffect } from 'react'; import { useEffect } from 'react';
import { createPortal } from 'react-dom';
import { X, Terminal, Clock, Maximize2 } from 'lucide-react'; import { X, Terminal, Clock, Maximize2 } from 'lucide-react';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm'; import remarkGfm from 'remark-gfm';
@ -65,9 +66,12 @@ export function ToolDetailModal({
? 'var(--accent-amber)' ? 'var(--accent-amber)'
: 'var(--text-muted)'; : 'var(--text-muted)';
return ( // portal 到 body在虚拟化消息行内打开时行元素的 transform 会成为
// fixed 后代的包含块,遮罩/定位全部失效(同 ImageLightbox
// z-[10000]高于下拉选择器z-[9999])等全局浮层。
return createPortal(
<div <div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm animate-fade-in" className="fixed inset-0 z-[10000] flex items-center justify-center bg-black/80 backdrop-blur-sm animate-fade-in"
onClick={onClose} onClick={onClose}
> >
{/* Modal container */} {/* Modal container */}
@ -145,6 +149,7 @@ export function ToolDetailModal({
</span> </span>
</div> </div>
</div> </div>
</div> </div>,
document.body,
); );
} }