Realtime Chat
supabase-ui-library/realtime-chat-nuxtjsFreeBlock
Component which provides a realtime chat interface.
Install it
npx shadcn@latest add https://raw.githubusercontent.com/supabase/supabase/master/apps/ui-library/public/r/realtime-chat-nuxtjs.jsonSource
1<script setup lang="ts">2import { ref, computed, watch } from 'vue'3import { Send } from 'lucide-vue-next'45import ChatMessageItem from './chat-message-item.vue'6import { useChatScroll } from '../composables/useChatScroll'7import {8 useRealtimeChat,9 type ChatMessage,10} from '../composables/useRealtimeChat'11 // @ts-ignore12import Button from '@/components/ui/Button.vue'13 // @ts-ignore14import Input from '@/components/ui/Input.vue'1516interface RealtimeChatProps {17 roomName: string18 username: string19 onMessage?: (messages: ChatMessage[]) => void20 messages?: ChatMessage[]21}2223const props = defineProps<RealtimeChatProps>()2425const initialMessages = computed(() => props.messages ?? [])2627const { containerRef, scrollToBottom } = useChatScroll()2829const { messages: realtimeMessages, sendMessage, isConnected } =30 useRealtimeChat({31 roomName: props.roomName,32 username: props.username,33 })3435const newMessage = ref('')3637/**38 * Merge + dedupe + sort39 */40const allMessages = computed<ChatMessage[]>(() => {41 const merged = [...initialMessages.value, ...realtimeMessages.value]4243 const unique = merged.filter(44 (message, index, self) =>45 index === self.findIndex((m) => m.id === message.id)46 )4748 return unique.sort((a, b) =>49 a.createdAt.localeCompare(b.createdAt)50 )51})5253/**54 * Emit messages to parent if callback provided55 */56watch(allMessages, (messages) => {57 if (props.onMessage) {58 props.onMessage(messages)59 }6061 scrollToBottom()62}, { flush: 'post' })6364function handleSendMessage() {65 if (!newMessage.value.trim() || !isConnected.value) return6667 sendMessage(newMessage.value)68 newMessage.value = ''69}70</script>7172<template>73 <div class="flex flex-col h-full w-full bg-background text-foreground antialiased">74 <!-- Messages -->75 <div76 ref="containerRef"77 class="flex-1 overflow-y-auto p-4 space-y-4"78 >79 <div80 v-if="allMessages.length === 0"81 class="text-center text-sm text-muted-foreground"82 >83 No messages yet. Start the conversation!84 </div>8586 <div class="space-y-1">87 <div88 v-for="(message, index) in allMessages"89 :key="message.id"90 class="animate-in fade-in slide-in-from-bottom-4 duration-300"91 >92 <ChatMessageItem93 :message="message"94 :isOwnMessage="message.user.name === props.username"95 :showHeader="96 !allMessages[index - 1] ||97// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from Supabase UI Library
All 37 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Current User Avatarcurrent-user-avatar-nuxtjs | Supabase UI Library | Blocks | Unverified | 1 dep · 3 files | |
| Current User Avatarcurrent-user-avatar-vue | Supabase UI Library | Blocks | Unverified | 1 dep · 3 files | |
| Dropzone (File Upload) for Nuxt and Supabasedropzone-nuxtjs | Supabase UI Library | Blocks | Unverified | 3 deps · 4 files | |
| Dropzone (File Upload) for Vue and Supabasedropzone-vue | Supabase UI Library | Blocks | Unverified | 3 deps · 4 files | |
| Infinite Query Hookinfinite-query-hook | Supabase UI Library | Blocks | Unverified | 2 deps | |
| Password Based Auth flow for Nextjs and Supabasepassword-based-auth-nextjs | Supabase UI Library | Blocks | Unverified | 2 deps · 17 files | |
| Password Based Auth flow for Nuxt.js and Supabasepassword-based-auth-nuxtjs | Supabase UI Library | Blocks | Unverified | 2 deps · 12 files | |
| Password Based Auth flow for React and Supabasepassword-based-auth-react | Supabase UI Library | Blocks | Unverified | 1 dep · 5 files |
