fix(playground): prevent model group option stretching (#6120)
* fix(playground): prevent model group option stretching - keep group options at a fixed 2rem height and align them to the top. - organize layout code in a dedicated module and cover layout and scrolling behavior. * docs(web): strengthen frontend testing requirements - require regression coverage for behavior changes, bug fixes, and UI states. - define module-scoped test organization, stable assertions, mocks, and verification rules.
This commit is contained in:
@@ -65,7 +65,7 @@ import { cn } from '@/lib/utils'
|
||||
import {
|
||||
modelGroupSelectorLayoutClasses,
|
||||
scrollSelectedOptionIntoView,
|
||||
} from './model-group-selector-layout'
|
||||
} from './model-group-selector/layout'
|
||||
|
||||
interface ModelOption {
|
||||
label: string
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright (C) 2023-2026 QuantumNous
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
For commercial licensing, please contact support@quantumnous.com
|
||||
*/
|
||||
import assert from 'node:assert/strict'
|
||||
import { describe, test } from 'node:test'
|
||||
|
||||
import {
|
||||
modelGroupSelectorLayoutClasses,
|
||||
scrollSelectedOptionIntoView,
|
||||
} from '../layout'
|
||||
|
||||
describe('model group selector layout', () => {
|
||||
test('keeps group options at a fixed height and aligned to the top', () => {
|
||||
const groupScrollClasses =
|
||||
modelGroupSelectorLayoutClasses.groupScroll.split(' ')
|
||||
|
||||
assert.ok(groupScrollClasses.includes('auto-rows-[2rem]'))
|
||||
assert.ok(groupScrollClasses.includes('content-start'))
|
||||
})
|
||||
|
||||
test('centers the selected group inside its own scroll container', () => {
|
||||
const scrollCalls: ScrollToOptions[] = []
|
||||
const selectedOption = {
|
||||
offsetHeight: 32,
|
||||
offsetTop: 160,
|
||||
scrollIntoView() {},
|
||||
}
|
||||
const scrollContainer = {
|
||||
clientHeight: 200,
|
||||
scrollTop: 0,
|
||||
scrollTo(options: ScrollToOptions) {
|
||||
scrollCalls.push(options)
|
||||
},
|
||||
}
|
||||
|
||||
scrollSelectedOptionIntoView(selectedOption, scrollContainer)
|
||||
|
||||
assert.deepEqual(scrollCalls, [{ top: 76, behavior: 'auto' }])
|
||||
})
|
||||
|
||||
test('falls back to scrollIntoView when no group container is provided', () => {
|
||||
const scrollCalls: ScrollIntoViewOptions[] = []
|
||||
const selectedOption = {
|
||||
scrollIntoView(options?: ScrollIntoViewOptions) {
|
||||
scrollCalls.push(options ?? {})
|
||||
},
|
||||
}
|
||||
|
||||
scrollSelectedOptionIntoView(selectedOption)
|
||||
|
||||
assert.deepEqual(scrollCalls, [{ block: 'center', inline: 'nearest' }])
|
||||
})
|
||||
})
|
||||
+2
-1
@@ -21,7 +21,8 @@ export const modelGroupSelectorLayoutClasses = {
|
||||
desktopContent:
|
||||
'grid h-[min(50vh,28rem)] max-h-[min(50vh,28rem)] min-h-0 gap-3 p-2 md:grid-cols-[9.5rem_minmax(0,1fr)]',
|
||||
groupColumn: 'flex h-full min-h-0 min-w-0 flex-col overflow-hidden',
|
||||
groupScroll: 'mt-2 grid min-h-0 flex-1 gap-1 overflow-y-auto pr-1',
|
||||
groupScroll:
|
||||
'mt-2 grid min-h-0 flex-1 auto-rows-[2rem] content-start gap-1 overflow-y-auto pr-1',
|
||||
modelColumn: 'flex h-full min-h-0 min-w-0 overflow-hidden rounded-lg border',
|
||||
modelCommand: 'min-h-0 flex-1 rounded-lg border-0 bg-transparent p-1',
|
||||
modelList:
|
||||
Reference in New Issue
Block a user