diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 8d917213aa3..1eea4fc7e0b 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -95,6 +95,7 @@ export const PromptInput: Component = (props) => { let editorRef!: HTMLDivElement let fileInputRef!: HTMLInputElement let scrollRef!: HTMLDivElement + let popoverRef!: HTMLDivElement const scrollCursorIntoView = () => { const container = scrollRef @@ -437,6 +438,26 @@ export const PromptInput: Component = (props) => { onSelect: handleSlashSelect, }) + // Scroll active item into view in popovers + createEffect(() => { + const activeKey = store.popover === "slash" ? slashActive() : store.popover === "at" ? atActive() : null + if (!activeKey || !popoverRef) return + const element = popoverRef.querySelector(`[data-key="${activeKey}"]`) as HTMLElement | null + if (!element) return + + const styles = getComputedStyle(popoverRef) + const paddingTop = parseFloat(styles.paddingTop) + const paddingBottom = parseFloat(styles.paddingBottom) + const elementTop = element.offsetTop + const elementBottom = elementTop + element.offsetHeight + + if (elementTop < popoverRef.scrollTop + paddingTop) { + popoverRef.scrollTop = elementTop - paddingTop + } else if (elementBottom > popoverRef.scrollTop + popoverRef.clientHeight - paddingBottom) { + popoverRef.scrollTop = elementBottom - popoverRef.clientHeight + paddingBottom + } + }) + createEffect( on( () => prompt.current(), @@ -1354,6 +1375,7 @@ export const PromptInput: Component = (props) => {
(popoverRef = el)} class="absolute inset-x-0 -top-3 -translate-y-full origin-bottom-left max-h-80 min-h-10 overflow-auto no-scrollbar flex flex-col p-2 rounded-md border border-border-base bg-surface-raised-stronger-non-alpha shadow-md" @@ -1367,6 +1389,7 @@ export const PromptInput: Component = (props) => { {(item) => (