export interface JuiProduct { /** Unique product identifier */ id: string; /** Display name shown in the product switcher */ title: string; /** URL for the product icon image (light mode) */ icon?: string; /** URL for the product icon image (dark mode) */ icon_dark?: string; /** * URL for a full-color logo image shown next to the product name in the * top-left of the omnibar when this is the active product. Distinct from * `icon`/`icon_dark` (which drive the switcher list's white-icon-on-tile * treatment) — has no light/dark split and no background tile. Omit to * show no icon in that area. */ icon_colour?: string; /** * CSS `background-image` value (typically a `linear-gradient(...)`) used * as this product's icon tile background in the switcher list/redirect * modal, and as the active product's name text-fill color. Falls back to * the default purple gradient when unset. */ product_gradient?: string; /** Link to navigate to when selected */ href?: string; /** Whether this switches account context */ switch_account?: boolean; /** Marks this product as currently active */ active?: boolean; /** Optional `data-tag` value rendered on the product's link (e.g. for Gainsight targeting). Renders `data-tag=""` when unset, so a missing value is visible rather than silently absent. */ data_tag?: string; /** * Marks this product as temporarily unavailable — shown in the list with * reduced opacity, a "Pending" badge, and no link/click handling. * * - A number (Unix seconds since epoch, not JS milliseconds) auto-clears * once that time passes, with no page reload needed — e.g. * `Math.floor(Date.now() / 1000) + 5 * 60` for "pending for the next 5 * minutes". * - `true` marks it pending indefinitely, until you update the config. */ pending_until?: number | true; } export interface JuiProductSwitcherConfig { /** Title of the currently active product (matches JuiProduct.title) */ current_product?: string; /** Optional help/support link */ help_href?: string; /** List of available products */ products?: JuiProduct[]; /** URL for the "Juniper Marketplace" footer button in the product switcher. Button is hidden when unset. */ marketplace_href?: string; } export interface JuiProfileAction { /** Unique action identifier */ id: string; /** Label shown in the UI */ label: string; /** URL for the action icon image (light mode) */ icon?: string; /** URL for the action icon image (dark mode) */ icon_dark?: string; /** Optional navigation link */ href?: string; /** Optional `data-tag` value rendered on the action's element (e.g. for Gainsight targeting). Renders `data-tag=""` when unset, so a missing value is visible rather than silently absent. */ data_tag?: string; /** Optional badge text */ badge?: string; /** URL for the badge icon image (light mode) */ badge_icon?: string; /** URL for the badge icon image (dark mode) */ badge_icon_dark?: string; /** Callback when action is selected */ onSelect?: (detail: { /** The action that was triggered */ action: JuiProfileAction; /** The DOM element for the action */ component: HTMLElement; /** Original browser event */ event: Event; }) => void; /** Modal title shown before redirect */ modal_title?: string; /** Modal description text */ modal_description?: string; /** URL for the modal icon image (light mode) */ modal_icon?: string; /** URL for the modal icon image (dark mode) */ modal_icon_dark?: string; /** Delay before redirect (ms) */ modal_delay?: number; /** * Force-skip the redirect countdown modal for the "profile" action and * let it navigate like a normal same-tab link. The modal already skips * itself automatically whenever the omnibar's current product is * "Portal" (the link's own destination) — set this to skip it in other * products too. */ skip_redirect_modal?: boolean; } export interface JuiOtherAccount { /** Unique account identifier */ id: string; /** Display name of the account */ name: string; /** Optional navigation link */ href?: string; /** Account type */ type?: "school" | "trust"; /** Optional `data-tag` value rendered on the account's link (e.g. for Gainsight targeting). Renders `data-tag=""` when unset, so a missing value is visible rather than silently absent. */ data_tag?: string; } export interface JuiProfileSwitcherConfig { /** User display name */ user_name?: string; /** URL for user avatar image */ user_img?: string; /** Current account name */ account?: string; /** Current account type — controls the icon shown next to the account name */ account_type?: "school" | "trust"; /** Current product title */ product_title?: string; /** URL for the current product icon (light mode) */ product_icon?: string; /** URL for the current product icon (dark mode) */ product_icon_dark?: string; /** URL for the current product's full-color logo (overrides the active product's `icon_colour`, same as `product_icon` does for `icon`/`icon_dark`) */ product_icon_colour?: string; /** CSS `background-image` value for the current product's icon tile background in the profile menu header. Falls back to the default purple gradient when unset. */ product_gradient?: string; /** Logout handler */ logout?: ((detail: { component: HTMLElement; event: Event }) => void) | null; /** List of profile actions */ actions?: JuiProfileAction[]; /** Other accounts available for switching */ other_accounts?: JuiOtherAccount[]; } export interface JuiMenuToggleDetail { /** Source of the toggle event */ source: "burger"; /** The button element that triggered the event */ component: HTMLElement; /** Whether the burger button's aria-expanded is now true or false */ open: boolean; } /** A nav icon action: a URL renders it as a link, a callback renders it as a button. Hidden when null/unset. */ export type JuiIconAction = | string | ((detail: { component: HTMLElement }) => void) | null; export interface JuiOmnibarElement extends HTMLElement { /** Configure the product switcher */ productSwitcher: JuiProductSwitcherConfig; /** Configure the profile switcher */ profileSwitcher: JuiProfileSwitcherConfig; /** Callback when menu is toggled */ menuToggle: ((detail: JuiMenuToggleDetail) => void) | null; /** * The burger button's expanded state (drives its aria-expanded). Defaults * to toggling itself on each click — set this explicitly if the menu it * controls can also be closed by something other than the burger button * (its own close button, an outside click, Escape handled in your app). */ menuOpen: boolean; /** Help nav button. Falls back to productSwitcher.help_href, then a default Juniper help URL, when unset. Renders with a fixed, non-overridable `data-tag`. */ help: JuiIconAction; /** "Take a tour" nav button. Button is hidden when null/unset. Renders with a fixed, non-overridable `data-tag`. */ gainsight: JuiIconAction; /** Contact Support nav button. Button is hidden when null/unset. Renders with a fixed, non-overridable `data-tag`. */ zendesk: JuiIconAction; /** Inbox nav button. Button is hidden when null/unset. Renders with a fixed, non-overridable `data-tag`. */ inbox: JuiIconAction; /** Count badge shown on the Inbox button. Hidden when null/0. */ inboxCount: number | null; /** Bookmarks nav button. Button is hidden when null/unset. Renders with a fixed, non-overridable `data-tag`. */ bookmarks: JuiIconAction; /** Count badge shown on the Bookmarks button. Hidden when null/0. */ bookmarksCount: number | null; /** Search nav button. Button is hidden when null/unset. Renders with a fixed, non-overridable `data-tag`. */ search: JuiIconAction; } declare global { interface HTMLElementTagNameMap { "jui-omnibar": JuiOmnibarElement; } }