Toggle-able sidebar

This commit is contained in:
2025-10-15 17:41:36 +02:00
parent e6d67a394e
commit 04b8651313
5 changed files with 54 additions and 8 deletions
+4 -3
View File
@@ -9,9 +9,6 @@ import { StringMap } from "@/types/typeUtils";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
import { useMessages } from "@/hooks/use-messages"; import { useMessages } from "@/hooks/use-messages";
// In this testing instance we are assuming that the target's node is localhost
// To make this functional we need to add a settings feature to the api
export default function DMs() { export default function DMs() {
const { id } = useParams<{ id: string }>(); const { id } = useParams<{ id: string }>();
const wsRef = useRef<WebSocket | null>(null); const wsRef = useRef<WebSocket | null>(null);
@@ -19,9 +16,12 @@ export default function DMs() {
const addMessage = useMessages((s) => s.addMessage); const addMessage = useMessages((s) => s.addMessage);
const [userList, setUserList] = useState<StringMap<UserProfile>>({}); const [userList, setUserList] = useState<StringMap<UserProfile>>({});
const [user, setUser] = useState<UserProfile | undefined>(); const [user, setUser] = useState<UserProfile | undefined>();
const [sidebarOpen, setSidebarOpen] = useState(false);
return ( return (
<AppSidebar <AppSidebar
open={sidebarOpen}
setOpen={setSidebarOpen}
addMessage={addMessage} addMessage={addMessage}
wsRef={wsRef} wsRef={wsRef}
userList={userList} userList={userList}
@@ -31,6 +31,7 @@ export default function DMs() {
messages={messages} messages={messages}
> >
<MessageBox <MessageBox
toggleSidebar={() => setSidebarOpen(true)}
channelName={userList[id]?.display_name || id} channelName={userList[id]?.display_name || id}
userList={userList} userList={userList}
setUserList={setUserList} setUserList={setUserList}
+3
View File
@@ -14,9 +14,12 @@ export default function Chat() {
const [userList, setUserList] = useState<StringMap<UserProfile>>({}); const [userList, setUserList] = useState<StringMap<UserProfile>>({});
const messages = useMessages((s) => s.messages); const messages = useMessages((s) => s.messages);
const addMessage = useMessages((s) => s.addMessage); const addMessage = useMessages((s) => s.addMessage);
const [sidebarOpen, setSidebarOpen] = useState(false);
return ( return (
<AppSidebar <AppSidebar
open={sidebarOpen}
setOpen={setSidebarOpen}
wsRef={wsRef} wsRef={wsRef}
userList={userList} userList={userList}
setUserList={setUserList} setUserList={setUserList}
+4
View File
@@ -18,6 +18,7 @@ export default function Server() {
const [userList, setUserList] = useState<StringMap<UserProfile>>({}); const [userList, setUserList] = useState<StringMap<UserProfile>>({});
const messages = useMessages((s) => s.messages); const messages = useMessages((s) => s.messages);
const addMessage = useMessages((s) => s.addMessage); const addMessage = useMessages((s) => s.addMessage);
const [sidebarOpen, setSidebarOpen] = useState(false);
useEffect(() => { useEffect(() => {
if (!ip) return; if (!ip) return;
@@ -26,6 +27,8 @@ export default function Server() {
return ( return (
<AppSidebar <AppSidebar
open={sidebarOpen}
setOpen={setSidebarOpen}
wsRef={wsNodeRef} wsRef={wsNodeRef}
addMessage={() => {}} addMessage={() => {}}
userList={userList} userList={userList}
@@ -33,6 +36,7 @@ export default function Server() {
server={server} server={server}
> >
<MessageBox <MessageBox
toggleSidebar={() => setSidebarOpen(true)}
channelName="General" channelName="General"
userList={userList} userList={userList}
setUserList={setUserList} setUserList={setUserList}
+6 -1
View File
@@ -10,7 +10,7 @@ import {
DropdownMenuContent, DropdownMenuContent,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "./ui/dropdown-menu"; } from "./ui/dropdown-menu";
import { SmilePlusIcon } from "lucide-react"; import { ChevronLeft, ChevronLeftIcon, SmilePlusIcon } from "lucide-react";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { format, isToday, isYesterday } from "date-fns"; import { format, isToday, isYesterday } from "date-fns";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
@@ -144,12 +144,14 @@ export default function MessageBox({
setUserList, setUserList,
sendMessage, sendMessage,
channelName, channelName,
toggleSidebar,
}: { }: {
messages: Message[]; messages: Message[];
userList: NumberMap<UserProfile>; userList: NumberMap<UserProfile>;
setUserList: React.Dispatch<React.SetStateAction<NumberMap<UserProfile>>>; setUserList: React.Dispatch<React.SetStateAction<NumberMap<UserProfile>>>;
sendMessage: (m: string) => void; sendMessage: (m: string) => void;
channelName?: string; channelName?: string;
toggleSidebar: () => void;
}) { }) {
const [text, setText] = useState(""); const [text, setText] = useState("");
@@ -157,7 +159,10 @@ export default function MessageBox({
<div className="h-screen w-full flex flex-col pb-5 pl-5 gap-5"> <div className="h-screen w-full flex flex-col pb-5 pl-5 gap-5">
{channelName && ( {channelName && (
<header className="h-12 py-4 flex items-center border-b text-sm font-semibold"> <header className="h-12 py-4 flex items-center border-b text-sm font-semibold">
<span onClick={toggleSidebar} className="cursor-pointer flex">
<ChevronLeftIcon className="w-5 h-5" />
{channelName} {channelName}
</span>
</header> </header>
)} )}
<div className="w-full flex-1 overflow-y-scroll flex gap-2 flex-col-reverse pr-5"> <div className="w-full flex-1 overflow-y-scroll flex gap-2 flex-col-reverse pr-5">
+35 -2
View File
@@ -35,6 +35,7 @@ import SettingsDialog from "./settings/SettingsDialog";
import Link from "next/link"; import Link from "next/link";
import axios from "axios"; import axios from "axios";
import { get, Response } from "@/lib/request"; import { get, Response } from "@/lib/request";
import { cn } from "@/lib/utils";
export default function AppSidebar({ export default function AppSidebar({
children, children,
@@ -45,6 +46,8 @@ export default function AppSidebar({
server, server,
messages, messages,
addMessage, addMessage,
open,
setOpen,
}: Readonly<{ }: Readonly<{
wsRef: React.RefObject<WebSocket | null>; wsRef: React.RefObject<WebSocket | null>;
addMessage: (msg: Message) => void; addMessage: (msg: Message) => void;
@@ -56,6 +59,8 @@ export default function AppSidebar({
children?: React.ReactNode; children?: React.ReactNode;
setUser?: React.Dispatch<React.SetStateAction<UserProfile | undefined>>; setUser?: React.Dispatch<React.SetStateAction<UserProfile | undefined>>;
server?: Server | undefined; server?: Server | undefined;
open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
}>) { }>) {
const [servers, setServers] = useState<[string, string][]>([]); const [servers, setServers] = useState<[string, string][]>([]);
const [newServer, setNewServer] = useState({ name: "", ip: "" }); const [newServer, setNewServer] = useState({ name: "", ip: "" });
@@ -123,7 +128,28 @@ export default function AppSidebar({
return ( return (
<div className="flex h-screen"> <div className="flex h-screen">
<div className="h-screen flex border-r"> {open && (
<div
className="absolute h-screen w-screen"
onClick={() => setOpen(false)}
/>
)}
{/* <div
className={cn(
"flex h-screen border-r absolute md:static z-50 transform transition-transform duration-300 ease-in-out",
open ? "translate-x-0 opacity-100" : "-translate-x-full opacity-0",
"md:static md:translate-x-0 md:opacity-100 pointer-events-none"
)}
> */}
<div
className={cn(
"flex h-screen border-r transform transition-transform duration-300 ease-in-out",
open
? "translate-x-0 opacity-100"
: "-translate-x-full opacity-0 absolute",
"md:static md:translate-x-0 md:opacity-100 pointer-events-none"
)}
>
<div className="w-16 flex flex-col items-center gap-4 py-4 bg-muted border-r"> <div className="w-16 flex flex-col items-center gap-4 py-4 bg-muted border-r">
<Button <Button
onClick={() => router.push(`/chat`)} onClick={() => router.push(`/chat`)}
@@ -265,9 +291,16 @@ export default function AppSidebar({
</footer> </footer>
</div> </div>
</div> </div>
{open ? (
<div className="w-screen h-full overflow-x-hidden">
<div className="overflow-x-hidden w-screen min-w-max flex-shrink-0">
{children} {children}
</div> </div>
</div>
) : (
children
)}
</div>
); );
} }