fix: auto-grow textarea using CSS field-sizing: content
Replace JS-based auto-resize with native CSS field-sizing: content. Eliminates timing issues with absolute-positioned containers.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, nextTick } from 'vue'
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import VoiceMicButton from './VoiceMicButton.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -14,8 +14,7 @@ const props = defineProps<{
|
||||
|
||||
const maxH = computed(() => {
|
||||
const lines = props.maxLines ?? 6
|
||||
// line-height is 1.5 at 13px = ~20px per line, plus padding
|
||||
return lines <= 1 ? '20px' : `${lines * 20}px`
|
||||
return lines <= 1 ? '1.5em' : `${lines * 1.5}em`
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -25,14 +24,6 @@ const emit = defineEmits<{
|
||||
}>()
|
||||
|
||||
const input = ref('')
|
||||
const textareaRef = ref<HTMLTextAreaElement | null>(null)
|
||||
|
||||
function adjustHeight() {
|
||||
const el = textareaRef.value
|
||||
if (!el) return
|
||||
el.style.height = 'auto'
|
||||
el.style.height = el.scrollHeight + 'px'
|
||||
}
|
||||
|
||||
const notReady = computed(() => props.terminalReady === false)
|
||||
const isDisabled = computed(() => !input.value.trim() || props.processing || notReady.value)
|
||||
@@ -42,7 +33,6 @@ function handleSend() {
|
||||
if (!msg || props.processing || notReady.value) return
|
||||
emit('send', msg)
|
||||
input.value = ''
|
||||
nextTick(adjustHeight)
|
||||
}
|
||||
|
||||
function handleKeydown(e: KeyboardEvent) {
|
||||
@@ -58,9 +48,6 @@ watch(() => props.voiceTranscript, (newText) => {
|
||||
input.value = newText
|
||||
}
|
||||
})
|
||||
|
||||
// Auto-grow textarea when content changes
|
||||
watch(input, () => nextTick(adjustHeight))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -79,7 +66,6 @@ watch(input, () => nextTick(adjustHeight))
|
||||
</div>
|
||||
<div class="input-container" :class="{ disabled: processing || notReady }">
|
||||
<textarea
|
||||
ref="textareaRef"
|
||||
v-model="input"
|
||||
class="input-field"
|
||||
:style="{ maxHeight: maxH }"
|
||||
@@ -182,7 +168,8 @@ watch(input, () => nextTick(adjustHeight))
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
resize: none;
|
||||
min-height: 20px;
|
||||
field-sizing: content;
|
||||
min-height: 1lh;
|
||||
overflow-y: auto;
|
||||
padding: 0.15rem 0.25rem;
|
||||
font-family: inherit;
|
||||
|
||||
Reference in New Issue
Block a user