Merge pull request #5760 from deepseek-harness/turtle/image-viewer-windows-e0e1e6a26a6b
fix(client): keep the image lightbox clear of the Windows caption
This commit is contained in:
commit
d83cdfafd6
6 files changed
+35
-14
No files matched your search
@@ -289,7 +289,18 @@ describe('web e2e: Markdown image rendering', () => {
|
||||
await page.getByRole('button', { name: `View full image: ${WORKSPACE_ALT}`, exact: true }).click()
|
||||
const lightbox = page.getByRole('dialog', { name: 'Image preview', exact: true })
|
||||
await lightbox.waitFor()
|
||||
await lightbox.getByRole('button', { name: 'Close image preview' }).click()
|
||||
const lightboxMask = lightbox.locator(':scope > div > [aria-hidden="true"]')
|
||||
const lightboxClose = lightbox.getByRole('button', { name: 'Close image preview' })
|
||||
for (const windows of [true, false]) {
|
||||
await page.evaluate((value) => {
|
||||
document.documentElement.toggleAttribute('data-windows-titlebar', value)
|
||||
document.documentElement.style.setProperty('--dsh-windows-titlebar-height', value ? '40px' : '')
|
||||
}, windows)
|
||||
// The Windows caption stays unpainted and the close control sits below it.
|
||||
expect((await lightboxMask.boundingBox())?.y).toBe(windows ? 40 : 0)
|
||||
expect((await lightboxClose.boundingBox())?.y).toBe(windows ? 60 : 20)
|
||||
}
|
||||
await lightboxClose.click()
|
||||
await lightbox.waitFor({ state: 'detached' })
|
||||
const link = page.getByRole('button', { name: 'View comparison', exact: true })
|
||||
await link.hover()
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
en: f0e54915b896af5a
|
||||
zh: 2047520fd321be90
|
||||
/deepseek-ai-dsh-client-ui-primitives/use-this-package/rendering-agent-output:
|
||||
en: d79e20306593c4bf
|
||||
zh: 5c0f1100e2cd6fcc
|
||||
en: 4a1a61bb2d64fe4c
|
||||
zh: 1b0097fff440c2ef
|
||||
/deepseek-ai-dsh-client-ui-primitives/use-this-package/localizing-copy:
|
||||
en: 4aef65dea11de083
|
||||
zh: abc22cd7c65cdf38
|
||||
|
||||
@@ -106,7 +106,7 @@ The nearest `MarkdownDelegateProvider` supplies optional `openExternalLink` and
|
||||
|
||||
`JsonTree` clamps collapsed strings to `collapsedStringLines` (three by default). Expanded strings show raw text, retain sibling commas, and fit within the window and outer scrolling containers. Resize and ancestor-scroll events update that limit. Row copy feedback updates independently of JSON value rendering; pending clipboard writes cannot update a different row or an unmounted tree.
|
||||
|
||||
`ImageLightbox` is the shared original-image modal with focus restoration and Escape dismissal. The internal thumbnail renderer receives loading/failure labels from its owner. `HoverCard.inline` keeps a file link in the text flow and uses the shared menu material, keyboard-visible focus, and placement above or below the anchor without covering it. Escape closes an open thumbnail even when focus is elsewhere; subsequent Escape presses reach the owner. `MarkdownDelegateProvider.fileImages` supplies a decoded-path resolver and complete image labels: settled image links gain hover previews, and standalone images gain lightbox activation. Image-only anchors retain their single navigation target. The parser recovers only complete, unescaped, standalone local image references with bare spaces and an unambiguous supported image suffix; code and ambiguous destinations remain literal.
|
||||
`ImageLightbox` is the shared original-image modal with focus restoration and Escape dismissal. Like `Modal`, its mask leaves the Windows caption unpainted, and its close control sits 20px below the caption. The internal thumbnail renderer receives loading/failure labels from its owner. `HoverCard.inline` keeps a file link in the text flow and uses the shared menu material, keyboard-visible focus, and placement above or below the anchor without covering it. Escape closes an open thumbnail even when focus is elsewhere; subsequent Escape presses reach the owner. `MarkdownDelegateProvider.fileImages` supplies a decoded-path resolver and complete image labels: settled image links gain hover previews, and standalone images gain lightbox activation. Image-only anchors retain their single navigation target. The parser recovers only complete, unescaped, standalone local image references with bare spaces and an unambiguous supported image suffix; code and ambiguous destinations remain literal.
|
||||
|
||||
### Localizing copy
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ kind: "package-library"
|
||||
|
||||
`JsonTree` 把折叠字符串限制为 `collapsedStringLines` 行(默认三行)。展开后显示原始文本、保留同级逗号,并限制在窗口与外层滚动容器内;尺寸变化和祖先滚动事件会更新此限制。行复制反馈独立于 JSON 值渲染更新;尚未完成的剪贴板写入不会更新另一行或已卸载的树。
|
||||
|
||||
`ImageLightbox` 是共享原图浮层,支持焦点恢复与 Esc 关闭。包内缩略图渲染器由调用方提供加载及失败文案。`HoverCard.inline` 使文件链接保持在文本流内,并使用共享菜单材质、键盘可见焦点,并在锚点上方或下方定位而不遮挡锚点。即使焦点位于其他位置,Esc 也会关闭已打开的缩略图;后续 Esc 按键继续传给 owner。`MarkdownDelegateProvider.fileImages` 提供已解码路径解析器与完整图片文案:消息落定后的图片链接支持悬停预览,独立图片支持点击放大。仅包含图片的链接保留单一导航目标。解析器仅恢复完整、未转义、独立成段且带明确图片扩展名的含裸空格本地图片引用;代码与有歧义的目标保持原文。
|
||||
`ImageLightbox` 是共享原图浮层,支持焦点恢复与 Esc 关闭。与 `Modal` 相同,其遮罩不覆盖 Windows 顶栏,关闭按钮位于顶栏下方 20px。包内缩略图渲染器由调用方提供加载及失败文案。`HoverCard.inline` 使文件链接保持在文本流内,并使用共享菜单材质、键盘可见焦点,并在锚点上方或下方定位而不遮挡锚点。即使焦点位于其他位置,Esc 也会关闭已打开的缩略图;后续 Esc 按键继续传给 owner。`MarkdownDelegateProvider.fileImages` 提供已解码路径解析器与完整图片文案:消息落定后的图片链接支持悬停预览,独立图片支持点击放大。仅包含图片的链接保留单一导航目标。解析器仅恢复完整、未转义、独立成段且带明确图片扩展名的含裸空格本地图片引用;代码与有歧义的目标保持原文。
|
||||
|
||||
### 本地化文案
|
||||
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
/* Full-viewport layer that blocks background clicks, including on the Windows caption. */
|
||||
.backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1000;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
/* Painted area below the Windows caption; like Modal, the caption stays unpainted. */
|
||||
.stage {
|
||||
position: absolute;
|
||||
inset: var(--dsh-frame-chrome-top, 0px) 0 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
@@ -18,7 +26,7 @@
|
||||
.image {
|
||||
position: relative;
|
||||
max-width: min(100%, 1600px);
|
||||
max-height: calc(100vh - 80px);
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
border-radius: var(--dsw-radius-lg);
|
||||
background: var(--dsw-specific-input-major);
|
||||
@@ -27,7 +35,7 @@
|
||||
}
|
||||
|
||||
.close {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 1;
|
||||
|
||||
@@ -54,11 +54,13 @@ export function ImageLightbox({ src, alt, labels, onClose }: {
|
||||
aria-modal="true"
|
||||
aria-label={labels.dialog}
|
||||
>
|
||||
<div className={css.mask} aria-hidden="true" onMouseDown={onClose} />
|
||||
<img className={css.image} src={src} alt={alt} />
|
||||
<button ref={closeRef} type="button" className={css.close} aria-label={labels.close} onClick={onClose}>
|
||||
<IconCloseOutlineRegular size={16} />
|
||||
</button>
|
||||
<div className={css.stage}>
|
||||
<div className={css.mask} aria-hidden="true" onMouseDown={onClose} />
|
||||
<img className={css.image} src={src} alt={alt} />
|
||||
<button ref={closeRef} type="button" className={css.close} aria-label={labels.close} onClick={onClose}>
|
||||
<IconCloseOutlineRegular size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
document.body,
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user