Side nav
<oblyx-side-nav> is a <nav> landmark that lays out whatever <oblyx-side-nav-heading>,<oblyx-side-nav-section>, and <oblyx-side-nav-item> children it's given, in document order. <oblyx-side-nav-item> can nest further <oblyx-side-nav-item> children of its own for multi-level menus. This is the sidebar container and its items only. There is no sidebar-level collapsed (icon-rail) mode, no drag-to-resize handle, and no app-shell wiring; those are real, larger scopes this component doesn't attempt yet.
Basic side nav
<oblyx-side-nav label="Docs navigation">
<oblyx-side-nav-heading heading="Oblyx" superheading="Documentation"></oblyx-side-nav-heading>
<oblyx-side-nav-section label="Get started">
<oblyx-side-nav-item label="Installation" href="/docs/install/"></oblyx-side-nav-item>
<oblyx-side-nav-item label="Foundations" href="/docs/foundations/" aria-current="page"></oblyx-side-nav-item>
</oblyx-side-nav-section>
<oblyx-side-nav-section label="Components">
<oblyx-side-nav-item label="Button" href="/docs/components/button/"></oblyx-side-nav-item>
<oblyx-side-nav-item label="Link" href="/docs/components/link/"></oblyx-side-nav-item>
</oblyx-side-nav-section>
</oblyx-side-nav>oblyxSideNav(label = "Docs navigation") {
oblyxSideNavHeading(heading = "Oblyx", superheading = "Documentation")
oblyxSideNavSection(label = "Get started") {
oblyxSideNavItem(label = "Installation", href = "/docs/install/")
oblyxSideNavItem(label = "Foundations", href = "/docs/foundations/", current = "page")
}
oblyxSideNavSection(label = "Components") {
oblyxSideNavItem(label = "Button", href = "/docs/components/button/")
oblyxSideNavItem(label = "Link", href = "/docs/components/link/")
}
}Current item
Set the standard aria-current="page" attribute directly on the <oblyx-side-nav-item> that matches the current route. Unlike breadcrumbs, this component never compares its own href against the current URL or infers which item is current: the value is always server-computed and passed straight through onto the item's rendered <a>/<button>/<span>. The example above sets it on "Foundations".
Collapsible items
Set collapsible on an item that has nested <oblyx-side-nav-item> children (it has no effect on a childless item) and expanded to control whether those children currently show. When the item also has an href, the link and the expand/collapse toggle render as separate, sibling controls in the same row, specifically to avoid nesting a <button> inside an <a>: clicking the label navigates, clicking the chevron toggles.
Expandable group with a link
The row is both a link (navigates to Navigation's own href, if any) and a separate toggle button.
<oblyx-side-nav label="Docs navigation">
<oblyx-side-nav-section label="Components">
<oblyx-side-nav-item label="Navigation" href="/docs/components/link/" collapsible expanded>
<oblyx-side-nav-item label="Link" href="/docs/components/link/"></oblyx-side-nav-item>
<oblyx-side-nav-item label="Tabs" href="/docs/components/tabs/"></oblyx-side-nav-item>
<oblyx-side-nav-item label="Breadcrumbs" href="/docs/components/breadcrumbs/" aria-current="page"></oblyx-side-nav-item>
</oblyx-side-nav-item>
</oblyx-side-nav-section>
</oblyx-side-nav>oblyxSideNav(label = "Docs navigation") {
oblyxSideNavSection(label = "Components") {
oblyxSideNavItem(label = "Navigation", href = "/docs/components/link/", collapsible = true, expanded = true) {
oblyxSideNavItem(label = "Link", href = "/docs/components/link/")
oblyxSideNavItem(label = "Tabs", href = "/docs/components/tabs/")
oblyxSideNavItem(label = "Breadcrumbs", href = "/docs/components/breadcrumbs/", current = "page")
}
}
}When a collapsible item has no href of its own, the whole row is a single <button> that both labels the group and toggles it.
Expandable group with no link
<oblyx-side-nav label="Docs navigation">
<oblyx-side-nav-item label="Settings" collapsible>
<oblyx-side-nav-item label="Profile" href="/settings/profile/"></oblyx-side-nav-item>
<oblyx-side-nav-item label="Billing" href="/settings/billing/"></oblyx-side-nav-item>
</oblyx-side-nav-item>
</oblyx-side-nav>oblyxSideNav(label = "Docs navigation") {
oblyxSideNavItem(label = "Settings", collapsible = true) {
oblyxSideNavItem(label = "Profile", href = "/settings/profile/")
oblyxSideNavItem(label = "Billing", href = "/settings/billing/")
}
}Disabled
disabled follows the same disabled-link contract as oblyx-link: an item with href omits it entirely rather than merely looking disabled.
Disabled item
<oblyx-side-nav label="Docs navigation">
<oblyx-side-nav-item label="Active item" href="/docs/"></oblyx-side-nav-item>
<oblyx-side-nav-item label="Locked section" href="/docs/enterprise/" disabled></oblyx-side-nav-item>
</oblyx-side-nav>oblyxSideNav(label = "Docs navigation") {
oblyxSideNavItem(label = "Active item", href = "/docs/")
oblyxSideNavItem(label = "Locked section", href = "/docs/enterprise/", disabled = true)
}Sizes
Item sizes
<oblyx-side-nav label="Docs navigation">
<oblyx-side-nav-item label="Small" href="/docs/" size="sm"></oblyx-side-nav-item>
<oblyx-side-nav-item label="Medium" href="/docs/" size="md"></oblyx-side-nav-item>
<oblyx-side-nav-item label="Large" href="/docs/" size="lg"></oblyx-side-nav-item>
</oblyx-side-nav>oblyxSideNav(label = "Docs navigation") {
oblyxSideNavItem(label = "Small", href = "/docs/", size = OblyxSideNavItemSize.SM)
oblyxSideNavItem(label = "Medium", href = "/docs/", size = OblyxSideNavItemSize.MD)
oblyxSideNavItem(label = "Large", href = "/docs/", size = OblyxSideNavItemSize.LG)
}Hidden section header
header-hidden visually hides a section's title row while keeping it in the accessibility tree via role="group"/aria-labelledby. It is never display: none, so the section is still announced to assistive tech even though sighted users don't see the heading.
Section with hidden header
<oblyx-side-nav label="Docs navigation">
<oblyx-side-nav-section label="Quick links" header-hidden>
<oblyx-side-nav-item label="Installation" href="/docs/install/"></oblyx-side-nav-item>
<oblyx-side-nav-item label="Foundations" href="/docs/foundations/"></oblyx-side-nav-item>
</oblyx-side-nav-section>
</oblyx-side-nav>oblyxSideNav(label = "Docs navigation") {
oblyxSideNavSection(label = "Quick links", headerHidden = true) {
oblyxSideNavItem(label = "Installation", href = "/docs/install/")
oblyxSideNavItem(label = "Foundations", href = "/docs/foundations/")
}
}Keyboard model
Side nav is not a composite widget: every row is a native <a>,<button>, or <span>, so Tab moves through every interactive row in document order using ordinary browser tab-stop behavior. There is no roving tabindex and no arrow-key navigation, unlike tabs. An expandable row's toggle <button> activates with Enter or Space for free, being a real button; a collapsed group's children carry inert as well as aria-hidden while closed, which removes the entire hidden subtree from the Tab order in one step, including any nested items several levels deep.
Reference
<oblyx-side-nav>
| Attribute | Type | Default | Description |
|---|---|---|---|
label | string | undefined | Sidebar navigation | Nav landmark accessible name. |
<oblyx-side-nav-section>
| Attribute | Type | Default | Description |
|---|---|---|---|
label | string | undefined | – | Section title, also the group's accessible name via aria-labelledby. Required; a section with no label has nothing to label its role="group" with. |
subtitle | string | undefined | – | Optional secondary line under the title. |
header-hidden | boolean | false | Visually hides the header row while keeping it in the accessibility tree. |
<oblyx-side-nav-heading>
| Attribute | Type | Default | Description |
|---|---|---|---|
heading | string | undefined | – | Primary heading text. Required. |
superheading | string | undefined | – | Optional line above the heading, e.g. a workspace name. |
subheading | string | undefined | – | Optional line below the heading. |
heading-href | string | undefined | – | Makes the heading row a link. Omitted, heading renders as plain text. |
superheading-href | string | undefined | – | Makes the superheading row a link. Omitted, it renders as plain text. |
subheading-href | string | undefined | – | Makes the subheading row a link. Omitted, it renders as plain text. |
<oblyx-side-nav-item>
| Attribute | Type | Default | Description |
|---|---|---|---|
label | string | undefined | – | Visible row text and default accessible name. Required. |
href | string | undefined | – | Link destination. Omitted from the rendered <a> when disabled. Absent entirely renders a non-interactive <span> (or, if expandable, a toggle-only <button>). |
disabled | boolean | false | Disabled state. Drives the href-omission contract on the <a> shape, and native disabled on the <button> shapes. |
collapsible | boolean | false | Whether this item's children can be expanded/collapsed. Only takes effect when this item actually has children. |
expanded | boolean | false | Current expand state of a collapsible item's children. |
size | smmdlg | md | Element height / horizontal padding band. |
aria-current | string | undefined | – | aria-current passthrough, server-computed by the caller. Only 'page' has any visual effect; any other value is still forwarded verbatim, since aria-current also has legal non-boolean values (step, location, ...) this component has no business rejecting. Named current, not ariaCurrent, since the latter collides with the standard ARIAMixin.ariaCurrent: string | null property every Element already has, which TypeScript's DOM lib types incompatibly with Lit's own optional-property convention. |