<st-header>
JSON type: Header
The app-shell header bar — brand (image + title, or title alone) on the left, a slot="menu"
for primary nav (e.g. st-dropdown/st-menu-grid mega-menus, or plain links) taking the
middle, and a slot="utility" for account/app-switcher/theme controls on the right. title is
the primary brand prop; brand-image-url is optional. For a fixed nav-links/user-menu header,
use st-app-header instead.
The nav link for the page being shown is marked: current-path (e.g. /t-pilot) is compared
with each st-menu-item/st-mega-menu-column/st-mega-menu-feature href (and a mega column's
cta-href). A link is current when it equals the path, or, for a non-root href, when the path is
beneath it; / is current only on /. The current link gets aria-current="page", and an
st-dropdown containing one is highlighted as active. Without current-path the header uses
location.pathname, re-checked on popstate; a single-page app should set current-path
on each navigation (the React Header does this from the router).
Layout: the menu starts 4rem after the brand, the utility
controls sit after a vertical divider, and below BREAKPOINT_TABLET (900px) menu/utility
collapse behind a hamburger toggle into a full-screen layer under the
toggle (closes on Escape or a click inside it), where the menu's st-dropdowns are switched to
inline so they open in the flow — the same two slotted elements just get repositioned by CSS
(.mobile-panel's display: contents at desktop width vs. a real fixed-position box below
BREAKPOINT_TABLET), rather than the slots being duplicated in the template, since a shadow
root can only ever assign a given light-DOM child to the first slot of a given name.
An optional slot="brand-extra" sits right after the brand (e.g. an edition badge such as
"🇮🇳 India Edition"); unlike menu/utility it stays in the bar at every width.
Also carries an optional built-in language switcher (languages/currentLanguageCode, fires
language-change). Hidden entirely when languages has fewer than two entries.
This component has no translation logic itself; the consuming app owns what a language code
means and which content it re-renders in response.
Context mode (opt-in): set context-trigger to a CSS selector for a page element (typically the
hero) and give the header a slot="context" child (e.g. an st-product-nav with embedded and
scroll-spy). Once the trigger element has scrolled up past the bar, the bar swaps its menu for
the slotted context content. Scrolling back above the trigger restores the menu. Both rows share the
same 64px box, so the header never changes height, and the bar is solid while the context row shows,
even when transparent. With no context-trigger, or no slot="context" content, the header is
unchanged. An open mobile menu closes when the context row takes over. context-active reflects the
state; header-context-change fires on every switch (detail { active }).
In context mode, the slotted product nav's site-menu button (product-nav-site-menu) opens this
header's site menu over the bar, at every width. The bar keeps its state: the context row stays
visible underneath (made inert), and only the drawer, its close button and a backdrop (above 768px)
are shown on top. st-cookie-consent steps aside while the drawer is open (see setModalOpen). Esc,
the close button, a click outside the bar, or activating a link in the drawer closes it and returns
focus to that button.
On a narrow screen the open drawer covers the whole viewport and locks page scroll. It sets
data-st-drawer-open on <html>, holds keyboard focus (Tab wraps, Esc closes, focus returns to the
toggle), and shows the brand and, with cta-label + cta-href, a primary call to action above the
menu, which sits before the theme toggle on desktop.
Usage
import '@sankhyatronics/sankhya-cms/header'; // registers <st-header>
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
title | title | string | '' | |
brandImageUrl | brand-image-url | string | '' | Optional logo image URL, shown before title. Omitted entirely when empty — none of this suite's apps has one today. Matches the source component's imageSrc (renamed here to pair with title/logoHref, since this component's only image use is the brand mark). |
currentPath | current-path | string | '' | Path of the page being shown (e.g. /t-pilot). Marks the matching nav link as current; falls back to location.pathname when empty. |
altText | alt-text | string | 'Logo' | alt text for the brand image — matches the source component's altText (default 'Logo'). |
logoHref | logoHref | string | '' | Wraps the brand in an <a> when set (e.g. /); a plain non-link <div> otherwise. |
logoTarget | logo-target | string | '_self' | target for the brand <a> — matches the source component's logoTarget (default _self). No effect when logoHref isn't set. |
logoClassName | logo-class-name | string | '' | Extra class(es) appended to the brand link/div — matches the source component's logoClassName. |
inverted | inverted | boolean | false | Inverts the header's color roles (light-on-dark instead of dark-on-light) — matches the source component's inverted (from its shared BaseProps). |
sticky | sticky | boolean | false | |
transparent | transparent | boolean | false | Fixes the header over the top of the page and makes it see-through, with light text (--st-header-transparent-color), until the page scrolls past scroll-threshold — for a header laid over a dark hero. It then takes its normal background and a shadow. The page content starts under it, so the first section should leave room for the 64px bar. |
hideOnScroll | hide-on-scroll | boolean | false | Slides the header out of view while the page scrolls down and back in when it scrolls up. |
scrollThreshold | scroll-threshold | number | 8 | Scroll distance in px after which the header counts as scrolled. |
scrolled | scrolled | boolean | false | True once the page has scrolled past scroll-threshold; reflected so pages can style st-header[scrolled]. Set by the header, never from outside. |
scrollHidden | scroll-hidden | boolean | false | True while hide-on-scroll has slid the header away. Set by the header, never from outside. |
languages | — | { code: string; label: string }[] | [] | Language switcher options, e.g. [{ code: 'en', label: 'English' }, ...] — hidden entirely when empty or when only one language is offered (same convention as st-app-header's languages, which this reuses verbatim). This component has no translation logic itself — selecting an option fires language-change (detail: { code }), and the consuming app owns what code actually means and which content it re-renders. |
currentLanguageCode | current-language-code | string | '' | |
languageMenuLabel | language-menu-label | string | 'Language' | |
mobileOpen | mobile-open | boolean | false | Internal open/closed state for the mobile nav overlay, reflected to an attribute purely so the :host([mobile-open]) CSS selector above can react to it — not meant to be set from outside. |
compact | compact | boolean | false | True while the menu doesn't fit the bar at the current width: the header then shows the same hamburger layout it uses on a narrow screen. Set by evaluateFit, never from outside. |
ctaLabel | cta-label | string | '' | Label of an optional primary call to action in the utility row, before the theme toggle. Hidden when empty (also needs cta-href). |
ctaHref | cta-href | string | '' | Target of the call to action. Hidden when empty (also needs cta-label). |
contextTrigger | context-trigger | string | '' | CSS selector of a page element (e.g. #hero). Once it has scrolled up past the bar, the bar shows the context row instead of its menu. Empty (the default) turns context mode off. The selector is re-queried for up to 5s if the element is not rendered yet, and again whenever it changes. |
contextActive | context-active | boolean | false | True while the page is past the trigger, so the context row shows. A site-menu drawer opened over it leaves it showing. Set by the header from the trigger's position, never from outside. |
Slots
| Slot | Description |
|---|---|
menu | Primary navigation. |
context | Product sub-nav shown in place of the menu in context mode (see above). Its children get inert while the context row is hidden or a site-menu drawer is open. |
utility | Account, app-switcher and theme controls, after the divider. |
brand-extra | Shown right after the brand at every width (e.g. an edition badge). |
menu-icon | Replaces the hamburger on the narrow-screen toggle (the built-in glyph when empty). |
close-icon | Replaces the close (X) on the toggle while the menu is open (the built-in glyph when empty). |
Events
| Event | Detail | Description |
|---|---|---|
header-context-change | CustomEvent | Fired when the bar switches to or from the context row. Detail: { active: boolean }. Bubbles, composed. |
language-change | CustomEvent |
See the live examples in Storybook.