jui-omnibar
v3.4.0
Published
Juniper omnibar web components
Downloads
1,395
Maintainers
Readme
JUI Omnibar
A lightweight, framework-agnostic web component omnibar for Juniper products.
Includes:
- Product switcher with redirect modal
- Profile switcher with redirect modal
- Image-based icons with automatic light/dark switching
- Account-aware configuration
- TypeScript definitions
- Fully accessible popovers & keyboard support
- No framework dependencies
Installation
NPM
npm install jui-omnibarimport "jui-omnibar/omnibar.css";
import "jui-omnibar";CDN (Quick start)
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/omnibar.css" />
<script type="module">
import "https://cdn.jsdelivr.net/npm/[email protected]/dist/omnibar.js";
</script>Pin to a specific version in production rather than using
latest.
Usage
<jui-omnibar product="MIS" account="Highlands Academy" home="/"></jui-omnibar>const omnibar = document.querySelector("jui-omnibar");Icons
All icons are provided as image URLs — the component no longer accepts inline SVG strings. Supply a light-mode URL and an optional dark-mode URL. The correct variant is shown automatically when data-theme="dark" is set on <body>.
{
icon: "/icons/my-icon.svg", // shown in light mode
icon_dark: "/icons/my-icon-dark.svg", // shown in dark mode (optional)
}If icon_dark is omitted, the single icon image is used in both modes.
Bundled icons
The package ships a set of icons at dist/icons/ (also available on the CDN). These are used internally and can be referenced directly if needed:
dist/icons/
help.svg / help-dark.svg
products.svg / products-dark.svg
menu.svg / menu-dark.svg
search.svg / search-dark.svg
logout.svg / logout-dark.svg
profile-action.svg / profile-action-dark.svg
external-link.svg / external-link-dark.svg
portal.svg / portal-dark.svg
admin.svg / admin-dark.svg
comms-hub.svg / comms-hub-dark.svg
events.svg / events-dark.svg
mis.svg / mis-dark.svg
sonar-lite.svg / sonar-lite-dark.svg
theme-toggle.svg / theme-toggle-dark.svg
account-school.svg / account-school-dark.svg
account-trust.svg / account-trust-dark.svg
arrow-open.svg / arrow-open-dark.svg
switch-account.svg / switch-account-dark.svg
uservoice.svg / uservoice-dark.svg
zendesk.svg / zendesk-dark.svgConfiguration
Product Switcher
current_productmatches againsttitle, notid.
omnibar.productSwitcher = {
current_product: "MIS",
help_href: "https://help.example.com",
products: [
{
id: "mis",
title: "MIS",
icon: "/icons/mis.svg",
icon_dark: "/icons/mis-dark.svg",
href: "/mis",
switch_account: false,
active: true,
},
{
id: "comms-hub",
title: "Comms Hub",
icon: "/icons/comms-hub.svg",
icon_dark: "/icons/comms-hub-dark.svg",
href: "/comms-hub",
switch_account: true, // shows "Available on other account" label
active: false,
},
],
};Clicking a non-active product shows a redirect modal with a 3-second countdown before navigating. The user can cancel at any time.
Profile Switcher
omnibar.profileSwitcher = {
user_name: "Joe Bloggs",
user_img: "https://...",
account: "Highlands Academy",
product_title: "MIS",
product_icon: "/icons/mis.svg",
product_icon_dark: "/icons/mis-dark.svg",
logout: () => {
console.log("Logout clicked");
},
actions: [
{
id: "profile",
label: "Profile",
icon: "/icons/profile-action.svg",
icon_dark: "/icons/profile-action-dark.svg",
href: "/portal/profile",
badge: "Open in portal",
badge_icon: "/icons/external-link.svg",
badge_icon_dark:"/icons/external-link-dark.svg",
modal_title: "Portal",
modal_description: "This will open in a new tab",
modal_delay: 3000,
modal_icon: "/icons/portal.svg",
modal_icon_dark: "/icons/portal-dark.svg",
},
{
id: "theme-toggle",
label: "Toggle dark theme",
icon: "/icons/theme-toggle.svg",
icon_dark: "/icons/theme-toggle-dark.svg",
command: "toggle-dark-theme",
},
{
id: "custom",
label: "Custom action",
icon: "/icons/custom.svg",
icon_dark: "/icons/custom-dark.svg",
onSelect: ({ action }) => {
console.log(action.id);
},
},
],
other_accounts: [
{
id: "magna",
name: "Magna Academy",
href: "/switch/magna",
type: "school",
},
],
};Actions behaviour
| Property | Behaviour |
| --- | --- |
| href | Renders action as <a> |
| no href | Renders action as <button> |
| id: "profile" + href | Shows redirect modal before opening link |
| command: "toggle-dark-theme" | Built-in dark theme toggle |
| onSelect | Custom callback fired on click |
Redirect modal
Both the product switcher and the profile "profile" action support a redirect modal.
// Profile action
{
id: "profile",
href: "/portal/profile",
modal_title: "Portal",
modal_description: "This will open in a new tab",
modal_delay: 3000, // ms before redirect
modal_icon: "/icons/portal.svg",
modal_icon_dark: "/icons/portal-dark.svg",
}- Countdown spinner shown during delay
- Cancel button stops the redirect
- ESC key also cancels
- Profile action opens the link in a new tab; product switcher navigates in the same tab
UserVoice
An optional UserVoice button appears in the omnibar nav when a URL is provided. Set it to null (or leave unset) to hide it. The URL should be the appropriate UserVoice page for the current product — the consuming app is responsible for providing the correct URL.
// Show the button linking to the product-specific UserVoice page
omnibar.uservoice = "https://juniper.uservoice.com/forums/mis";
// Hide the button
omnibar.uservoice = null;The link opens in a new tab. Tooltip text: "UserVoice".
Live Chat (Zendesk)
An optional Live Chat button appears in the omnibar nav when a callback is provided. Set it to null (or leave unset) to hide it — useful for environments where Zendesk is not available.
// Show the button and open the Zendesk messenger on click
omnibar.zendesk = () => {
zE("messenger", "open");
};
// Hide the button
omnibar.zendesk = null;The callback receives { component } as its argument.
Other accounts
other_accounts: [
{
id: "account-id",
name: "Magna Academy",
href: "/switch",
type: "school", // "school" | "trust"
},
];Hidden when the array is empty.
Attributes
| Attribute | Description |
| --------- | -------------------- |
| product | Current product name |
| account | Current account name |
| home | Logo link href |
Events
omnibar.addEventListener("jui:menu-toggle", (event) => {
console.log(event.detail); // { source: "burger", component }
});
omnibar.addEventListener("jui:profile-action", (event) => {
console.log(event.detail.action); // the action object
});
omnibar.addEventListener("jui:logout", () => {
console.log("Logout fired");
});Dark mode
Dark mode is activated by setting data-theme="dark" on <body>. The built-in toggle-dark-theme command does this automatically, or you can set it yourself:
document.body.setAttribute("data-theme", "dark");All icon icon_dark variants switch automatically — no JavaScript required.
Styling
import "jui-omnibar/omnibar.css";Key CSS variables:
:root {
--j-o-color-brand-primary: #271a38;
--j-o-color-brand-secondary: #814af4;
--j-o-font-family: "Inter", sans-serif;
}Package structure
dist/
omnibar.js
product-switcher.js
profile-switcher.js
icons.js
omnibar.css
omnibar.d.ts
icons/
*.svg (light mode)
*-dark.svg (dark mode)Development
npm run buildAccessibility
- Keyboard navigation (ESC closes menus and modals)
- Focus management on close
- ARIA roles, labels, and expanded states
- Screen reader announcements for loading states
Migration from v3.0.x
All SVG string props have been replaced with image URL props:
| Before (v3.0.x) | After (v3.1.0) |
| --- | --- |
| icon_svg: "<svg>...</svg>" | icon: "/path/to/icon.svg" + optional icon_dark |
| badge_icon_svg | badge_icon + badge_icon_dark |
| product_icon_svg | product_icon + product_icon_dark |
| modal_icon_svg | modal_icon + modal_icon_dark |
License
MIT
