fix(ai): cap agent composer height
This commit is contained in:
@@ -197,6 +197,18 @@ describe('AiPanel', () => {
|
||||
expect(screen.getByTestId('ai-panel')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('caps long AI agent drafts inside a scrollable composer while keeping send visible', () => {
|
||||
render(<AiPanel onClose={vi.fn()} vaultPath="/tmp/vault" />)
|
||||
|
||||
const editor = screen.getByTestId('agent-input')
|
||||
editor.textContent = Array.from({ length: 40 }, (_, index) => `Line ${index + 1}`).join('\n')
|
||||
fireEvent.input(editor)
|
||||
|
||||
expect(editor).toHaveClass('max-h-[160px]', 'overflow-y-auto', 'overscroll-contain')
|
||||
expect(editor).toHaveStyle({ maxHeight: '160px', overflowY: 'auto' })
|
||||
expect(screen.getByTestId('agent-send')).toBeVisible()
|
||||
})
|
||||
|
||||
it('calls onClose when close button is clicked', () => {
|
||||
const onClose = vi.fn()
|
||||
render(<AiPanel onClose={onClose} vaultPath="/tmp/vault" />)
|
||||
|
||||
@@ -369,7 +369,7 @@ export function AiPanelComposer({
|
||||
style={{ padding: '8px 12px' }}
|
||||
>
|
||||
<div className="flex items-end gap-2">
|
||||
<div className="flex-1">
|
||||
<div className="min-w-0 flex-1">
|
||||
<WikilinkChatInput
|
||||
entries={entries}
|
||||
value={input}
|
||||
@@ -379,6 +379,8 @@ export function AiPanelComposer({
|
||||
disabled={composerDisabled}
|
||||
placeholder={placeholder}
|
||||
inputRef={inputRef}
|
||||
editorClassName="max-h-[160px] overflow-y-auto overscroll-contain"
|
||||
editorStyle={{ maxHeight: 160, overflowY: 'auto', overscrollBehavior: 'contain' }}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
type CSSProperties,
|
||||
type ReactNode,
|
||||
} from 'react'
|
||||
import type { VaultEntry } from '../types'
|
||||
@@ -57,6 +58,7 @@ interface InlineWikilinkInputProps {
|
||||
inputRef?: React.RefObject<HTMLDivElement | null>
|
||||
dataTestId?: string
|
||||
editorClassName?: string
|
||||
editorStyle?: CSSProperties
|
||||
suggestionListVariant?: 'floating' | 'palette'
|
||||
suggestionEmptyLabel?: string
|
||||
paletteHeader?: ReactNode
|
||||
@@ -168,6 +170,7 @@ export function InlineWikilinkInput({
|
||||
inputRef,
|
||||
dataTestId = 'agent-input',
|
||||
editorClassName,
|
||||
editorStyle,
|
||||
suggestionListVariant = 'floating',
|
||||
suggestionEmptyLabel = 'No matching notes',
|
||||
paletteHeader,
|
||||
@@ -472,6 +475,7 @@ export function InlineWikilinkInput({
|
||||
inputRef={setCombinedRef}
|
||||
dataTestId={dataTestId}
|
||||
editorClassName={editorClassName}
|
||||
editorStyle={editorStyle}
|
||||
onCompositionEnd={handleCompositionEnd}
|
||||
onCompositionStart={handleCompositionStart}
|
||||
onInput={handleInput}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Fragment, createElement } from 'react'
|
||||
import type { CSSProperties } from 'react'
|
||||
import type { VaultEntry } from '../types'
|
||||
import { getTypeColor, getTypeLightColor } from '../utils/typeColors'
|
||||
import { NoteTitleIcon } from './NoteTitleIcon'
|
||||
@@ -158,6 +159,7 @@ export function InlineWikilinkEditorField({
|
||||
inputRef,
|
||||
dataTestId,
|
||||
editorClassName,
|
||||
editorStyle,
|
||||
onCompositionEnd,
|
||||
onCompositionStart,
|
||||
onInput,
|
||||
@@ -175,6 +177,7 @@ export function InlineWikilinkEditorField({
|
||||
inputRef: React.Ref<HTMLDivElement>
|
||||
dataTestId: string
|
||||
editorClassName?: string
|
||||
editorStyle?: CSSProperties
|
||||
onCompositionEnd: () => void
|
||||
onCompositionStart: () => void
|
||||
onInput: () => void
|
||||
@@ -222,7 +225,7 @@ export function InlineWikilinkEditorField({
|
||||
onClick={onSelectionChange}
|
||||
onKeyUp={onSelectionChange}
|
||||
onMouseUp={onSelectionChange}
|
||||
style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}
|
||||
style={{ ...editorStyle, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}
|
||||
>
|
||||
{segments.map((segment, index) => (
|
||||
segment.kind === 'text'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { CSSProperties } from 'react'
|
||||
import type { VaultEntry } from '../types'
|
||||
import type { NoteReference } from '../utils/ai-context'
|
||||
import { InlineWikilinkInput } from './InlineWikilinkInput'
|
||||
@@ -11,6 +12,8 @@ interface WikilinkChatInputProps {
|
||||
disabled?: boolean
|
||||
placeholder?: string
|
||||
inputRef?: React.RefObject<HTMLDivElement | null>
|
||||
editorClassName?: string
|
||||
editorStyle?: CSSProperties
|
||||
}
|
||||
|
||||
export function WikilinkChatInput({
|
||||
@@ -22,6 +25,8 @@ export function WikilinkChatInput({
|
||||
disabled,
|
||||
placeholder,
|
||||
inputRef,
|
||||
editorClassName,
|
||||
editorStyle,
|
||||
}: WikilinkChatInputProps) {
|
||||
return (
|
||||
<InlineWikilinkInput
|
||||
@@ -33,6 +38,8 @@ export function WikilinkChatInput({
|
||||
disabled={disabled}
|
||||
placeholder={placeholder}
|
||||
inputRef={inputRef}
|
||||
editorClassName={editorClassName}
|
||||
editorStyle={editorStyle}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user