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

spartaxx-topbar

v1.0.36

Published

Spartaxx enterprise TopBar — reusable across all Spartaxx micro-frontend applications

Readme

@spartaxx/topbar

Enterprise-grade reusable TopBar component for all Spartaxx micro-frontend applications.

Extracted from loginapp — preserves all existing UI, behavior, styling, animations, auth flow, and Redux integration.


Installation

npm install @spartaxx/topbar

Install peer dependencies (if not already in your app):

npm install react react-dom react-router-dom react-redux redux lucide-react axios js-cookie

Quick Start (minimum props)

import { TopBar } from '@spartaxx/topbar';
import { Outlet } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { SSOConfigViaOffice365, HubMicroservice } from '../appsettings/appsettings';
import { UpdateAppList, UpdateLoginUserInfo, Logout } from '../appreduxservice/appreduxactionservice';

const AppLayout = () => {
  const dispatch = useDispatch();

  return (
    <TopBar
      onLogout={() => dispatch(Logout())}
      ssoConfig={SSOConfigViaOffice365}
      hubMicroservice={HubMicroservice}
      onUpdateAppList={(list) => dispatch(UpdateAppList(list))}
      onUpdateUserInfo={(profile) => dispatch(UpdateLoginUserInfo(profile))}
    >
      <Outlet />
    </TopBar>
  );
};

Full Prop API Reference

| Prop | Type | Default | Description | |---|---|---|---| | onLogout | () => void \| Promise<void> | required | Called after cookie is deleted. Shell handles Redux cleanup + redirect. | | ssoConfig | SSOConfig | undefined | If provided and localStorage.isSSO === "true", redirects to SSO logout URI. | | encodedToken | string | URL ?nekoT= param | Override the token (e.g. from React context). | | userProfile | UserProfile \| null | — | Pass from Redux to use controlled mode. Omit for self-managed auth. | | appList | AppItem[] | — | Pass from Redux for controlled mode app list. | | appListLoaded | boolean | — | Pass from Redux to indicate list is ready. | | appFetchError | boolean | — | Pass from Redux to indicate fetch failed. | | hubMicroservice | HubMicroserviceConfig | — | API config for self-managed app list fetch. | | fetchAppList | (userId: number) => Promise<AppItem[]> | — | Custom fetch function overriding microservicegateway. | | onUpdateAppList | (list: AppItem[]) => void | — | Dispatcher called after app list is fetched. | | onUpdateUserInfo | (profile: UserProfile) => void | — | Dispatcher called after profile is read from cookie. | | dashboardPath | string | "/dashboard" | Logo click navigates here. | | loginPath | string | "/" | Logout and Back to Login navigate here. | | sessionExpiredPath | string | "/session-expired" | Session monitor fires here on expiry. | | logoSrc | string | "image/spartaxx_logo.png" | Logo image path (relative to consuming app's public/). | | logoAlt | string | "Spartaxx" | Logo alt text. | | pageTitle | string | "Dashboard" | Uppercase label shown next to logo divider. | | brandColor | string | "#2eb135" | Navbar background color. | | sessionConfig | SessionConfig | — | Override session monitor timings. | | children | React.ReactNode | — | Page content rendered inside the main area. |

SessionConfig shape

{
  inactivityMs?: number;  // default: 1200000 (20 min)
  warnBeforeMs?: number;  // default: 60000 (1 min)
  tickMs?: number;        // default: 5000 (5 sec)
  activityKey?: string;   // default: "spartaxx_last_activity"
  enabled?: boolean;      // default: true
}

Redux Integration

Option A — Legacy createStore (existing loginapp pattern)

Pass Redux state and dispatchers as props. The package never imports your store.

import { useSelector, useDispatch } from 'react-redux';
import { TopBar } from '@spartaxx/topbar';
import { UpdateAppList, UpdateLoginUserInfo, Logout } from '../appreduxservice/appreduxactionservice';

const AppLayout = ({ ClearAllReduxCache }) => {
  const dispatch = useDispatch();
  const appList = useSelector((state) => state.appList);
  const loginUserInfo = useSelector((state) => state.loginUserInfo);

  return (
    <TopBar
      onLogout={() => { ClearAllReduxCache(); }}
      appList={appList}
      userProfile={loginUserInfo}
      appListLoaded={true}
      onUpdateAppList={(list) => dispatch(UpdateAppList(list))}
      onUpdateUserInfo={(profile) => dispatch(UpdateLoginUserInfo(profile))}
    >
      <Outlet />
    </TopBar>
  );
};

Option B — Redux Toolkit createSlice

Add the package's reducer to your store:

// store.ts
import { configureStore } from '@reduxjs/toolkit';
import { topbarReducer } from '@spartaxx/topbar';

export const store = configureStore({
  reducer: {
    topbar: topbarReducer,
    // ... your other reducers
  },
});

Use the selectors:

import { useSelector, useDispatch } from 'react-redux';
import { TopBar, selectAppList, selectLoginUserInfo, updateAppList, updateLoginUserInfo, logout } from '@spartaxx/topbar';

const AppLayout = () => {
  const dispatch = useDispatch();
  const appList = useSelector(selectAppList);
  const userProfile = useSelector(selectLoginUserInfo);

  return (
    <TopBar
      onLogout={() => dispatch(logout())}
      appList={appList}
      userProfile={userProfile}
      onUpdateAppList={(list) => dispatch(updateAppList(list))}
      onUpdateUserInfo={(profile) => dispatch(updateLoginUserInfo(profile))}
    >
      <Outlet />
    </TopBar>
  );
};

Option C — Self-managed (no Redux)

Omit all Redux props. The component manages its own auth and app list fetch:

<TopBar
  onLogout={() => { /* your cleanup */ }}
  ssoConfig={SSOConfigViaOffice365}
  hubMicroservice={HubMicroservice}
>
  <Outlet />
</TopBar>

SSO Logout Configuration

<TopBar
  ssoConfig={{
    logoutUri: {
      logoutUri: 'https://login.microsoftonline.com/tenant/oauth2/logout?...'
    }
  }}
  // ...
/>

When the user clicks "Sign Out" and localStorage.isSSO === "true", the package redirects to ssoConfig.logoutUri.logoutUri. Otherwise it navigates to loginPath.


Session Monitor Configuration

<TopBar
  sessionConfig={{
    inactivityMs: 30 * 60 * 1000,   // 30 minutes
    warnBeforeMs: 2 * 60 * 1000,    // warn 2 minutes before
    tickMs: 1000,                    // check every second
    enabled: isAuthenticated,        // disable before auth
  }}
/>

Logo Asset

The default logoSrc is "image/spartaxx_logo.png". Copy the logo to your app's public folder:

your-app/public/image/spartaxx_logo.png

Or override with a full path:

<TopBar logoSrc="/assets/your-logo.png" />

Multi-App Usage Examples

LoginApp (after extraction)

// loginapp/src/layout/applayout.js
import { TopBar } from '@spartaxx/topbar';
import { Outlet, useNavigate } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { SSOConfigViaOffice365, HubMicroservice } from '../appsettings/appsettings';
import { UpdateAppList, UpdateLoginUserInfo, Logout } from '../appreduxservice/appreduxactionservice';

const AppLayout = ({ ClearAllReduxCache }) => {
  const dispatch = useDispatch();

  return (
    <TopBar
      onLogout={ClearAllReduxCache}
      ssoConfig={SSOConfigViaOffice365}
      hubMicroservice={HubMicroservice}
      onUpdateAppList={(list) => dispatch(UpdateAppList(list))}
      onUpdateUserInfo={(profile) => dispatch(UpdateLoginUserInfo(profile))}
      dashboardPath="/dashboard"
      sessionExpiredPath="/session-expired"
      loginPath="/"
    >
      <Outlet context={{ /* pass context as before */ }} />
    </TopBar>
  );
};

export default AppLayout;

ProtestApp

import { TopBar } from '@spartaxx/topbar';

const ProtestAppLayout = ({ ClearAllReduxCache }) => (
  <TopBar
    onLogout={ClearAllReduxCache}
    ssoConfig={window.ConfigManager.APPConfig.SSOConfigViaOffice365}
    hubMicroservice={window.ConfigManager.MicroServiceConfig.HubService}
    pageTitle="Protest"
    dashboardPath="/dashboard"
    loginPath="/"
  >
    <Outlet />
  </TopBar>
);

AdminApp (with custom brand color)

<TopBar
  brandColor="#1e40af"
  pageTitle="Admin Portal"
  onLogout={handleLogout}
  hubMicroservice={HubMicroservice}
/>

Module Federation Shell

// shell/src/Layout.tsx
import { TopBar } from '@spartaxx/topbar';
import { useSelector, useDispatch } from 'react-redux';

export const ShellLayout = ({ children }) => {
  const dispatch = useDispatch();
  const appList = useSelector((state) => state.shell.appList);
  const userProfile = useSelector((state) => state.shell.userProfile);

  return (
    <TopBar
      appList={appList}
      appListLoaded={true}
      userProfile={userProfile}
      onLogout={() => dispatch({ type: 'SHELL_LOGOUT' })}
    >
      {children}
    </TopBar>
  );
};

Local Development (npm link)

# In the package directory
cd spartaxx-topbar
npm install
npm run build
npm link

# In the consuming app
cd loginapp
npm link @spartaxx/topbar

# Rebuild on changes
cd spartaxx-topbar
npm run build:watch

Publishing to Private Verdaccio Registry

# Start local registry (one-time setup)
npm install -g verdaccio
verdaccio

# Publish package
cd spartaxx-topbar
npm publish --registry http://localhost:4873

# Install in consuming apps
npm install @spartaxx/topbar --registry http://localhost:4873
# Or add to .npmrc:
# @spartaxx:registry=http://localhost:4873

Versioning Strategy

  • 1.0.x — Bug fixes (no API changes)
  • 1.x.0 — New optional props added
  • x.0.0 — Breaking API changes (remove props, change behavior)

Always update CHANGELOG.md before publishing.


Common Mistakes to Avoid

  1. Missing logo asset — Copy spartaxx_logo.png to public/image/ in the consuming app.
  2. Peer dependency version mismatch — Use react@>=18, react-redux@>=9, react-router-dom@>=6.
  3. Double Redux connection — Don't use both controlled props AND hubMicroservice. Pick one mode.
  4. Forgetting isSSO in localStorage — The package reads localStorage.isSSO for SSO logout routing. Your sign-in flow must set it.
  5. Cookie domain — The package automatically sets .poconnor.com domain when on *.poconnor.com hosts. Works out-of-the-box.
  6. Outlet inside children — Wrap <Outlet /> in children: <TopBar ...><Outlet /></TopBar>.