expand and search the new chat Agent profile picker
Build / build (push) Canceled after 0s
Playwright / e2e (push) Canceled after 0s

This commit is contained in:
2026-10-25 00:10:21 +08:00
parent d3b3a0833e
commit ecb7c9501c
3 changed files with 55 additions and 0 deletions
@@ -0,0 +1,10 @@
---
date: 2026-10-25
pr: pending
feature: New chat Agent profile picker
impact: The Agent popup shows more profiles using a viewport-bounded height and supports searching by profile name. Model/provider pickers and chat events are unchanged.
---
The new-chat profile list uses up to 480px or 60% of the dynamic viewport height,
whichever is smaller. Browser checks cover 20 profiles, search/selection and popup
bounds on desktop, portrait mobile and short landscape screens.
@@ -1444,6 +1444,8 @@ async function handleSessionModelCustomSubmit() {
:model-value="newChatProfile"
:options="newChatProfileOptions"
:loading="newChatLoading || profilesStore.loading"
:trigger-props="{ contentClass: 'new-chat-profile-popup' }"
allow-search
@change="handleNewChatProfileChange"
/>
</div>
@@ -2158,6 +2160,10 @@ async function handleSessionModelCustomSubmit() {
}
}
:global(.new-chat-profile-popup .arco-select-dropdown-list-wrapper) {
max-height: min(480px, 60dvh);
}
.new-chat-form {
display: flex;
flex-direction: column;
+39
View File
@@ -100,3 +100,42 @@ test('new chat selectors stay open after clicking their field and allow selectio
await expect(drawer).toBeVisible()
}
})
for (const viewport of [{ width: 1440, height: 900 }, { width: 390, height: 844 }, { width: 844, height: 390 }]) {
test(`Agent selector shows more profiles and supports searching at ${viewport.width}x${viewport.height}`, async ({ page }, testInfo) => {
await page.setViewportSize(viewport)
await authenticate(page, TEST_ACCESS_KEY, 'research')
await mockHermesApi(page)
await page.route(url => url.pathname === '/api/hermes/profiles', route => route.fulfill({
json: { profiles: ['research', ...Array.from({ length: 19 }, (_, index) => `profile-${String(index + 1).padStart(2, '0')}`)].map(name => ({ name, model: 'test-model', alias: '', active: name === 'research' })) },
}))
await mockChatSocket(page)
await page.goto('/#/hermes/chat')
if (viewport.width <= 768) await page.locator('.hamburger-btn').click()
await page.getByRole('button', { name: 'New Chat', exact: true }).click()
const selector = page.locator('.new-chat-drawer .new-chat-field > .arco-select').first()
await selector.click({ position: { x: 8, y: 16 } })
const popup = page.locator('.new-chat-profile-popup')
await expect(popup).toBeVisible()
const list = popup.locator('.arco-select-dropdown-list-wrapper')
await expect.poll(() => list.evaluate(element => element.clientHeight)).toBeGreaterThan(viewport.height > 600 ? 350 : 200)
const bounds = (await popup.boundingBox())!
expect(bounds.y).toBeGreaterThanOrEqual(0)
expect(bounds.y + bounds.height).toBeLessThanOrEqual(viewport.height)
const visibleOptions = await list.evaluate(element => {
const bounds = element.getBoundingClientRect()
return [...element.querySelectorAll('.arco-select-option')].filter(option => {
const rect = option.getBoundingClientRect()
return rect.top >= bounds.top && rect.bottom <= bounds.bottom
}).length
})
expect(visibleOptions).toBeGreaterThanOrEqual(viewport.height > 600 ? 10 : 5)
if (viewport.width === 390) await page.screenshot({ path: testInfo.outputPath('agent-profile-picker-mobile.png'), animations: 'disabled' })
await selector.locator('input').fill('profile-19')
await expect(popup.locator('.arco-select-option')).toHaveCount(1)
await popup.locator('.arco-select-option', { hasText: 'profile-19' }).click()
await expect(selector).toContainText('profile-19')
await expect(popup).toBeHidden()
})
}