85 lines
1.7 KiB
Vue
85 lines
1.7 KiB
Vue
<script setup lang="ts">
|
|
import StylessButton from "@/components/button/StylessButton.vue";
|
|
import {nextTick, reactive, ref} from "vue";
|
|
import {useScroll, watchArray} from "@vueuse/core";
|
|
|
|
export interface ChatMessage {
|
|
Id: string;
|
|
Sender: string;
|
|
Message: string;
|
|
}
|
|
|
|
const props = defineProps<{
|
|
chats: ChatMessage[]
|
|
}>();
|
|
|
|
const emits = defineEmits<{
|
|
(event: "send", message: string): void
|
|
}>();
|
|
|
|
const chatRef = ref<HTMLElement>();
|
|
const scroll = useScroll(chatRef);
|
|
|
|
const state = reactive<{
|
|
chatInput: string;
|
|
}>({
|
|
chatInput: "",
|
|
});
|
|
|
|
watchArray(props.chats, async () => {
|
|
await nextTick();
|
|
if (scroll.arrivedState.bottom) {
|
|
chatRef.value?.children[chatRef.value.children.length - 1]?.scrollIntoView();
|
|
}
|
|
});
|
|
|
|
const sendChat = () => {
|
|
emits("send", state.chatInput);
|
|
state.chatInput = "";
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<ol ref="chatRef" class="chat-list">
|
|
<li v-for="chat in chats" :key="chat.Id">
|
|
<strong>{{ chat.Sender }}</strong>: {{ chat.Message }}
|
|
</li>
|
|
</ol>
|
|
<form @submit.prevent="sendChat" class="chat-form">
|
|
<label>
|
|
Chat:
|
|
<input v-model="state.chatInput" type="text" autocomplete="off"/>
|
|
</label>
|
|
<StylessButton type="submit">Send</StylessButton>
|
|
</form>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
.chat {
|
|
&-list {
|
|
list-style-type: none;
|
|
word-wrap: break-word;
|
|
overflow: scroll;
|
|
padding: 0;
|
|
|
|
li {
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
}
|
|
|
|
&-form {
|
|
display: grid;
|
|
grid-template-columns: 1fr auto;
|
|
background-color: #2E2E2E;
|
|
padding: 0.5rem;
|
|
border-radius: 0.5rem;
|
|
|
|
input {
|
|
background-color: transparent;
|
|
border: none;
|
|
color: white;
|
|
outline: none;
|
|
}
|
|
}
|
|
}
|
|
</style> |