Skip to content

Instantly share code, notes, and snippets.

@nimone
Created June 29, 2023 09:33
Show Gist options
  • 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">[email protected]</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>
)
}
@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'>[email protected]</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}


    )}

  • )
    }

    @cristhianreyesp
    Copy link

    Agregen al app.jsx

    import { LayoutDashboard, Home, StickyNote, Layers, Flag, Calendar, LifeBuoy, Settings } from "lucide-react";
    import Sidebar, { SidebarItem } from "./components/Sidebar"

    function App() {

    return (
    <>



    <SidebarItem icon={} text="Home" alert />
    <SidebarItem icon={} text="Dashboard" active />
    <SidebarItem icon={} text="Projects" alert />
    <SidebarItem icon={} text="Calendar" />
    <SidebarItem icon={} text="Tasks" />
    <SidebarItem icon={} text="Reporting" />


    <SidebarItem icon={} text="Settings" />
    <SidebarItem icon={} text="Help" />


    </>
    )
    }

    export default App

    @PrathivKrishnaR
    Copy link

    PrathivKrishnaR commented May 4, 2024

    Vite.+.React.-.Opera.2024-05-04.23-58-36.mp4

    could u update the code

    @haseeb-sheikh10
    Copy link

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

    I am making the ul overflow-y-scroll but it also start scrolling tooltip on x-axis
    what could be the problem? all other code is same

    Uploading Screenshot from 2024-05-11 13-38-05.png…

    @dashingvinit
    Copy link

    I just created a react app added the first thing is this.. it takes the full screen. Should I add something below it so it doesn't take full width ?

    @arthurhamon
    Copy link

    Capture d’écran 2024-07-17 à 12 56 44
    Is their a way to fix the over text that always goes on 2 lines when we have multiple words ?

    @alinscodes
    Copy link

    To fix the FULL SCREEN issue add w-fit to nav element.

    <nav className="h-full w-fit flex flex-col bg-white border-r shadow-sm">

    @masanchez91
    Copy link

    When adding the property overflow-y-auto to enable scrolling, the module names no longer appear when the sidebar is collapsed and the mouse hovers over a module. How can I resolve this issue without modifying the property?

    @ephraim-rpl
    Copy link

    Screenshot 2024-09-29 183233

    so guys i'm new to react ,but why there's nothing on the sidebar?

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