fix(ui-deliverables): fill diff row backgrounds across scroll width

This commit is contained in:
sjw1231 committed 2026-09-21 15:05:43 +08:00
1 parent 60cdd547ae
commit 795e5024bc
5 files changed
+40 -5

No files matched your search

+34
View File
@@ -217,6 +217,40 @@ describe('web e2e: a git workspace turn ends with its changed files', () => {
return [center(text), center(caret), center(counts)].map(value => Math.abs(value - buttonCenter))
})
for (const offset of headerAlignment) expect(offset).toBeLessThanOrEqual(0.5)
// The appended row has no old-side text; constrain the columns so the hunk header overflows it.
const emptyRowLayout = await page.addStyleTag({ content: `
[data-diff-side="left"] { width: 90px; }
[data-diff-side="right"] { width: 120px; }
` })
try {
const left = review.locator('[data-diff-side="left"]')
const emptyRow = left.locator('[data-diff-line="add"]')
const maximum = await left.evaluate(element => element.scrollWidth - element.clientWidth)
expect(maximum).toBeGreaterThan(0)
await left.evaluate((element) => { element.scrollLeft = element.scrollWidth })
await expect.poll(() => left.evaluate(element => element.scrollLeft)).toBe(maximum)
const fill = await emptyRow.evaluate((row) => {
const column = row.closest('[data-diff-side]')!
const columnBox = column.getBoundingClientRect()
const rowBox = row.getBoundingClientRect()
const y = rowBox.top + rowBox.height / 2
return {
rowWidth: rowBox.width,
contentWidth: column.scrollWidth,
background: getComputedStyle(row).backgroundColor,
coversViewport: [columnBox.left + 4, columnBox.right - 4].every(x =>
document.elementFromPoint(x, y)?.closest('[data-diff-line]') === row),
}
})
expect(fill.background).not.toBe('rgba(0, 0, 0, 0)')
expect(fill.rowWidth).toBeGreaterThanOrEqual(fill.contentWidth - 0.5)
expect(fill.coversViewport).toBe(true)
} finally {
await emptyRowLayout.evaluate(element => element.parentNode!.removeChild(element))
await review.locator('[data-diff-side]').evaluateAll((elements) => {
for (const element of elements) element.scrollLeft = 0
})
}
const addedLine = review.locator('[data-diff-side="right"] [data-diff-line="add"]')
const rightContextLine = review.locator('[data-diff-side="right"] [data-diff-line="context"]')
const addedRule = await addedLine.evaluate((line) => {
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/client/ui-deliverables/README.md
README.md: d3f0d391380f6f4ae9c95fdc8c0b4e8c4b00654a
README.zh.md: 1c25199512b5c97f041954995cf45452e58706ff
README.md: c537911c8ff32239278059c067e86c5775aa0a12
README.zh.md: 2a0c78ef2c741f65c37f31a53db82c9e7a523853
+1 -1
View File
@@ -46,7 +46,7 @@ A row opens the turn's `changes-review` tab, addressed by the viewed Session and
The selected-file title uses the document preview’s [`PathLabel`](../ui-primitives/README.md#component-catalog): complete and left-aligned when it fits, otherwise clipped at the left with a fade that preserves trailing characters and the extension. Directories use subdued text, the filename uses primary text, and hovering reveals the complete displayed path. Resizing the pane or selecting another file updates the fade; the dropdown arrow, line counts, and toolbar actions retain their space.
Without wrapping, the two columns synchronize vertical scrolling and horizontal offsets up to each side’s available range. Both columns suppress elastic edge feedback and scroll chaining on both axes; the browser retains control of native momentum within each column’s scrollable range. Both horizontal scrollbars remain at the bottom of the visible comparison; scrolling vertically preserves a long line’s horizontal offset when the other side fits without horizontal scrolling.
Without wrapping, the two columns synchronize vertical scrolling and horizontal offsets up to each side’s available range. Line backgrounds, including empty alignment rows, cover each column’s full scrollable width. Both columns suppress elastic edge feedback and scroll chaining on both axes; the browser retains control of native momentum within each column’s scrollable range. Both horizontal scrollbars remain at the bottom of the visible comparison; scrolling vertically preserves a long line’s horizontal offset when the other side fits without horizontal scrolling.
### Inline-code links
+1 -1
View File
@@ -46,7 +46,7 @@ Web 的 `standard`、`ptc` 与 `cordis` preset 提供 `present` 用于声明交
当前文件标题使用文档预览页的 [`PathLabel`](../ui-primitives/README.zh.md#component-catalog):空间足够时完整靠左显示,否则从左侧裁剪并渐隐,保留尾部字符和扩展名。目录使用弱化颜色,文件名使用主色,悬停显示完整路径。调整面板宽度或切换文件时更新渐隐;下拉箭头、行数和工具栏操作保留各自的空间。
关闭自动换行时,两列同步纵向滚动,横向偏移同步到各自可滚动范围内。两列在双轴上都禁用弹性边缘反馈和向外层传递滚动;各列可滚动范围内的原生惯性仍由浏览器控制。两侧横向滚动条始终位于可见对比区域底部;如果只有一侧需要横向滚动,上下滚动会保留该侧的横向偏移。
关闭自动换行时,两列同步纵向滚动,横向偏移同步到各自可滚动范围内。各行背景(包括用于对齐的空行)覆盖所在列的完整可滚动宽度。两列在双轴上都禁用弹性边缘反馈和向外层传递滚动;各列可滚动范围内的原生惯性仍由浏览器控制。两侧横向滚动条始终位于可见对比区域底部;如果只有一侧需要横向滚动,上下滚动会保留该侧的横向偏移。
### 行内代码链接
@@ -24,7 +24,8 @@
.status { display: flex; gap: 12px; align-items: center; margin: 0; padding: 16px; font-size: 13px; color: var(--dsw-alias-label-secondary); }
.body { display: flex; flex: 1 1 auto; flex-direction: column; min-height: 0; overflow: auto; padding: 8px 0 16px; font: var(--dsw-font-markdown-code-block); }
.columns { display: grid; flex: 1 1 auto; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); min-height: 0; }
.column { min-width: 0; overflow-x: scroll; overscroll-behavior: none; }
/* One intrinsic-width track keeps every hunk and empty row painted across the scrollable content. */
.column { display: grid; grid-template-columns: minmax(max-content, 100%); align-content: start; min-width: 0; overflow-x: scroll; overscroll-behavior: none; }
.column + .column { border-left: 0.5px solid var(--dsw-alias-border-l3); }
.sideLine { display: grid; grid-template-columns: 3.5em max-content; box-sizing: border-box; min-width: 100%; width: max-content; min-height: 22px; line-height: 22px; white-space: pre; }
.note { margin: 0; padding: 4px 16px 8px; font: var(--dsw-font-xs-13); color: var(--dsw-alias-label-tertiary); }