Chat changes
This commit is contained in:
@ -36,6 +36,7 @@ export default function Chat() {
|
|||||||
} else {
|
} else {
|
||||||
setMessages((prev) => [...prev, data]);
|
setMessages((prev) => [...prev, data]);
|
||||||
|
|
||||||
|
// Auto-scroll to bottom on new message
|
||||||
const chatBox = document.getElementById("chat-messages");
|
const chatBox = document.getElementById("chat-messages");
|
||||||
if (chatBox) {
|
if (chatBox) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -73,19 +74,21 @@ export default function Chat() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="w-full max-w-4xl mx-auto bg-dark rounded-lg shadow-lg overflow-hidden border border-gray-800">
|
<div class="w-full max-w-4xl mx-auto bg-[#1E2127] rounded-lg shadow-lg overflow-hidden border border-gray-800 flex flex-col h-[calc(100vh-180px)] md:h-[600px]">
|
||||||
|
{/* Header */}
|
||||||
<div class="p-4 bg-secondary text-white">
|
<div class="p-4 bg-secondary text-white">
|
||||||
<h2 class="text-xl font-bold">Live Chat</h2>
|
<h2 class="text-2xl font-bold">Live Chat</h2>
|
||||||
<p class="text-sm opacity-80">
|
<p class="text-sm">
|
||||||
{isConnected
|
{isConnected
|
||||||
? `${userCount} online • Messages are not saved`
|
? `${userCount} online • Messages are not saved`
|
||||||
: "Connecting..."}
|
: "Connecting..."}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Chat messages area */}
|
||||||
<div
|
<div
|
||||||
id="chat-messages"
|
id="chat-messages"
|
||||||
class="p-4 h-96 overflow-y-auto bg-dark text-gray-300"
|
class="flex-grow overflow-y-auto bg-[#1E2127] text-gray-300 p-4"
|
||||||
>
|
>
|
||||||
{messages.length === 0
|
{messages.length === 0
|
||||||
? (
|
? (
|
||||||
@ -97,7 +100,7 @@ export default function Chat() {
|
|||||||
messages.map((msg, i) => (
|
messages.map((msg, i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
class={`mb-3 max-w-md ${
|
class={`mb-3 max-w-[85%] ${
|
||||||
msg.sender === username ? "ml-auto" : ""
|
msg.sender === username ? "ml-auto" : ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
@ -112,44 +115,44 @@ export default function Chat() {
|
|||||||
<span class="font-bold text-sm">
|
<span class="font-bold text-sm">
|
||||||
{msg.sender === username ? "You" : msg.sender}
|
{msg.sender === username ? "You" : msg.sender}
|
||||||
</span>
|
</span>
|
||||||
<span class="text-xs opacity-70">
|
<span class="text-xs opacity-70 ml-2">
|
||||||
{new Date(msg.timestamp).toLocaleTimeString([], {
|
{new Date(msg.timestamp).toLocaleTimeString([], {
|
||||||
hour: "2-digit",
|
hour: "2-digit",
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p>{msg.text}</p>
|
<p class="break-words">{msg.text}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form onSubmit={sendMessage} class="p-4 border-t border-gray-800">
|
{/* Input area */}
|
||||||
<div class="flex">
|
<div class="p-3 border-t border-gray-800 pb-6 md:pb-3">
|
||||||
|
<form onSubmit={sendMessage} class="relative">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={newMessage}
|
value={newMessage}
|
||||||
onChange={(e) => setNewMessage(e.currentTarget.value)}
|
onChange={(e) => setNewMessage(e.currentTarget.value)}
|
||||||
placeholder="Type your message..."
|
placeholder="Type your message..."
|
||||||
class="flex-1 px-4 py-3 bg-gray-800 text-white rounded-l-lg border-0 focus:outline-none focus:ring-2 focus:ring-secondary placeholder-gray-500"
|
class="w-full pl-4 pr-20 py-3 bg-gray-800 text-white rounded-lg border-0 focus:outline-none focus:ring-1 focus:ring-secondary placeholder-gray-500"
|
||||||
disabled={!isConnected}
|
disabled={!isConnected}
|
||||||
maxLength={2000}
|
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
class="bg-secondary text-white px-8 py-3 rounded-r-lg hover:bg-opacity-90 focus:outline-none focus:ring-2 focus:ring-secondary font-medium"
|
class="absolute right-0 top-0 h-full bg-secondary text-white px-5 rounded-r-lg font-medium"
|
||||||
disabled={!isConnected || !newMessage.trim()}
|
disabled={!isConnected || !newMessage.trim()}
|
||||||
>
|
>
|
||||||
Send
|
Send
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</form>
|
||||||
<p class="mt-2 text-xs text-gray-500">
|
<p class="mt-2 text-xs text-gray-500">
|
||||||
You are chatting as{" "}
|
You are chatting as{" "}
|
||||||
<span class="font-medium text-gray-400">{username}</span>
|
<span class="font-medium text-gray-400">{username}</span>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// islands/NavigationBar.tsx
|
|
||||||
import { useComputed, useSignal } from "@preact/signals";
|
import { useComputed, useSignal } from "@preact/signals";
|
||||||
import { useEffect } from "preact/hooks";
|
import { useEffect } from "preact/hooks";
|
||||||
import {
|
import {
|
||||||
@ -54,8 +53,8 @@ export default function NavigationBar({ currentPath }: NavigationBarProps) {
|
|||||||
isScrolling.value ? "opacity-30" : "opacity-100"
|
isScrolling.value ? "opacity-30" : "opacity-100"
|
||||||
} ${isVisible.value ? "translate-y-0" : "translate-y-20"}`}
|
} ${isVisible.value ? "translate-y-0" : "translate-y-20"}`}
|
||||||
>
|
>
|
||||||
<ul class="menu menu-horizontal bg-base-200 rounded-box p-2 shadow-lg gap-2">
|
<ul class="menu menu-horizontal bg-base-200 rounded-box p-2 shadow-lg flex flex-nowrap whitespace-nowrap overflow-x-auto">
|
||||||
<li>
|
<li class="mx-1">
|
||||||
<a href="/" class={currentPath === "/" ? "menu-active" : ""}>
|
<a href="/" class={currentPath === "/" ? "menu-active" : ""}>
|
||||||
<div class="tooltip" data-tip="Home">
|
<div class="tooltip" data-tip="Home">
|
||||||
<LuHouse class="text-xl" />
|
<LuHouse class="text-xl" />
|
||||||
@ -63,7 +62,7 @@ export default function NavigationBar({ currentPath }: NavigationBarProps) {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li class="mx-1">
|
||||||
<a
|
<a
|
||||||
href="/posts"
|
href="/posts"
|
||||||
class={isPostsPath(currentPath) ? "menu-active" : ""}
|
class={isPostsPath(currentPath) ? "menu-active" : ""}
|
||||||
@ -74,7 +73,7 @@ export default function NavigationBar({ currentPath }: NavigationBarProps) {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li class="mx-1">
|
||||||
<a
|
<a
|
||||||
href="/projects"
|
href="/projects"
|
||||||
class={currentPath.startsWith("/projects") ? "menu-active" : ""}
|
class={currentPath.startsWith("/projects") ? "menu-active" : ""}
|
||||||
@ -85,7 +84,7 @@ export default function NavigationBar({ currentPath }: NavigationBarProps) {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li class="mx-1">
|
||||||
<a
|
<a
|
||||||
href="/chat"
|
href="/chat"
|
||||||
class={currentPath.startsWith("/chat") ? "menu-active" : ""}
|
class={currentPath.startsWith("/chat") ? "menu-active" : ""}
|
||||||
|
@ -2,14 +2,19 @@ import Chat from "../islands/Chat.tsx";
|
|||||||
|
|
||||||
export default function ChatPage() {
|
export default function ChatPage() {
|
||||||
return (
|
return (
|
||||||
<div class="min-h-screen p-4 sm:p-8">
|
<div class="min-h-screen p-4 pb-24">
|
||||||
<h1 class="text-3xl sm:text-4xl font-bold text-secondary mb-6 sm:mb-8 text-center">
|
<div class="flex items-center justify-center mb-6">
|
||||||
Chat Room <div className="badge badge-dash badge-primary">Demo</div>
|
<h1 class="text-3xl font-bold text-secondary">Chat Room</h1>
|
||||||
</h1>
|
<span class="ml-3 border border-pink-500 text-pink-500 rounded-full px-3 py-1 text-sm">
|
||||||
|
Demo
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<Chat />
|
<Chat />
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-8 text-center text-sm text-gray-500">
|
|
||||||
|
<div class="mt-4 text-center text-xs text-gray-500 mb-20">
|
||||||
<p>
|
<p>
|
||||||
This is an ephemeral chat room. Messages are only visible to users
|
This is an ephemeral chat room. Messages are only visible to users
|
||||||
currently online and aren't stored after you leave.
|
currently online and aren't stored after you leave.
|
||||||
|
Reference in New Issue
Block a user