Skip to content

Instantly share code, notes, and snippets.

@nimone
Created June 29, 2023 09:33
Show Gist options
  • Star 38 You must be signed in to star a gist
  • Fork 15 You must be signed in to fork a gist
  • Save nimone/9204ed6e9d725c0eef003011c9113698 to your computer and use it in GitHub Desktop.
Save nimone/9204ed6e9d725c0eef003011c9113698 to your computer and use it in GitHub Desktop.
Retractable Sidebar Component purely in ReactJS and TailwindCSS
import { MoreVertical, ChevronLast, ChevronFirst } from "lucide-react"
import { useContext, createContext, useState } from "react"
const SidebarContext = createContext()
export default function Sidebar({ children }) {
const [expanded, setExpanded] = useState(true)
return (
<aside className="h-screen">
<nav className="h-full flex flex-col bg-white border-r shadow-sm">
<div className="p-4 pb-2 flex justify-between items-center">
<img
src="https://img.logoipsum.com/243.svg"
className={`overflow-hidden transition-all ${
expanded ? "w-32" : "w-0"
}`}
alt=""
/>
<button
onClick={() => setExpanded((curr) => !curr)}
className="p-1.5 rounded-lg bg-gray-50 hover:bg-gray-100"
>
{expanded ? <ChevronFirst /> : <ChevronLast />}
</button>
</div>
<SidebarContext.Provider value={{ expanded }}>
<ul className="flex-1 px-3">{children}</ul>
</SidebarContext.Provider>
<div className="border-t flex p-3">
<img
src="https://ui-avatars.com/api/?background=c7d2fe&color=3730a3&bold=true"
alt=""
className="w-10 h-10 rounded-md"
/>
<div
className={`
flex justify-between items-center
overflow-hidden transition-all ${expanded ? "w-52 ml-3" : "w-0"}
`}
>
<div className="leading-4">
<h4 className="font-semibold">John Doe</h4>
<span className="text-xs text-gray-600">johndoe@gmail.com</span>
</div>
<MoreVertical size={20} />
</div>
</div>
</nav>
</aside>
)
}
export function SidebarItem({ icon, text, active, alert }) {
const { expanded } = useContext(SidebarContext)
return (
<li
className={`
relative flex items-center py-2 px-3 my-1
font-medium rounded-md cursor-pointer
transition-colors group
${
active
? "bg-gradient-to-tr from-indigo-200 to-indigo-100 text-indigo-800"
: "hover:bg-indigo-50 text-gray-600"
}
`}
>
{icon}
<span
className={`overflow-hidden transition-all ${
expanded ? "w-52 ml-3" : "w-0"
}`}
>
{text}
</span>
{alert && (
<div
className={`absolute right-2 w-2 h-2 rounded bg-indigo-400 ${
expanded ? "" : "top-2"
}`}
/>
)}
{!expanded && (
<div
className={`
absolute left-full rounded-md px-2 py-1 ml-6
bg-indigo-100 text-indigo-800 text-sm
invisible opacity-20 -translate-x-3 transition-all
group-hover:visible group-hover:opacity-100 group-hover:translate-x-0
`}
>
{text}
</div>
)}
</li>
)
}
@lolideppt123
Copy link

lolideppt123 commented Sep 27, 2023

Hi

John Doe

johndoe@gmail.com

Does not work. It's on top. right below the logo.
Thanks

@pmkent
Copy link

pmkent commented Oct 14, 2023

I hd the same issue but I fixed it. Now it shows up where it should but it is blurred.

image

I'm implementing the sidebar in Next.js

@nimone
Copy link
Author

nimone commented Oct 16, 2023

It's kind of weird. The styles shouldn't be a problem.

@yeazullah-aziz
Copy link

I hd the same issue but I fixed it. Now it shows up where it should but it is blurred.

image

I'm implementing the sidebar in Next.js

How?

@fluttermoonger
Copy link

There is an issue here. So when don't giving the aside a width it will fill the whole screen and also when collapsing the width does not change and the padding on the icons change and looks all strange.

Screenshot 2023-12-06 at 09 56 46

Now it has a fixed with of 300px because I set it to that.

@nimone
Copy link
Author

nimone commented Dec 6, 2023

Use max width instead.

@designbyaesthetics
Copy link

There is an issue here. So when don't giving the aside a width it will fill the whole screen and also when collapsing the width does not change and the padding on the icons change and looks all strange.

In line 11, I used 'inline-flex' instead of 'flex'.

@theanmol-raj
Copy link

I hd the same issue but I fixed it. Now it shows up where it should but it is blurred.

image

I'm implementing the sidebar in Next.js

Try Setting the Image property unoptimized to true

@ooerooer
Copy link

nice like lkie like❤️

@MomchilovP
Copy link

I hd the same issue but I fixed it. Now it shows up where it should but it is blurred.

image

I'm implementing the sidebar in Next.js

Have you implemented it in Nextjs? If yes how did you set it up?

@anonymousminati
Copy link

`import { MoreVertical, ChevronLast, ChevronFirst } from "lucide-react";
import { useContext, createContext } from "react";
import { useState } from "react";

const SidebarContext = createContext();

export default function Sidebar({ children }) {
const [expanded, setExpanded] = useState(true);

return (




<img
src="https://img.logoipsum.com/243.svg"
className={overflow-hidden transition-all ${ expanded ? "w-32" : "w-0" }}
alt=""
/>
<button
onClick={() => setExpanded((curr) => !curr)}
className="p-1.5 rounded-lg bg-gray-500 hover:bg-gray-700 border-2 border-green-700"
>
{expanded ? : }

    <SidebarContext.Provider value={{ expanded }}>
      <ul className="flex-1 px-3">{children}</ul>
    </SidebarContext.Provider>

    <div className="border-t flex p-3">
      <img
        src="https://ui-avatars.com/api/?background=c7d2fe&color=3730a3&bold=true"
        alt=""
        className="w-10 h-10 rounded-md"
      />
      <div
        className={`
          flex justify-between items-center
          overflow-hidden transition-all ${expanded ? "w-52 ml-3" : "w-0"}
      `}
      >
        <div className="leading-4">
          <h4 className="font-semibold">John Doe</h4>
          <span className="text-xs text-gray-600">johndoe@gmail.com</span>
        </div>
        <MoreVertical size={20} />
      </div>
    </div>
  </nav>
</aside>

);
}

export function SidebarItem({ icon, text, active, alert }) {
const { expanded } = useContext(SidebarContext);

return (
<li
className={relative flex items-center py-2 px-3 my-1 font-medium rounded-md cursor-pointer transition-colors group ${ active ? "bg-gradient-to-tr from-indigo-200 to-indigo-100 text-indigo-800" : "hover:bg-black text-gray-200" }}
>
{icon}
<span
className={overflow-hidden transition-all ${ expanded ? "w-52 ml-3" : "w-0" }}
>
{text}

{alert && (
<div
className={absolute right-2 w-2 h-2 rounded bg-indigo-400 ${ expanded ? "" : "top-2" }}
/>
)}

  {!expanded && (
    <div
      className={`
      absolute left-full rounded-md px-2 py-1 ml-6
      bg-gray-500 text-indigo-800 text-sm
      invisible opacity-20 -translate-x-3 transition-all
      group-hover:visible group-hover:opacity-100 group-hover:translate-x-0
  `}
    >
      {text}
    </div>
  )}
</li>

);
}
`

`"use client";

import { Inter } from "next/font/google";
import "./globals.css";
import Sidebar, { SidebarItem } from "./components/sidebar";
import { useRouter } from "next/navigation";
import { LayoutDashboard } from "lucide-react";

const inter = Inter({ subsets: ["latin"] });

export default function RootLayout({ children }) {
const router = useRouter();
return (



      <SidebarItem icon={<LayoutDashboard size={20} />} text={"Dashboard"} active />
      <SidebarItem icon={<LayoutDashboard size={20} />} text={"hell"} />
      <SidebarItem icon={<LayoutDashboard size={20} />} text={"ad"} />
      <SidebarItem icon={<LayoutDashboard size={20} />} text={"gd"} />
      <SidebarItem icon={<LayoutDashboard size={20} />} text={"g"} />
      <SidebarItem icon={<LayoutDashboard size={20} />} text={"Dashgaboard"} />

    </Sidebar>
  </aside>
  <main className="flex flex-col  overflow-y-scroll h-screen w-full flex-grow p-4">
    {children}
  </main>
</div>

);
}
`

image

i am clicking on other menu buttons but they are not highliging and also sidebar expanded is not toggling

@P0IW
Copy link

P0IW commented Feb 3, 2024

2024-02-03.01-34-56.mp4

what could be the problem here ?

@anonymousminati
Copy link

anonymousminati commented Feb 3, 2024 via email

@DavOlufuwa
Copy link

2024-02-03.01-34-56.mp4
what could be the problem here ?

Add a "h-0" to the "w-0" on the other side of the ternary of the span element in the SidebarItem

        <span
          className={`overflow-hidden transition-all ${
            expanded ? "w-52 ml-3" : "w-0 h-0"
          }`}
        >
          {text}
        </span> ```

@Siajey
Copy link

Siajey commented Mar 17, 2024

Sidebar.mp4

hi friends i just worked on this Sidebar and i fixed the problems - i will leave a Preview video of it - u can use the code and save time `//SiaJey
import { MoreVertical, ChevronLast, ChevronFirst } from 'lucide-react'
import { useContext, createContext, useState } from 'react'

const SidebarContext = createContext()

export default function Sidebar({ children }) {
const [expanded, setExpanded] = useState(true)

return (




<img
src='https://img.logoipsum.com/243.svg'
className={overflow-hidden transition-all ${ expanded ? 'w-32 opacity-90' : 'w-0' }}
alt=''
/>
<button
onClick={() => setExpanded((curr) => !curr)}
className='rounded-lg bg-gray-50 hover:bg-gray-100'
>
{expanded ? : }

    <SidebarContext.Provider value={{ expanded }}>
      <div>
        <ul
          className={` rounded-lg transition-all ${
            expanded ? 'bg-[#333333] opacity-90' : 'w-[40px]'
          }`}
        >
          {children}
        </ul>
      </div>
    </SidebarContext.Provider>

    <div className='flex p-3 bg-[#FFE328] rounded-lg'>
      <img
        src='https://ui-avatars.com/api/?background=c7d2fe&color=3730a3&bold=true'
        alt=''
        className='w-10 h-10 rounded-md'
      />
      <div
        className={`
          flex justify-between items-center
          overflow-hidden transition-all ${expanded ? 'w-52 ml-3' : 'w-0'}
      `}
      >
        <div className='leading-4'>
          <h4 className='font-semibold'>John Doe</h4>
          <span className='text-xs text-gray-600'>johndoe@gmail.com</span>
        </div>
        <MoreVertical size={20} />
      </div>
    </div>
  </nav>
</aside>

)
}

export function SidebarItem({ icon, text, active, alert }) {
const { expanded } = useContext(SidebarContext)

return (
<li
className={relative flex items-center py-2 px-3 my-1 font-medium rounded-md cursor-pointer transition-colors group ${ active ? 'bg-gradient-to-tr from-indigo-200 to-indigo-100 text-indigo-800' : 'hover:bg-indigo-50 text-gray-600' }}
>
{icon}
<span
className={overflow-hidden transition-all ${ expanded ? 'w-52 ml-3' : 'w-0' }}
>
{text}

{alert && (
<div
className={absolute right-2 w-2 h-2 rounded bg-indigo-400 ${ expanded ? '' : 'top-2' }}
/>
)}

  {!expanded && (
    <div
      className={`
      absolute left-full rounded-md px-2 py-1 ml-6
      bg-indigo-100 text-indigo-800 text-sm
      invisible opacity-20 -translate-x-3 transition-all
      group-hover:visible group-hover:opacity-100 group-hover:translate-x-0
  `}
    >
      {text}
    </div>
  )}
</li>

)
}

`

@Siajey
Copy link

Siajey commented Mar 17, 2024

i leave the code correctly i think there is a problem with this comment system of github that modify my code like this - soryy

@obuastella
Copy link

please can you try sending the full code again.. i am still having issues with it

@Siajey
Copy link

Siajey commented Mar 29, 2024

hi friend yes ill paste it here again

@Siajey
Copy link

Siajey commented Mar 29, 2024

import { MoreVertical, ChevronLast, ChevronFirst } from 'lucide-react'
import { useContext, createContext, useState } from 'react'

const SidebarContext = createContext()

export default function Sidebar({ children }) {
const [expanded, setExpanded] = useState(true)

return (

<img
src='https://img.logoipsum.com/243.svg'
className={overflow-hidden transition-all ${ expanded ? 'w-32 opacity-90' : 'w-0' }}
alt=''
/>
<button
onClick={() => setExpanded((curr) => !curr)}
className='rounded-lg bg-gray-50 hover:bg-gray-100'

{expanded ? : }

<SidebarContext.Provider value={{ expanded }}>
  <div>
    <ul
      className={` rounded-lg transition-all ${
        expanded ? 'bg-[#333333] opacity-90' : 'w-[40px]'
      }`}
    >
      {children}
    </ul>
  </div>
</SidebarContext.Provider>

<div className='flex p-3 bg-[#FFE328] rounded-lg'>
  <img
    src='https://ui-avatars.com/api/?background=c7d2fe&color=3730a3&bold=true'
    alt=''
    className='w-10 h-10 rounded-md'
  />
  <div
    className={`
      flex justify-between items-center
      overflow-hidden transition-all ${expanded ? 'w-52 ml-3' : 'w-0'}
  `}
  >
    <div className='leading-4'>
      <h4 className='font-semibold'>John Doe</h4>
      <span className='text-xs text-gray-600'>johndoe@gmail.com</span>
    </div>
    <MoreVertical size={20} />
  </div>
</div>

)
}

export function SidebarItem({ icon, text, active, alert }) {
const { expanded } = useContext(SidebarContext)

return (

  • {icon} {text}

    {alert && (

    )}

    {!expanded && (
    <div
    className={absolute left-full rounded-md px-2 py-1 ml-6 bg-indigo-100 text-indigo-800 text-sm invisible opacity-20 -translate-x-3 transition-all group-hover:visible group-hover:opacity-100 group-hover:translate-x-0}
    >
    {text}


    )}

  • )
    }

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment