diff --git a/opensquilla-webui/src/components/chat/ActivityCodeDetails.vue b/opensquilla-webui/src/components/chat/ActivityCodeDetails.vue index dfda0f2dfa..b140980289 100644 --- a/opensquilla-webui/src/components/chat/ActivityCodeDetails.vue +++ b/opensquilla-webui/src/components/chat/ActivityCodeDetails.vue @@ -146,7 +146,7 @@ const diffLines = computed(() => source.value.split('\n').map(text => ({ .activity-code-details__open { width: auto; padding: 0 0.375rem; font: inherit; opacity: 0; } .activity-code-details:hover .activity-code-details__open, .activity-code-details:focus-within .activity-code-details__open { opacity: 1; } -.activity-code-details__viewport { min-width: 0; width: 100%; max-height: min(20rem, 45vh); overflow: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; color: var(--text); } +.activity-code-details__viewport { min-width: 0; width: 100%; max-height: min(20rem, 45vh); overflow: auto; overscroll-behavior: auto; scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; color: var(--text); } .activity-code-details pre, .activity-code-details code { border: 0; border-radius: 0; background: transparent; box-shadow: none; font-family: var(--font-mono); font-size: 0.8125rem; font-weight: 400; line-height: 1.375rem; text-align: left; tab-size: 2; } .activity-code-details pre { width: max-content; min-width: 100%; box-sizing: border-box; margin: 0; padding: 0; white-space: pre; } diff --git a/opensquilla-webui/src/components/chat/ActivityToolDetails.scrollChain.test.ts b/opensquilla-webui/src/components/chat/ActivityToolDetails.scrollChain.test.ts new file mode 100644 index 0000000000..d6c9ee576b --- /dev/null +++ b/opensquilla-webui/src/components/chat/ActivityToolDetails.scrollChain.test.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from 'vitest' + +import codeDetailsSource from './ActivityCodeDetails.vue?raw' +import toolDetailsSource from './ActivityToolDetails.vue?raw' + +function ruleFor(source: string, selector: string): string { + const start = source.indexOf(`${selector} {`) + expect(start, `${selector} rule`).toBeGreaterThanOrEqual(0) + return source.slice(start, source.indexOf('}', start) + 1) +} + +describe('tool detail scroll windows', () => { + it('lets a wheel gesture at the inner boundary continue the transcript scroll', () => { + // `overscroll-behavior: contain` swallows the gesture at either inner + // boundary, so the transcript never moves while the pointer stays over the + // expanded details. Both the generic window and the code/diff viewport sit + // inside the chat column and must hand the remainder to it. + expect(ruleFor(toolDetailsSource, '.activity-tool-details__window')) + .toContain('overscroll-behavior: auto') + expect(ruleFor(codeDetailsSource, '.activity-code-details__viewport')) + .toContain('overscroll-behavior: auto') + }) +}) diff --git a/opensquilla-webui/src/components/chat/ActivityToolDetails.vue b/opensquilla-webui/src/components/chat/ActivityToolDetails.vue index 1168aa720a..8c99794c1c 100644 --- a/opensquilla-webui/src/components/chat/ActivityToolDetails.vue +++ b/opensquilla-webui/src/components/chat/ActivityToolDetails.vue @@ -515,7 +515,7 @@ const detailActionLabel = computed(() => { .activity-tool-details__log-status button { margin-inline-start: 0.5rem; padding: 0; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--text); font: inherit; text-decoration: underline; cursor: pointer; } .activity-tool-details__log-status button:focus-visible { outline: none; box-shadow: var(--focus-ring); } .activity-tool-details--bounded { position: relative; display: flex; flex-direction: column; max-width: 100%; max-height: min(20rem, 45vh); padding: 0; border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--bg); overflow: hidden; } -.activity-tool-details__window { min-height: 0; padding: 0.875rem 2.75rem 0.875rem 0.875rem; overflow: auto; overscroll-behavior: contain; scrollbar-gutter: stable; } +.activity-tool-details__window { min-height: 0; padding: 0.875rem 2.75rem 0.875rem 0.875rem; overflow: auto; overscroll-behavior: auto; scrollbar-gutter: stable; } .activity-tool-details__truncated { flex: 0 0 auto; margin: 0; padding: 0.375rem 0.875rem; color: var(--text-muted); font-size: 0.75rem; } .activity-tool-details__window:focus-visible { outline: none; box-shadow: var(--focus-ring-inset); } .activity-tool-details__section { margin: 0; padding: 0; border: 0; background: transparent; }