Files
archy/packages/app/src/components/chat/ChatInput.vue
T

74 lines
2.1 KiB
Vue
Raw Normal View History

<template>
<div class="p-3 md:p-4">
<div
class="glass rounded-2xl px-4 py-3 flex items-end gap-3 transition-all duration-300"
:class="isFocused ? 'border-glass-highlight' : ''"
:style="isFocused ? 'box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.22)' : ''"
>
<textarea
ref="textareaRef"
v-model="text"
rows="1"
:placeholder="placeholder"
class="flex-1 resize-none bg-transparent text-sm text-white/90 outline-none placeholder:text-white/25 min-h-[24px] max-h-[120px]"
@focus="isFocused = true"
@blur="isFocused = false"
@keydown.enter.exact.prevent="send"
@input="autoResize"
/>
<button
:disabled="!canSend"
class="shrink-0 glass-button glass-button-sm rounded-xl px-3 transition-all duration-200"
:class="canSend
? 'hover:bg-white/15 active:scale-95'
: 'opacity-30 cursor-not-allowed'"
aria-label="Send message"
@click="send"
>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 12L3.269 3.126A59.768 59.768 0 0121.485 12 59.77 59.77 0 013.27 20.876L5.999 12zm0 0h7.5" />
</svg>
</button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, nextTick } from 'vue'
const props = withDefaults(
defineProps<{
disabled?: boolean
placeholder?: string
}>(),
{
disabled: false,
placeholder: 'Message AIUI...',
}
)
const emit = defineEmits<{
send: [text: string]
}>()
const text = ref('')
const isFocused = ref(false)
const textareaRef = ref<HTMLTextAreaElement | null>(null)
const canSend = computed(() => text.value.trim().length > 0 && !props.disabled)
function send() {
if (!canSend.value) return
emit('send', text.value.trim())
text.value = ''
nextTick(autoResize)
}
function autoResize() {
const el = textareaRef.value
if (!el) return
el.style.height = 'auto'
el.style.height = Math.min(el.scrollHeight, 120) + 'px'
}
</script>