npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@asafarim/sidebar

v1.2.0

Published

A collapsible sidebar component for React applications

Downloads

22

Readme

@asafarim/sidebar

A flexible and customizable collapsible sidebar component for React applications.

Demo

Sidebar Component Demo

Check out the live demo or view the demo source code

Features

  • 🎯 Fully Collapsible - Smooth toggle between expanded and collapsed states
  • 🎨 Themed - Light and dark theme support
  • 📱 Responsive - Mobile-friendly with overlay support
  • Accessible - Full keyboard navigation and screen reader support
  • 🔧 Flexible - Highly customizable with multiple configuration options
  • 🌲 Nested Items - Support for multi-level navigation hierarchies
  • 🎪 Icons & Badges - Rich visual elements for better UX
  • 📍 Positioning - Left or right sidebar positioning with dynamic toggle
  • 🔘 Optimized Toggle Button - Strategically positioned toggle button at the top of the sidebar

Installation

npm install @asafarim/sidebar
# or
yarn add @asafarim/sidebar
# or
pnpm add @asafarim/sidebar

Version History

  • 1.1.9 - Updated githubPath and demoPath of PackageLinks component
  • 1.1.8 - Updated github pages branch to main
  • 1.1.7 - Updated repository structure (moved to standalone repository)
  • 1.1.6 - Updated publishConfig to public
  • 1.1.5 - Added demo image
  • 1.1.4 - Added demo folder
  • 1.1.3 - Added support for React component icons
  • 1.1.2 - Repositioned toggle button, added support for dynamic sidebar positioning
  • 1.1.1 - Initial stable release

Basic Usage

import { Sidebar } from '@asafarim/sidebar';
import type { SidebarItem } from '@asafarim/sidebar';

const sidebarItems: SidebarItem[] = [
  {
    id: 'dashboard',
    label: 'Dashboard',
    icon: '📊',
    onClick: () => console.log('Dashboard clicked')
  },
  {
    id: 'projects',
    label: 'Projects',
    icon: '📁',
    children: [
      {
        id: 'my-projects',
        label: 'My Projects',
        icon: '📂'
      },
      {
        id: 'shared-projects',
        label: 'Shared Projects',
        icon: '👥',
        badge: 3
      }
    ]
  },
  {
    id: 'settings',
    label: 'Settings',
    icon: '⚙️',
    url: '/settings'
  }
];

function App() {
  return (
    <Sidebar
      items={sidebarItems}
      logo={<span>My App</span>}
      theme="dark"
      onItemClick={(item) => console.log('Clicked:', item.label)}
    />
  );
}

Props

SidebarProps

| Prop | Type | Default | Description | |------|------|---------|-------------| | items | SidebarItem[] | Required | Array of navigation items | | isCollapsed | boolean | undefined | Controlled collapsed state | | onToggle | (collapsed: boolean) => void | undefined | Callback when toggle state changes | | sidebarWidth | string | '280px' | Width when expanded | | collapsedWidth | string | '60px' | Width when collapsed | | className | string | '' | Additional CSS class | | theme | 'light' \| 'dark' | 'light' | Color theme | | position | 'left' \| 'right' | 'left' | Sidebar position | | overlay | boolean | false | Show overlay on mobile | | showToggleButton | boolean | true | Show collapse/expand button | | logo | ReactNode | undefined | Logo/brand element | | footer | ReactNode | undefined | Footer content for the sidebar | | onItemClick | (item: SidebarItem) => void | undefined | Item click handler |

SidebarItem

| Property | Type | Required | Description | |----------|------|----------|-------------| | id | string | ✅ | Unique identifier | | label | string | ✅ | Display text | | icon | string \| ReactNode | ❌ | Icon (emoji, text, or React component) | | url | string | ❌ | Navigation URL | | onClick | () => void | ❌ | Click handler | | children | SidebarItem[] | ❌ | Nested items | | badge | string \| number | ❌ | Notification badge | | disabled | boolean | ❌ | Disabled state |

Examples

Using React Icons

import { Sidebar } from '@asafarim/sidebar';
import type { SidebarItem } from '@asafarim/sidebar';
import { FiHome, FiFolder, FiSettings, FiUsers } from 'react-icons/fi';

const sidebarItemsWithReactIcons: SidebarItem[] = [
  {
    id: 'dashboard',
    label: 'Dashboard',
    icon: <FiHome aria-hidden="true" />,
    onClick: () => console.log('Dashboard clicked')
  },
  {
    id: 'projects',
    label: 'Projects',
    icon: <FiFolder aria-hidden="true" />,
    children: [
      {
        id: 'my-projects',
        label: 'My Projects',
        icon: <FiFolder aria-hidden="true" />
      },
      {
        id: 'shared-projects',
        label: 'Shared Projects',
        icon: <FiUsers aria-hidden="true" />,
        badge: 3
      }
    ]
  },
  {
    id: 'settings',
    label: 'Settings',
    icon: <FiSettings aria-hidden="true" />,
    url: '/settings'
  }
];

function App() {
  return (
    <Sidebar
      items={sidebarItemsWithReactIcons}
      logo={<span>My App</span>}
      theme="dark"
      onItemClick={(item) => console.log('Clicked:', item.label)}
    />
  );
}

Controlled Sidebar

function App() {
  const [collapsed, setCollapsed] = useState(false);

  return (
    <Sidebar
      items={items}
      isCollapsed={collapsed}
      onToggle={setCollapsed}
      theme="dark"
    />
  );
}

With Custom Footer

<Sidebar
  items={items}
  footer={
    <div style={{ textAlign: 'center', padding: '1rem' }}>
      <img src="/avatar.jpg" alt="User" style={{ borderRadius: '50%', width: '40px' }} />
      <div>John Doe</div>
    </div>
  }
/>

Mobile Responsive with Overlay

<Sidebar
  items={items}
  overlay={true}
  theme="light"
  position="left"
/>

Dynamic Sidebar Position with Custom Footer

function App() {
  const [position, setPosition] = useState<'left' | 'right'>('left');
  const [isCollapsed, setIsCollapsed] = useState(false);
  
  // Custom footer with position toggle button
  const footer = (
    <div style={{ display: 'flex', justifyContent: 'space-between', padding: '0.5rem 1rem' }}>
      {!isCollapsed && <p>© 2025 My App</p>}
      <button 
        onClick={() => setPosition(position === 'left' ? 'right' : 'left')}
        aria-label={position === 'left' ? 'Move sidebar to right' : 'Move sidebar to left'}
        style={{ background: 'transparent', border: 'none', cursor: 'pointer' }}
      >
        {position === 'left' ? '❯' : '❮'}
      </button>
    </div>
  );
  
  return (
    <div style={{ display: 'flex', height: '100vh' }}>
      <Sidebar
        items={items}
        isCollapsed={isCollapsed}
        onToggle={setIsCollapsed}
        position={position}
        showToggleButton={true}
        sidebarWidth="260px"
        collapsedWidth="60px"
        theme="dark"
        footer={footer}
        logo={<span>My App</span>}
      />
      <main style={{
        marginLeft: position === 'left' ? (isCollapsed ? '60px' : '260px') : 0,
        marginRight: position === 'right' ? (isCollapsed ? '60px' : '260px') : 0,
        width: `calc(100% - ${isCollapsed ? '60px' : '260px'})`,
        transition: 'margin-left 0.3s ease, margin-right 0.3s ease, width 0.3s ease'
      }}>
        <h1>Main Content</h1>
        <p>Your application content goes here.</p>
      </main>
    </div>
  );
}

Complex Navigation Structure

const complexItems: SidebarItem[] = [
  {
    id: 'workspace',
    label: 'Workspace',
    icon: '🏢',
    children: [
      {
        id: 'overview',
        label: 'Overview',
        icon: '📈'
      },
      {
        id: 'team',
        label: 'Team Members',
        icon: '👥',
        badge: '12'
      },
      {
        id: 'projects',
        label: 'Projects',
        icon: '📁',
        children: [
          {
            id: 'active-projects',
            label: 'Active',
            badge: 5
          },
          {
            id: 'archived-projects',
            label: 'Archived',
            badge: 23
          }
        ]
      }
    ]
  }
];

Toggle Button Positioning

In version 1.1.0, the sidebar toggle button has been repositioned to the top of the icon column for better usability. This provides a more intuitive user experience and follows modern UI patterns.

The toggle button is now:

  • Positioned at the top-left corner of the sidebar (or top-right when position is set to 'right')
  • Styled to match the sidebar theme
  • Easily accessible regardless of sidebar content

This positioning makes it more accessible and visible to users, improving the overall navigation experience.

Sidebar Position Toggle

The sidebar now supports dynamic position toggling between left and right sides of the screen. This can be implemented using a custom footer with a toggle button as shown in the examples above.

When implementing this feature, remember to adjust your main content margins accordingly to maintain proper layout.

Styling

The component uses CSS modules for styling. You can override styles by providing a custom className prop or by targeting the CSS classes directly.

CSS Custom Properties

.sidebar {
  --sidebar-bg: #ffffff;
  --sidebar-text: #374151;
  --sidebar-hover: #f3f4f6;
  --sidebar-active: #dbeafe;
  --sidebar-border: #e5e7eb;
}

.sidebar.dark {
  --sidebar-bg: #1f2937;
  --sidebar-text: #d1d5db;
  --sidebar-hover: #374151;
  --sidebar-active: #1e40af;
  --sidebar-border: #374151;
}

Accessibility

The sidebar component is built with accessibility in mind:

  • Full keyboard navigation support
  • ARIA labels and roles
  • Screen reader friendly
  • Focus management
  • High contrast support

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

Changelog

Version 1.1.7

  • Moved to standalone repository at https://github.com/AliSafari-IT/sidebar
  • Updated demo deployment to GitHub Pages at https://alisafari-it.github.io/sidebar
  • Updated documentation to reflect new repository structure

Version 1.1.6

  • Updated publishConfig to public

Version 1.1.5

  • Added demo image

Version 1.1.4

  • Added demo folder

Version 1.1.3

  • Added support for React component icons (e.g., from react-icons library)
  • Updated type definitions to accept both string and ReactNode for icons
  • Enhanced documentation with React icons examples

Version 1.1.0

  • Repositioned toggle button to the top of the sidebar icon column
  • Added support for dynamic sidebar positioning (left/right)
  • Improved styling for toggle button and sidebar components
  • Updated prop names for better clarity (widthsidebarWidth)
  • Enhanced documentation with new examples

License

MIT