mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-24 14:43:35 +08:00
fix: use bottom-anchored positioning for above-trigger dropdown in ModelSelector
When the dropdown opens above the trigger button, use CSS bottom instead of top to prevent a gap between the dropdown and the button when content is shorter than maxHeight. Co-Authored-By: claude-opus-4-6 <noreply@anthropic.com>
This commit is contained in:
parent
aa1321a02b
commit
12ccd2b611
@ -1,4 +1,4 @@
|
|||||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||||
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react'
|
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react'
|
||||||
import '@testing-library/jest-dom'
|
import '@testing-library/jest-dom'
|
||||||
|
|
||||||
@ -34,6 +34,12 @@ afterEach(() => {
|
|||||||
useHahaOpenAIOAuthStore.setState(useHahaOpenAIOAuthStore.getInitialState(), true)
|
useHahaOpenAIOAuthStore.setState(useHahaOpenAIOAuthStore.getInitialState(), true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Prevent real API calls from fetchStatus on mount
|
||||||
|
beforeEach(() => {
|
||||||
|
useHahaOAuthStore.setState({ fetchStatus: async () => {} })
|
||||||
|
useHahaOpenAIOAuthStore.setState({ fetchStatus: async () => {} })
|
||||||
|
})
|
||||||
|
|
||||||
describe('ModelSelector', () => {
|
describe('ModelSelector', () => {
|
||||||
it('uses controlled model selection without mutating settings directly', async () => {
|
it('uses controlled model selection without mutating settings directly', async () => {
|
||||||
const onChange = vi.fn()
|
const onChange = vi.fn()
|
||||||
@ -139,7 +145,10 @@ describe('ModelSelector', () => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
const setSessionRuntime = vi.fn()
|
const setSessionRuntime = vi.fn()
|
||||||
useHahaOpenAIOAuthStore.setState({ status: { loggedIn: true, expiresAt: null, email: null, accountId: null } })
|
useHahaOpenAIOAuthStore.setState({
|
||||||
|
status: { loggedIn: true, expiresAt: null, email: null, accountId: null },
|
||||||
|
fetchStatus: async () => {},
|
||||||
|
})
|
||||||
useSettingsStore.setState({
|
useSettingsStore.setState({
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
availableModels: openAIModels,
|
availableModels: openAIModels,
|
||||||
@ -175,8 +184,8 @@ describe('ModelSelector', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('hides official provider sections when OAuth is not logged in', async () => {
|
it('hides official provider sections when OAuth is not logged in', async () => {
|
||||||
useHahaOAuthStore.setState({ status: { loggedIn: false } })
|
useHahaOAuthStore.setState({ status: { loggedIn: false }, fetchStatus: async () => {} })
|
||||||
useHahaOpenAIOAuthStore.setState({ status: { loggedIn: false } })
|
useHahaOpenAIOAuthStore.setState({ status: { loggedIn: false }, fetchStatus: async () => {} })
|
||||||
useSettingsStore.setState({
|
useSettingsStore.setState({
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
availableModels: MODELS,
|
availableModels: MODELS,
|
||||||
|
|||||||
@ -38,7 +38,8 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DropdownPosition = {
|
type DropdownPosition = {
|
||||||
top: number
|
top: number | undefined
|
||||||
|
bottom: number | undefined
|
||||||
left: number
|
left: number
|
||||||
width: number
|
width: number
|
||||||
maxHeight: number
|
maxHeight: number
|
||||||
@ -267,9 +268,8 @@ export function ModelSelector({
|
|||||||
const maxHeight = Math.min(DROPDOWN_MAX_HEIGHT, availableHeight)
|
const maxHeight = Math.min(DROPDOWN_MAX_HEIGHT, availableHeight)
|
||||||
|
|
||||||
setDropdownPosition({
|
setDropdownPosition({
|
||||||
top: placeBelow
|
top: placeBelow ? rect.bottom + DROPDOWN_GAP : undefined,
|
||||||
? rect.bottom + DROPDOWN_GAP
|
bottom: placeBelow ? undefined : (viewportHeight - rect.top + DROPDOWN_GAP),
|
||||||
: Math.max(VIEWPORT_MARGIN, rect.top - DROPDOWN_GAP - maxHeight),
|
|
||||||
left,
|
left,
|
||||||
width,
|
width,
|
||||||
maxHeight,
|
maxHeight,
|
||||||
@ -535,6 +535,7 @@ export function ModelSelector({
|
|||||||
className="fixed z-[80] rounded-xl border border-[var(--color-border)] bg-[var(--color-surface-container-lowest)] shadow-[var(--shadow-dropdown)]"
|
className="fixed z-[80] rounded-xl border border-[var(--color-border)] bg-[var(--color-surface-container-lowest)] shadow-[var(--shadow-dropdown)]"
|
||||||
style={{
|
style={{
|
||||||
top: dropdownPosition.top,
|
top: dropdownPosition.top,
|
||||||
|
bottom: dropdownPosition.bottom,
|
||||||
left: dropdownPosition.left,
|
left: dropdownPosition.left,
|
||||||
width: dropdownPosition.width,
|
width: dropdownPosition.width,
|
||||||
}}
|
}}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user