spartaxx-topbar
v1.0.36
Published
Spartaxx enterprise TopBar — reusable across all Spartaxx micro-frontend applications
Maintainers
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/topbarInstall peer dependencies (if not already in your app):
npm install react react-dom react-router-dom react-redux redux lucide-react axios js-cookieQuick 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.pngOr 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:watchPublishing 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:4873Versioning Strategy
1.0.x— Bug fixes (no API changes)1.x.0— New optional props addedx.0.0— Breaking API changes (remove props, change behavior)
Always update CHANGELOG.md before publishing.
Common Mistakes to Avoid
- Missing logo asset — Copy
spartaxx_logo.pngtopublic/image/in the consuming app. - Peer dependency version mismatch — Use
react@>=18,react-redux@>=9,react-router-dom@>=6. - Double Redux connection — Don't use both controlled props AND
hubMicroservice. Pick one mode. - Forgetting
isSSOin localStorage — The package readslocalStorage.isSSOfor SSO logout routing. Your sign-in flow must set it. - Cookie domain — The package automatically sets
.poconnor.comdomain when on*.poconnor.comhosts. Works out-of-the-box. Outletinsidechildren— Wrap<Outlet />in children:<TopBar ...><Outlet /></TopBar>.
