@ojiepermana/angular-navigation
v22.0.59
Published
Scalable, accessible navigation shells and route-aware primitives for Angular 22.
Maintainers
Readme
Navigation
@ojiepermana/angular-navigation renders input-driven navigation with configurable types and instance-aware state.
import {
NavigationContainerComponent,
NavigationSidebarComponent, // type: NavigationDockbar/Navbar/FlyoutComponent
NavigationHeaderComponent,
NavigationContentComponent,
NavigationFooterComponent,
type NavigationItem,
} from '@ojiepermana/angular-navigation';
import { NavigationService } from '@ojiepermana/angular-navigation/service';
const items: NavigationItem[] = [
{ id: 'dashboard', title: 'Dashboard', link: '/dashboard', icon: 'dashboard' },
{
id: 'reports',
title: 'Reports',
type: 'collapsible',
children: [{ id: 'monthly', title: 'Monthly', link: '/reports/monthly' }],
},
];<Navigation id="erp-sidebar" [data]="items" class="h-full">
<NavigationSidebar>
<NavigationHeader class="px-1" [toggle]="true">
<div class="text-sm font-semibold">Workspace</div>
</NavigationHeader>
<NavigationContent />
<NavigationFooter class="p-3">
<button type="button">Sign out</button>
</NavigationFooter>
</NavigationSidebar>
</Navigation>
<Navigation id="erp-topbar" [data]="items">
<NavigationNavbar />
</Navigation>Type dipilih lewat komponen anak deklaratif — NavigationSidebar, NavigationDockbar, NavigationNavbar, atau NavigationFlyout — satu type hidup per <Navigation>. Di dalam type, NavigationHeader dan NavigationFooter opsional, sedangkan NavigationContent selalu dirender (otomatis dibuat bila tidak diproyeksikan).
API Notes
datais the source of navigation data.- Type is declared by the child component:
NavigationSidebar/NavigationDockbar(vertical),NavigationNavbar/NavigationFlyout(horizontal). Orientation is implied by the type child. ididentifies a navigation instance so multiple navs can keep distinct service state.positiononNavigationSidebar/NavigationDockbaracceptsleftorright(vertical).collapsedonNavigationSidebarcontrols the icon-only sidebar state.modeonNavigationDockbaracceptsstickyordrawer.ariaLabeloverrides the host navigation label and defaults toPrimary navigation.labelonNavigationFlyoutsets the single trigger label and defaults toMenu.icononNavigationFlyoutrenders a Material Symbols icon on the trigger;icon-position(start/end) sets its placement andicon-onlyhides the label visually while keeping it as the accessible name (compact mode is always icon-only and falls back to themenuicon).nav-positiononNavigationNavbar/NavigationFlyoutacceptstop(default) orbottom. Withbottom, the navbar grid panel opens upward with squared bottom corners, and the flyout panel anchors to the container's bottom edge with the tab row docked at the bottom — seamless for bars placed below the content.nav-appearanceonNavigationNavbar/NavigationFlyoutacceptsflatorborder-rail(same vocabulary as the layout'slayout-appearance).border-railsquares the panel (no rounding), frames entry icons with dimmed blueprint-style rail lines plus dashed center cross lines (instead of rounded boxes), renders the nested-collapse rail dashed, and replaces hover/active backgrounds with primary-colored text.flatkeeps the current visuals.- The
navbartype renders root items inline immediately; clicking a group (hover does not open it) opens a full-width grid panel below the bar with the same flyout-style entries, responsive columns, and nested collapse. - The
flyouttype renders one trigger button that opens a floating panel overlaying the parent container exactly (same top position and width, covering the trigger with no visible gap;display: contentswrappers are skipped when measuring the container). Root items with children become the horizontal navigation inside the panel (theiriconrenders in the row), their children render as title/subtitle entries in a responsive grid (1 column on mobile, 2 fromsm, 3 frommd, 4 fromlgand up;columnscaps the maximum at 1–4), and deeper children render as a vertical collapse below their entry — expanded by default every time the panel opens, collapsible per entry via the chevron, with the child icons aligned on the same vertical line as the parent entry icon. The panel closes onEscape, outside clicks, the close button, or leaf selection. - Items with children render a
chevron_righticon pinned at the right edge and vertically centered: it points right by default and rotates down (in place, no layout shift) only while open — hover does not move it. This applies to flyout tabs and entries, navbar branch triggers, and collapsible items. - Angular Router is supported for internal links through
link,queryParams,fragment,exactMatch, andisActiveMatchOptions. - External links can use
hreforlinkwithexternalLink: true. activeIdslets consumers force active state by nav id or normalized key.activeUrllets consumers drive active matching without relying on the current router URL.openedIdsowns collapsible state and supports two-way binding.previewExpandedonNavigationSidebarforces a collapsed sidebar instance to render in expanded-preview mode.itemSelectedemits for action, router, and external items.classapplies classes to the hostnavelement.itemClassapplies shared classes to rendered items.nav-group-class(groupClass) applies Tailwind classes to the container of each horizontal group — the flyout tab<li>and the navbar group<li>— so consumers can tune height, padding, or borders of the group container. Per-group control is also available viaitem.classes.container.compactis still supported as a compatibility alias for collapsed vertical sidebars.nav-sidebar-collapseonNavigationSidebarenables hover-preview behavior for collapsed vertical sidebars.collapse-treeacceptsstairsorstraightfor nested collapsible connector styling.NavigationHeaderis optional, accepts Tailwind classes throughclass, and can render a built-in collapse toggle with[toggle]="true".NavigationFooteris optional and accepts Tailwind classes throughclass.NavigationContentwraps the active navigation renderer and owns the scrollable region between the optional header and footer slots. It is rendered automatically by the type component when not projected, and acceptsclasswhen used explicitly.
Nav Inputs And Outputs
Inputs pada <Navigation> (container):
| API | Type | Notes |
| ----------------- | -------------------------------------------------- | ------------------------------------------------------------------------------- |
| id | string | Navigation instance id. main is the only id persisted to localStorage. |
| data | readonly NavigationItem[] | Source of navigation items. |
| ariaLabel | string | Accessible label on the host navigation landmark. |
| compact | boolean | Compatibility alias for collapsed-rail item layout. |
| collapse-tree | stairs \| straight | Controls nested connector styling for collapsible items. |
| class | string | Extra classes for the host nav. |
| itemClass | string | Shared classes applied to rendered nav items. |
| nav-group-class | string | Classes for each horizontal group container (flyout tab / navbar group <li>). |
| activeIds | ReadonlySet<string> \| readonly string[] \| null | Explicit active state override by item id or normalized key. |
| activeUrl | string \| null | Explicit URL used during active matching. |
| openedIds | readonly string[] | Two-way bound open state for collapsible items. |
| itemSelected | NavigationSelection | Emits when a leaf item is selected. |
Inputs pada komponen type:
| Component | API | Type | Notes |
| ------------------- | ---------------------- | -------------------------- | ----------------------------------------------------------------------------- |
| NavigationSidebar | position | left \| right \| null | Side the rail docks to. |
| NavigationSidebar | collapsed | boolean \| null | Controls collapsed vertical sidebar state. |
| NavigationSidebar | nav-sidebar-collapse | boolean | Enables hover-driven preview expansion on collapsed sidebars. |
| NavigationSidebar | previewExpanded | boolean | Forces a collapsed sidebar to render expanded for preview. |
| NavigationDockbar | mode | sticky \| drawer \| null | Docked aside beside the rail, or overlay drawer. |
| NavigationDockbar | position | left \| right \| null | Side the rail docks to. |
| NavigationNavbar | nav-appearance | flat \| border-rail | Style variant. border-rail = squared panel, dashed icon rails, no hover bg. |
| NavigationFlyout | label | string | Trigger label. Defaults to Menu. |
| NavigationFlyout | nav-appearance | flat \| border-rail | Style variant. border-rail = squared panel, dashed icon rails, no hover bg. |
Semua type juga menerima class untuk kelas tambahan pada elemen shell-nya.
NavigationItem
NavigationItem supports deeper trees, mixed item kinds, and both router and external navigation.
| Field | Type | Notes |
| -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| id | string | Stable item id. Reused for active/open state when present. |
| type | item \| basic \| aside \| group \| collapsible \| collapsable \| mega \| divider \| spacer | collapsable is accepted as a compatibility alias of collapsible. |
| title, subtitle, tooltip | string | Primary labels and optional compact tooltip. |
| active, disabled | boolean | Explicit active and disabled flags. |
| icon | string | Rendered through the default icon slot unless overridden. |
| badge | { title?: string; classes?: string } | Small label rendered beside the item title. |
| classes | { wrapper?, container?, icon?, title?, subtitle? } | Per-item class overrides. container targets the horizontal group <li> wrapper. |
| meta | Record<string, unknown> | Consumer-owned metadata bag. |
| isHidden | (item) => boolean | Filters items at normalization time. |
| link | string \| readonly unknown[] \| UrlTree | Angular Router link target. |
| href | string | Direct external URL. |
| queryParams, queryParamsHandling, fragment, preserveFragment | Router options | Extra Angular Router navigation options. |
| externalLink, target, rel | link options | External navigation behavior and rel handling. |
| exactMatch, isActiveMatchOptions | Router match options | Control how router activity is resolved. |
| action | (item) => void | Callback for action-driven leaf items. |
| columns | number | Column count for mega style items. |
| children | readonly NavigationItem[] | Nested items. Trees can be deeper than one level. |
Public Shell APIs
NavigationHeaderexposes[toggle]andclass.NavigationFooterexposesclass.NavigationContentexposesclassand renders the active type menu; declare it explicitly to control slot order, or omit it for the automatic default.[NavigationCollapseRoot]adjusts layout for collapsible shell content when the sidebar rail is collapsed.[NavigationCollapseExpanded]only renders its template while the vertical shell is not in collapsed display mode.
<div NavigationCollapseRoot class="flex items-center gap-3 px-3">
<Icon name="work" />
<span *NavigationCollapseExpanded>Workspace</span>
</div>Nav Service
@ojiepermana/angular-navigation/service exposes NavigationService as a singleton registry for navigation type and overlay state.
import { NavigationService } from '@ojiepermana/angular-navigation/service';
const nav = inject(NavigationService);
nav.setType('erp-sidebar', 'dockbar');
nav.setCollapsed('erp-sidebar', true);
nav.toggleCollapsed('erp-sidebar');
nav.setPosition('erp-sidebar', 'right');
nav.setDockbarMode('erp-sidebar', 'drawer');
nav.openDrawer('erp-sidebar');
nav.closeDrawer('erp-sidebar');Available service helpers include:
register,unregister,state,currentState, andupdatefor instance lifecycle and state access.setType,setPosition,setCollapsed,toggleCollapsed, andsetDockbarModefor instance configuration.currentPanelKey,isPanelOpen,openPanel,togglePanel, andclosePanelfor flyout or mega-panel state.isDrawerOpen,openDrawer,toggleDrawer, andcloseDrawerfor drawer dockbar mode.exactMatchOptionsandsubsetMatchOptionsfor router matching defaults.
Navigation UI depends on the NAVIGATION_ADAPTER contract, not directly on the
service class. The default token factory uses NavigationService; an application
can override the token with a compatible adapter to change persistence or state
ownership without replacing the components.
import { NAVIGATION_ADAPTER } from '@ojiepermana/angular-navigation/core';
const providers = [{ provide: NAVIGATION_ADAPTER, useExisting: WorkspaceNavigationAdapter }];Only the primary sidebar navigation (id="main") persists preferences in localStorage under:
nav-orientationnav-typenav-positionnav-type-mode
nav-type-mode depends on the active vertical type:
- sidebar:
defaultorcollapsed - dockbar:
stickyordrawer
Any other navigation id, such as erp-navbar, only keeps its state in memory for the active instance. Consumers should provide those values explicitly at usage time or rely on the built-in defaults.
Icons
Saat item.icon tersedia, nav akan merender Material Symbols secara default melalui @ojiepermana/angular-component/icon. Jalankan provideUiTheme() untuk preload global, atau biarkan IconComponent melakukan lazy-load saat icon pertama dipakai.
<Navigation [data]="items">
<NavigationSidebar />
</Navigation>Gunakan template NavigationIcon hanya bila consumer ingin override renderer bawaan.
<Navigation [data]="items">
<NavigationSidebar />
<ng-template NavigationIcon let-icon let-item="item" let-active="active" let-level="level">
<Icon [name]="icon" class="text-primary" />
</ng-template>
</Navigation>NavigationIcon template context exposes:
$implicitandicon: resolved icon name.item: sourceNavigationItem.active: current active state.orientation: current nav orientation.level: current nesting depth.
Boundaries
Entry point ini tetap extensible di layer consumer. Type defaults, instance registration, overlay state, dan affordance icon bawaan dikelola di library, sementara consumer masih bisa mengganti renderer icon dan komposisi layout sesuai kebutuhan.
Bundle / performance
NavigationContent me-render renderer sesuai type aktif. Renderer yang lebih jarang
dipakai — flyout, horizontal/navbar, dan dockbar — dibungkus @defer (on immediate)
sehingga bundler aplikasi memecahnya menjadi lazy chunk: aplikasi yang hanya memakai
sidebar (vertical list, renderer default yang tetap eager) tidak ikut membundel ketiga
renderer tersebut. Tidak ada perubahan API — komposisi <Navigation><NavigationSidebar>…
tetap sama; hanya distribusi chunk di sisi consumer yang lebih ringan.
