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

@darksnow-ui/nav-sidebar

v0.0.2

Published

Collapsible navigation sidebar component for DarkSnow UI

Readme

Sidebar Component

Componente de sidebar híbrido profissional com suporte para collapsed/expanded, submenus expansíveis, badges tipados e tooltips.

Recursos

  • 🎯 Estados collapsed/expanded com transições suaves
  • 📁 Submenus expansíveis com animação e caret rotativo
  • 🏷️ Sistema de badges com 4 tipos (info, success, warning, danger)
  • 💬 Tooltips inteligentes no modo collapsed
  • 🎨 Totalmente customizável via classes CSS
  • 🌓 Suporte completo para dark mode
  • Acessível com suporte a teclado
  • 🚀 Performance otimizada com lazy rendering

Instalação

O componente já usa dependências instaladas no projeto:

  • @radix-ui/react-tooltip
  • react-router-dom
  • clsx

Uso Básico

import { Sidebar } from "@/components/sidebar";
import { Home, Users, Settings, Menu, X } from "lucide-react";

const iconMap = {
  home: Home,
  users: Users,
  settings: Settings,
  menu: Menu,
  "menu-open": X,
};

const menuItems = [
  {
    id: "home",
    label: "Home",
    icon: "home",
    href: "/",
  },
  {
    id: "users",
    label: "Usuários",
    icon: "users",
    href: "/users",
    badge: 5,
    badgeType: "info", // info | success | warning | danger
  },
  {
    id: "reports",
    label: "Relatórios",
    icon: "reports",
    badge: "!",
    badgeType: "warning",
    children: [
      {
        id: "reports-sales",
        label: "Vendas",
        icon: "chart",
        href: "/reports/sales",
      },
      {
        id: "reports-analytics",
        label: "Analytics",
        icon: "analytics",
        href: "/reports/analytics",
        badge: "New",
        badgeType: "success",
      },
    ],
  },
];

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

  return (
    <Sidebar
      items={menuItems}
      collapsed={collapsed}
      onCollapsedChange={setCollapsed}
      resolveIcon={(name) => iconMap[name as keyof typeof iconMap]}
      hamburger={{
        enabled: true,
        icon: "menu",
        expandedIcon: "menu-open",
        label: "Menu Principal",
      }}
    />
  );
}

Props

SidebarProps

| Prop | Tipo | Descrição | | ------------------- | --------------------------------------- | ---------------------------------- | | items | MenuItem[] | Lista de items do menu | | collapsed | boolean? | Estado collapsed (controlado) | | onCollapsedChange | (collapsed: boolean) => void? | Callback para mudança de estado | | resolveIcon | (name: string) => React.ComponentType | Função para resolver ícones | | hamburger | HamburgerConfig? | Configuração do botão hamburger | | className | string? | Classes para o container principal | | classNames | ClassNames? | Classes para elementos internos |

MenuItem

interface MenuItem {
  id: string;
  label: string;
  icon: string;
  href?: string;
  action?: () => void;
  children?: MenuItem[];
  disabled?: boolean;
  badge?: string | number;
  badgeType?: "danger" | "info" | "success" | "warning";
}

HamburgerConfig

interface HamburgerConfig {
  enabled: boolean;
  icon?: string; // default: "menu"
  expandedIcon?: string; // default: "menu-open"
  label?: string; // default: "Menu"
}

ClassNames

interface ClassNames {
  root?: string; // Container principal
  nav?: string; // Elemento nav
  item?: string; // Item do menu
  itemActive?: string; // Item ativo
  itemDisabled?: string; // Item desabilitado
  icon?: string; // Container do ícone
  label?: string; // Label do item
  badge?: string; // Badge
  hamburger?: string; // Botão hamburger
  submenu?: string; // Dropdown submenu
}

Comportamentos

Modo Collapsed (60px largura)

  • Items sem children: mostram tooltip ao hover
  • Items com children e href: mostram dropdown flutuante ao hover
  • Items com children sem href: ao clicar, expandem o sidebar e abrem o submenu
  • Badges aparecem no canto inferior direito do ícone (máx. 4 caracteres)
  • Largura: 60px

Modo Expanded (256px largura)

  • Items mostram ícone + label + badge (se houver)
  • Items com children mostram caret que rotaciona ao expandir
  • Submenus aparecem com animação slideDown
  • Clicar em item com children toggle o submenu
  • Largura padrão: 256px (w-64)

Sistema de Badges

  • Tipos disponíveis: info (azul), success (verde), warning (amarelo), danger (vermelho)
  • Modo collapsed: Badge pequeno no canto inferior direito do ícone
  • Modo expanded: Badge à direita do label com cores suaves
  • Suporta: números e strings (ex: "999+", "New", "!")

Navegação

  • Integrado com React Router
  • Detecta automaticamente item ativo baseado na URL
  • Suporta tanto href (Link) quanto action (button)
  • Items ativos têm destaque visual

Exemplos Avançados

Com Actions e Badges Tipados

const items = [
  {
    id: "notifications",
    label: "Notificações",
    icon: "bell",
    badge: 12,
    badgeType: "info",
    action: () => openNotifications(),
  },
  {
    id: "errors",
    label: "Erros",
    icon: "alert",
    badge: "!",
    badgeType: "danger",
    href: "/errors",
  },
  {
    id: "updates",
    label: "Atualizações",
    icon: "download",
    badge: "New",
    badgeType: "success",
    children: [
      {
        id: "update-system",
        label: "Sistema",
        icon: "settings",
        action: () => checkUpdates(),
      },
    ],
  },
];

Item Apenas Container (sem href)

const items = [
  {
    id: "management",
    label: "Gerenciamento",
    icon: "folder",
    // Sem href - ao clicar quando collapsed, expande o sidebar
    children: [
      {
        id: "users",
        label: "Usuários",
        icon: "users",
        href: "/management/users",
      },
      {
        id: "roles",
        label: "Perfis",
        icon: "shield",
        href: "/management/roles",
      },
    ],
  },
];

Customização de Estilos

<Sidebar
  items={items}
  className="shadow-lg"
  classNames={{
    item: "rounded-lg mx-2",
    itemActive: "bg-blue-500 text-white",
    itemActiveIcon: "text-white",
    badge: "font-bold",
    hamburger: "border-b-2 border-gray-200",
    submenu: "bg-gray-50 rounded-lg",
  }}
/>

Estado Não Controlado

// Sidebar gerencia próprio estado
<Sidebar
  items={items}
  resolveIcon={resolveIcon}
  hamburger={{
    enabled: true,
    label: "Menu",
  }}
/>

Separadores e Organização

const items = [
  // Items principais
  { id: "home", label: "Home", icon: "home", href: "/" },
  { id: "dashboard", label: "Dashboard", icon: "chart", href: "/dashboard" },

  // Separador com items de configuração
  {
    id: "bottom-section",
    icon: "", // Sem ícone
    label: "", // Sem label
    children: [
      {
        id: "settings",
        label: "Configurações",
        icon: "settings",
        href: "/settings",
      },
      { id: "help", label: "Ajuda", icon: "help", href: "/help" },
    ],
  },
];