skip to Main Content

Im making a chat app. I have a sidebar which displays the chats with your already created conversations. I want to make this sidebar responsive (like closing and opening it on mobile)

I have this code (Sidebar.tsx):

import React, { Suspense } from 'react'
import Chats from './Chats'
import ChatsSkeleton from './ChatsSkeleton'
import AddButton from './AddButton'

export default function Sidebar() {
  return (
    <aside className="w-[400px] bg-gray-900 h-[calc(100vh-100px)] mt-[30px] flex flex-col p-4 gap-3 rounded-r-xl max-[700px]:fixed z-10">
        <div className='flex items-center justify-between'>
            <h1 className="text-2xl">Conversations</h1>
            <AddButton />
        </div>

        <Suspense fallback={<ChatsSkeleton />} children={<Chats />}>
        </Suspense>
    </aside>
  )
}

Also I have the Chats.tsx component where it fetches all the data:

import React from 'react'
import Chat from './Chat';
import { getServerSession } from 'next-auth';
import { authOptions } from '../utils/auth';
import { getChats } from '../actions';

export default async function Chats() {
    const chats = await getChats();
    const session = await getServerSession(authOptions);

    return (
        <div>
            {chats.map((chat: any) => (
                <Chat
                    key={chat.id}
                    name={chat.users.filter((user: any) => user.id !== session?.user.id)[0].name}
                    id={chat.id}
                    image={chat.users.filter((user: any) => user.id !== session?.user.id)[0].imageUrl}
                    lastMessage={chat.messages.length > 0 ? chat.messages[chat.messages.length - 1].text : 'No messages yet...'}
                />
            ))}
        </div>
    )
}

The data is being fetched with a new Server Action (actions.ts):

"use server"

import { getServerSession } from "next-auth";
import { revalidatePath } from "next/cache"
import { authOptions } from "./utils/auth";

export async function getChats() {
    const session = await getServerSession(authOptions);

    const res = await fetch('http://localhost:8000/api/chats/', {
        headers: {
            'authorization': session?.user.token as string,
            'Content-Type': 'application/json'
        },
        next: {
            tags: ['chats']
        }
    })

    // handle unauthorized
    if (res.status === 401) {
        return []
    }

    const { data } = await res.json()

    return data
}

How can i do this?

2

Answers


  1. Chosen as BEST ANSWER

    Anyways, I turned my component to a Client Component instead. Its a little bit slower but its okay i think.


  2. As I understood, you want to implement it like a hamburger menu and toggle it on and off by using a button.

    You can do it by using the state hook (call it a drawer). Here is a simplified example (in JavaScript):

    import { Menu2 as MenuIcon, X as XIcon } from "tabler-icons-react";
    
    const [drawer, setDrawer] = useState(false);
    
    return (
      <div>
        <div>
          <button
            onClick={() => {
              setDrawer(true);
            }}
          >
            <MenuIcon />
          </button>
        </div>
    
        {/* DRAWER */}
        {drawer && (
          <div>
            <div>
              <p className="text-2xl">Menu</p>
    
              <button
                onClick={() => {
                  setDrawer(false);
                }}
              >
                <XIcon />
              </button>
            </div>
            {/* REST OF THE SIDEBAR ITEMS */}
          )}
    
        {/* DESKTOP SIDEBAR ITEMS */}
        </div>
      </div>
    );
    

    This code is not ready for copy-paste to your code but it can show an examle for how to close and open it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search