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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@titusjin/universal-header-module

v1.1.1

Published

A comprehensive React universal header component with theme management, sidebar integration, and authentication display

Readme

Universal Header Module

A comprehensive React universal header component for modern web applications with theme management, sidebar integration, user authentication display, and responsive design.

📋 Table of Contents

Installation

npm install @titusjin/universal-header-module

Quick Start

import UniversalHeader from '@titusjin/universal-header-module';
import '@titusjin/universal-header-module/dist/styles.css';

function App() {
  return <UniversalHeader logoSrc='/your-logo.png' logoAlt='Your Company' />;
}

🏗️ Code Structure

module_universalHeader/
├── src/
│   ├── universalHeader.tsx    # Main component implementation
│   ├── styles.module.scss     # Component styles with CSS modules
│   ├── example.tsx            # Example usage component
│   └── index.ts               # Module exports
├── dist/                      # Built files (auto-generated)
├── package.json               # Module dependencies and metadata
├── tsconfig.json             # TypeScript configuration
├── rollup.config.js          # Build configuration
└── README.md                 # This documentation

Component Architecture

UniversalHeader
├── Logo Section (Clickable)
├── Navigation Area (Extensible)
├── User Controls
│   ├── Theme Toggle (Dark/Light)
│   ├── User Info Display
│   └── Logout Button
└── Sidebar Toggle (Hamburger Menu)

🎯 Trigger Points & Integration

1. Theme Toggle Trigger

  • When: User clicks sun/moon icon
  • Action: Toggles between light and dark themes
  • Persistence: Automatically saves preference to localStorage
  • CSS Variables: Updates global CSS custom properties
// Theme toggle automatically handles:
document.documentElement.setAttribute('data-theme', 'dark'); // or 'light'
localStorage.setItem('theme', 'dark');

2. Sidebar Integration Trigger

  • When: User clicks hamburger menu (☰)
  • Action: Calls sidebarContext.toggleSidebar()
  • Integration Point: Connect to your sidebar state management
const sidebarContext = {
  isSidebarOpen: false,
  toggleSidebar: () => setSidebarOpen(!sidebarOpen),
  openSidebar: () => setSidebarOpen(true),
  closeSidebar: () => setSidebarOpen(false),
};

3. Navigation Trigger

  • When: User clicks logo or home button
  • Action: Calls onNavigateHome() callback
  • Integration Point: Connect to your routing system
// Next.js integration
const handleNavigateHome = () => {
  router.push('/dashboard');
};

// React Router integration
const handleNavigateHome = () => {
  navigate('/');
};

4. Authentication Trigger

  • When: User clicks logout button
  • Action: Calls onLogout() callback
  • Integration Point: Connect to your auth system
const handleLogout = async () => {
  await authService.logout();
  dispatch(clearUserData());
  router.push('/login');
};

📚 Usage Examples

1. Minimal Setup (No Authentication)

import UniversalHeader from '@titusjin/universal-header-module';
import '@titusjin/universal-header-module/dist/styles.css';

function BasicApp() {
  return (
    <UniversalHeader
      logoSrc='/company-logo.svg'
      logoAlt='My Company'
      showSidebarToggle={false} // Hide sidebar toggle if no sidebar
    />
  );
}

2. E-commerce Application Integration

import { useState } from 'react';

import { useRouter } from 'next/navigation';

import UniversalHeader from '@titusjin/universal-header-module';

const EcommerceHeader = () => {
  const router = useRouter();
  const [isSidebarOpen, setIsSidebarOpen] = useState(false);

  // User data from your auth context/store
  const user = useUser(); // Your auth hook

  const sidebarContext = {
    isSidebarOpen,
    toggleSidebar: () => setIsSidebarOpen(!isSidebarOpen),
    openSidebar: () => setIsSidebarOpen(true),
    closeSidebar: () => setIsSidebarOpen(false),
  };

  const handleLogout = async () => {
    await signOut(); // Your auth function
    router.push('/login');
  };

  const handleNavigateHome = () => {
    router.push('/dashboard');
  };

  return (
    <>
      <UniversalHeader
        loginInfo={
          user
            ? {
                email: user.email,
                name: `${user.firstName} ${user.lastName}`,
                role: user.role,
              }
            : null
        }
        onLogout={handleLogout}
        onNavigateHome={handleNavigateHome}
        sidebarContext={sidebarContext}
        logoSrc='/store-logo.png'
        logoAlt='My Store'
        showThemeToggle={true}
        showSidebarToggle={true}
        className='ecommerce-header'
      />

      {/* Your sidebar component */}
      {isSidebarOpen && <Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />}
    </>
  );
};

3. Admin Dashboard Integration

import { logout, selectCurrentUser } from '@/store/authSlice';
import { useAppDispatch, useAppSelector } from '@/store/hooks';
import { selectSidebarState, toggleSidebar } from '@/store/uiSlice';

const AdminHeader = () => {
  const dispatch = useAppDispatch();
  const currentUser = useAppSelector(selectCurrentUser);
  const { isSidebarOpen } = useAppSelector(selectSidebarState);

  const sidebarContext = {
    isSidebarOpen,
    toggleSidebar: () => dispatch(toggleSidebar()),
    openSidebar: () => dispatch(openSidebar()),
    closeSidebar: () => dispatch(closeSidebar()),
  };

  const handleLogout = () => {
    dispatch(logout());
  };

  const handleNavigateHome = () => {
    window.location.href = '/admin/dashboard';
  };

  return (
    <UniversalHeader
      loginInfo={currentUser}
      onLogout={handleLogout}
      onNavigateHome={handleNavigateHome}
      sidebarContext={sidebarContext}
      logoSrc='/admin-logo.png'
      logoAlt='Admin Panel'
    />
  );
};

4. Multi-tenant Application

interface TenantConfig {
  logoSrc: string;
  logoAlt: string;
  themeBrand: string;
}

const MultiTenantHeader = ({ tenantConfig }: { tenantConfig: TenantConfig }) => {
  const { user, logout } = useAuth();
  const { isSidebarOpen, toggleSidebar } = useSidebar();

  // Apply tenant-specific theming
  useEffect(() => {
    document.documentElement.style.setProperty('--brand-primary', tenantConfig.themeBrand);
  }, [tenantConfig.themeBrand]);

  return (
    <UniversalHeader
      loginInfo={user}
      onLogout={logout}
      onNavigateHome={() => (window.location.href = `/${tenantConfig.slug}/dashboard`)}
      sidebarContext={{ isSidebarOpen, toggleSidebar }}
      logoSrc={tenantConfig.logoSrc}
      logoAlt={tenantConfig.logoAlt}
      className={`tenant-${tenantConfig.slug}`}
    />
  );
};

5. Mobile-First PWA Integration

import { useEffect, useState } from 'react';

const PWAHeader = () => {
  const [isMobile, setIsMobile] = useState(false);
  const [isOnline, setIsOnline] = useState(navigator.onLine);

  useEffect(() => {
    const checkMobile = () => setIsMobile(window.innerWidth < 768);
    const handleOnlineStatus = () => setIsOnline(navigator.onLine);

    checkMobile();
    window.addEventListener('resize', checkMobile);
    window.addEventListener('online', handleOnlineStatus);
    window.addEventListener('offline', handleOnlineStatus);

    return () => {
      window.removeEventListener('resize', checkMobile);
      window.removeEventListener('online', handleOnlineStatus);
      window.removeEventListener('offline', handleOnlineStatus);
    };
  }, []);

  return (
    <UniversalHeader
      logoSrc='/pwa-logo.png'
      logoAlt='PWA App'
      showSidebarToggle={isMobile}
      className={`pwa-header ${!isOnline ? 'offline' : ''}`}
      // Additional PWA-specific props
    />
  );
};

6. Real-time Notifications Integration

import { useNotifications } from '@/hooks/useNotifications';

const NotificationHeader = () => {
  const { notifications, markAsRead } = useNotifications();
  const unreadCount = notifications.filter((n) => !n.read).length;

  return (
    <div className='header-with-notifications'>
      <UniversalHeader
        loginInfo={{ name: 'User', email: '[email protected]' }}
        onLogout={handleLogout}
        logoSrc='/app-logo.png'
      />

      {/* Custom notification bell - extends the header */}
      {unreadCount > 0 && (
        <div className='notification-badge'>
          <span className='badge-count'>{unreadCount}</span>
        </div>
      )}
    </div>
  );
};

📖 API Reference

UniversalHeaderProps

| Prop | Type | Default | Required | Description | | ------------------- | -------------------- | -------------------------------- | -------- | ----------------------------------- | | loginInfo | LoginInfo \| null | null | ✗ | User login information to display | | onLogout | () => void | undefined | ✗ | Callback when user clicks logout | | onNavigateHome | () => void | undefined | ✗ | Callback when user clicks logo/home | | sidebarContext | SidebarContextType | undefined | ✗ | Sidebar state management context | | logoSrc | string | '/greencitizen-logo-white.png' | ✗ | Logo image source URL | | logoAlt | string | 'Logo' | ✗ | Logo alt text for accessibility | | className | string | '' | ✗ | Additional CSS classes | | showThemeToggle | boolean | true | ✗ | Show/hide theme toggle button | | showSidebarToggle | boolean | true | ✗ | Show/hide sidebar toggle button |

Type Definitions

LoginInfo

interface LoginInfo {
  email?: string; // User's email address
  name?: string; // User's display name
  avatar?: string; // User's avatar URL
  role?: string; // User's role/permission level
  [key: string]: any; // Additional user properties
}

SidebarContextType

interface SidebarContextType {
  isSidebarOpen: boolean; // Current sidebar state
  toggleSidebar: () => void; // Toggle sidebar open/closed
  openSidebar?: () => void; // Force sidebar open
  closeSidebar?: () => void; // Force sidebar closed
}

🎨 Theming & Customization

Theme System

The component includes a built-in theme system with automatic persistence:

// Light theme (default)
:root {
  --header-bg: #ffffff;
  --header-text: #000000;
  --header-border: #e5e5e5;
  --button-hover: #f5f5f5;
}

// Dark theme
[data-theme='dark'] {
  --header-bg: #1a1a1a;
  --header-text: #ffffff;
  --header-border: #333333;
  --button-hover: #2a2a2a;
}

CSS Custom Properties Override

/* Custom theme colors */
:root {
  --brand-primary: #007bff;
  --brand-secondary: #6c757d;
  --header-height: 64px;
  --header-padding: 1rem;
  --logo-max-height: 40px;
  --button-border-radius: 0.375rem;
}

Custom Styling Examples

Custom Header Styles

.custom-header {
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  border-bottom: 3px solid var(--brand-primary);

  .logo {
    filter: brightness(1.1);
  }

  .user-info {
    background: linear-gradient(45deg, var(--brand-primary), var(--brand-secondary));
    color: white;
    border-radius: 20px;
  }
}

Responsive Customization

.mobile-friendly-header {
  @media (max-width: 768px) {
    .logo {
      max-height: 32px;
    }

    .user-info .name {
      display: none; // Hide name on mobile
    }

    .theme-toggle {
      margin-left: 0.5rem;
    }
  }
}

Component Extension

// Extend the header with custom elements
const ExtendedHeader = (props) => (
  <div className='extended-header-wrapper'>
    <UniversalHeader {...props} />
    <div className='header-extensions'>
      <SearchBar />
      <NotificationBell />
      <UserQuickActions />
    </div>
  </div>
);

🚀 Best Practices

1. State Management Integration

// ✅ Good: Integrate with your state management
const Header = () => {
  const { user, isAuthenticated } = useAuth();
  const { isSidebarOpen, toggleSidebar } = useUI();

  return (
    <UniversalHeader
      loginInfo={isAuthenticated ? user : null}
      sidebarContext={{ isSidebarOpen, toggleSidebar }}
      onLogout={() => dispatch(logoutUser())}
    />
  );
};

// ❌ Bad: Local state for global UI concerns
const Header = () => {
  const [user, setUser] = useState(null); // Should be global state
  return <UniversalHeader loginInfo={user} />;
};

2. Error Handling

// ✅ Good: Handle errors gracefully
const SafeHeader = () => {
  const handleLogout = async () => {
    try {
      await authService.logout();
      router.push('/login');
    } catch (error) {
      toast.error('Logout failed. Please try again.');
      console.error('Logout error:', error);
    }
  };

  const handleNavigateHome = () => {
    try {
      router.push('/dashboard');
    } catch (error) {
      // Fallback navigation
      window.location.href = '/dashboard';
    }
  };

  return <UniversalHeader onLogout={handleLogout} onNavigateHome={handleNavigateHome} />;
};

3. Performance Optimization

// ✅ Good: Memoize callbacks and context
const OptimizedHeader = () => {
  const sidebarContext = useMemo(
    () => ({
      isSidebarOpen,
      toggleSidebar: () => setIsSidebarOpen(!isSidebarOpen),
    }),
    [isSidebarOpen]
  );

  const handleLogout = useCallback(async () => {
    await logout();
  }, [logout]);

  return <UniversalHeader sidebarContext={sidebarContext} onLogout={handleLogout} />;
};

4. Accessibility

// ✅ Good: Provide meaningful alt text and ARIA labels
<UniversalHeader
  logoSrc='/company-logo.svg'
  logoAlt='Acme Corporation - Go to homepage'
  loginInfo={{
    name: 'John Doe',
    email: '[email protected]',
    role: 'Administrator',
  }}
/>

5. Testing Integration

// Test-friendly component setup
const TestableHeader = (props) => (
  <UniversalHeader
    {...props}
    data-testid='universal-header'
    logoAlt='Company Logo'
    className='testable-header'
  />
);

🔧 Troubleshooting

Common Issues

1. Theme Not Persisting

// Problem: Theme resets on page reload
// Solution: Ensure localStorage is available
useEffect(() => {
  if (typeof window !== 'undefined') {
    const savedTheme = localStorage.getItem('theme');
    if (savedTheme) {
      document.documentElement.setAttribute('data-theme', savedTheme);
    }
  }
}, []);

2. Sidebar Not Responding

// Problem: Sidebar toggle not working
// Solution: Ensure sidebarContext is properly connected
const [isSidebarOpen, setIsSidebarOpen] = useState(false);

// ✅ Correct context setup
const sidebarContext = {
  isSidebarOpen,
  toggleSidebar: () => {
    console.log('Toggling sidebar:', !isSidebarOpen); // Debug log
    setIsSidebarOpen(!isSidebarOpen);
  },
};

3. Styles Not Loading

// Problem: Styles not applied
// Solution: Import styles in your main app file or layout
import '@titusjin/universal-header-module/dist/styles.css';

// Or in your CSS
@import '@titusjin/universal-header-module/dist/styles.css';

4. Logo Not Displaying

// Problem: Logo not showing
// Solution: Check image path and ensure it's accessible
<UniversalHeader
  logoSrc='/images/logo.png' // Ensure path is correct
  logoAlt='Company Logo' // Always provide alt text
/>

5. TypeScript Errors

# Problem: TypeScript can't find module types
# Solution: Install types or add to declarations
npm install @types/react @types/react-dom

# Or create a declarations file
echo 'declare module "@titusjin/universal-header-module";' > src/types/modules.d.ts

Debug Mode

Enable debug logging for troubleshooting:

const DebugHeader = () => {
  const debugSidebarContext = {
    isSidebarOpen,
    toggleSidebar: () => {
      console.log('🔄 Sidebar toggle clicked. Current state:', isSidebarOpen);
      setIsSidebarOpen(!isSidebarOpen);
    },
  };

  return (
    <UniversalHeader
      sidebarContext={debugSidebarContext}
      onLogout={() => console.log('🚪 Logout clicked')}
      onNavigateHome={() => console.log('🏠 Home navigation clicked')}
    />
  );
};

🌟 Features

  • 🎨 Built-in Theme System: Automatic dark/light mode with localStorage persistence
  • 📱 Responsive Design: Mobile-first approach with breakpoint optimization
  • 🍔 Sidebar Integration: Seamless hamburger menu for sidebar control
  • 🔐 Authentication Display: User info display with logout functionality
  • 🏠 Navigation Support: Clickable logo for home navigation
  • 🎛️ Highly Configurable: Extensive props for customization
  • 💾 State Persistence: Automatic theme and preference saving
  • Accessibility Ready: ARIA labels and keyboard navigation
  • 🚀 Performance Optimized: Minimal re-renders and efficient updates
  • 🔧 Developer Friendly: TypeScript support with comprehensive types

📦 Browser Support

| Browser | Version | Notes | | ------------- | ------- | ------------ | | Chrome | 88+ | Full support | | Firefox | 85+ | Full support | | Safari | 14+ | Full support | | Edge | 88+ | Full support | | iOS Safari | 14+ | Full support | | Chrome Mobile | 88+ | Full support |

Legacy Support

For older browsers, include these polyfills:

<!-- For IE11 support -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=default,Array.prototype.find,Promise"></script>

📄 License

MIT © Titus Jin

🤝 Contributing

We welcome contributions! Please see our Contributing Guide.

Development Setup

# Clone the repository
git clone https://github.com/titusjin/listingApplication.git
cd listingApplication/module_universalHeader

# Install dependencies
npm install

# Start development
npm run dev

# Build the module
npm run build

# Publish (maintainers only)
npm run publish

Reporting Issues

When reporting issues, please include:

  • 📝 Clear description of the problem
  • 🔄 Steps to reproduce
  • 🖥️ Browser/environment details
  • 📱 Screenshots if applicable
  • 🧪 Minimal code example

Create an Issue


Made with ❤️ by Titus Jin