ONav v2.0.4
A standalone WordPress navigation builder, completely independent of Appearance → Menus. Primary nav, topbar, footer, and mobile drawer, all managed from one place, with mega panels, click analytics, and a clean developer API.
What ONav does
ONav operates completely independently of WordPress's built-in menu system. Every nav item, mega panel, CTA button, and mobile menu is defined inside ONav, so your navigation lives entirely outside the WP menu system and theme layer, and remains unaffected by theme updates.
--onav-* custom properties on :root.onav_overrides.Getting installed
From WordPress admin
onav.zip and click Install Now, then Activate Plugin.Manual upload
onav/ folder to /wp-content/plugins/onav/.wp_options keys: onav_slot_primary, onav_slot_topbar_v2, onav_slot_footer, onav_slot_mobile, plus template slots. On first activation the plugin uses built-in generic defaults; replace these with your site's actual content.Plugin architecture
Constants
| Constant | Value | Description |
|---|---|---|
ONAV_VERSION | 2.0.4 | Plugin version string |
ONAV_PATH | plugin_dir_path(__FILE__) | Absolute filesystem path |
ONAV_URL | plugin_dir_url(__FILE__) | Absolute URL path |
ONAV_OPTION | onav_config | Legacy unified option name (kept for back-compat) |
| Per-slot prefix | onav_slot_<slot> | Per-slot wp_options keys, e.g. onav_slot_primary, onav_slot_topbar_v2 |
Admin interface
Two-row sticky header (brand bar + horizontal tab nav) with full-width card-based content, following the Orravo Plugin Design System. No WP admin sidebar. Light/dark toggle persisted to localStorage under key onav_theme.
Primary nav editor
The main editor for your site's header navigation. Split into a sortable item list on the left, an item editor panel on the right, and a live preview iframe below.
| Panel | What it does |
|---|---|
| Item List (left) | Sortable rows showing type badge, label, URL, and actions. Drag by the ⠿ handle to reorder. Mega items show a Panel button to open the Mega Panel Builder. |
| Item Editor (right) | Appears on Add Item or pencil icon. Fields adapt to the selected type. Dropdown items show a child link manager. Save Item stages changes; click the top-right Save button to persist. |
| Preview strip | Live iframe preview. Toggle Desktop / Mobile view and Dark / Light theme. Click Refresh to reload after saving. |
Topbar tab
Configures the thin utility bar that sits above the primary nav.
| Field | Description |
|---|---|
| Enable topbar | Show/hide the topbar globally |
| Descriptor text | Short announcement or tagline shown on the left |
| Height (px) | Topbar height (default 36px) |
| Background | Any CSS color value |
| Text / Link color | Colors for descriptor text and topbar links |
| Hide on mobile | Hides the topbar below the mobile breakpoint |
| Topbar Links | Links with a side setting (left / right) controlling which side of the topbar they appear on |
Mobile drawer tab
| Field | Description |
|---|---|
| Mirror primary nav | When on (default), mobile uses the same items as the primary nav |
| Menu style | accordion (bottom sheet), slide-left, slide-right, fullscreen |
| Breakpoint (px) | Window width below which mobile menu activates (default 768) |
| Background | Drawer background color |
| CTA Label / URL | CTA button shown at the bottom of the drawer |
When Mirror primary nav is off, define a completely separate set of items for mobile only using the Custom Mobile Items card.
Scroll behavior
| Setting | Description |
|---|---|
| Sticky on scroll | Nav fixes to the top of the viewport after scrolling past it |
| Transparent start | Nav starts with transparent background (over a hero), fills in on scroll |
| Smart hide | Hides nav when scrolling down, reveals it when scrolling up |
| Shadow on scroll | Adds a drop shadow when the nav is in sticky/scrolled state |
| Background style | solid, blur (glass/frosted), or gradient |
| Blur amount | Backdrop blur in pixels (only applies when bg style = blur) |
IntersectionObserver on a 1px sentinel element for zero scroll-event cost. Smart hide uses requestAnimationFrame-debounced scroll listener only when that setting is active.Appearance customizer
Color and dimension customizer. No CSS editing required; all values become CSS custom properties on :root.
| Token | Affects |
|---|---|
| Nav background | The nav bar background color |
| Nav background (on scroll) | Background once scrolled (for transparent-start nav) |
| Link color | Default link text color |
| Link hover | Link color on hover |
| Active link | Color of the currently active nav item |
| CTA button background / text / hover | Colors for button-type nav items |
| Mega panel background / border | Mega panel popout colors |
| Dropdown background | Simple dropdown background |
| Nav height | Height of the primary nav bar (default 64px) |
| Link font size | Font size of all nav link labels (default 14px) |
All values accept #rrggbb, rgba(r,g,b,a), or CSS var() references.
Analytics tab
Lightweight, opt-in click tracking. Off by default. Stores aggregate counts only.
| Element | Description |
|---|---|
| Stat cards | Total clicks tracked · Number of distinct items tracked · Last updated timestamp |
| Opt-in toggle | Enable click tracking. When enabled, each nav item click increments its count in wp_options. |
| Click Counts table | Each tracked item with total click count and share percentage, sorted by count descending |
| Clear data | Permanently deletes all click data from wp_options |
Settings tab
| Feature | Description |
|---|---|
| Export JSON | Downloads a full ONav config .json for backup or migration to another site |
| Import JSON | Upload a previously exported file. Overwrites current config with a confirmation prompt. |
| WP Menus Sync | Pulls the WP menu at the primary theme location and converts it to ONav items. Runs as a one-time import. |
| Reset | Resets all config to factory defaults. Export first; this is permanent. |
| Developer API reference | In-panel code reference for all filters, actions, and helper functions |
Nav item types
Button styles
Mega panel builder
Accessible via the Panel button on any mega type item. Build multi-column panels with up to 6 different block types per column.
Panel settings
| Setting | Options | Description |
|---|---|---|
| Width | container, full | container aligns with the content grid; full spans viewport width |
| Columns | 1–4 | Number of columns in the grid |
| Animation | fade, slide, none | Opening animation |
| Trigger | hover, click | Whether the panel opens on mouse hover or requires a click |
Block types
Block data structures
JSON · link-list / icon-grid{
"column": 0,
"type": "link-list",
"heading": "Section Title",
"links": [
{ "label": "Item One", "url": "/path/", "desc": "Short description", "icon": "" }
]
}
JSON · featured{
"column": 1,
"type": "featured",
"image": "https://example.com/image.jpg",
"title": "Featured Title",
"body": "Description text.",
"cta": "Learn more",
"cta_url": "/learn-more/"
}
JSON · recent-posts{
"column": 2,
"type": "recent-posts",
"heading": "Latest",
"count": 3,
"category": 0
}
Frontend usage
ONav does not auto-inject into any theme location. Call it from your theme templates.
PHP · header.php<?php do_action('onav_primary'); ?>
PHP · footer.php<?php do_action('onav_footer'); ?>
PHP · direct rendererONAV_Renderer::render_primary();
ONAV_Renderer::render_footer();
functions.php: add_action('get_header', function() { do_action('onav_primary'); }, 1);CSS custom properties
ONav injects a <style id="onav-vars"> block into wp_head with all color and dimension values as CSS custom properties on :root. Use them freely in your own theme CSS.
CSS · example usage.my-hero {
/* Push content below both topbar + nav */
padding-top: calc(var(--onav-h) + var(--onav-topbar-h));
}
/* Dark mode override */
@media (prefers-color-scheme: light) {
:root {
--onav-nav-bg: #ffffff;
--onav-link: #1a1814;
}
}
Filters
onav_primary_items
Modify the array of primary nav items before they are rendered.
PHPadd_filter('onav_primary_items', function (array $items): array {
// Add a conditional item for logged-in users
if (is_user_logged_in()) {
$items[] = [
'id' => 'my-account',
'type' => 'link',
'label' => 'My Account',
'url' => '/my-account/',
];
}
return $items;
});
Action hooks
onav_before_render & onav_after_render
PHP// Fires before the primary nav HTML is output
add_action('onav_before_render', function (): void {
// e.g. set up a nonce or output custom data
});
// Fires after the primary nav HTML is output
add_action('onav_after_render', function (): void {
// e.g. output additional markup
});
Helper functions
PHP// Get nav items for any slot
$primary_items = onav_get_items('primary'); // onav_primary_items filter applied
$footer_cols = onav_get_items('footer'); // returns columns array
$topbar_items = onav_get_items('topbar');
// Get the full merged config
$cfg = ONAV_Config::get();
$behavior = $cfg['primary']['behavior'];
// Get a single slot's config
$primary = ONAV_Config::get_slot('primary');
$mobile = ONAV_Config::get_slot('mobile');
// Resolve a relative URL
$url = ONAV_Config::resolve_url('/about/');
// → https://example.com/about/
JavaScript events
ONav dispatches custom DOM events on document for all major interaction states.
JS// Dropdown or mega panel opened
document.addEventListener('onav:open', function (e) {
console.log('Opened item:', e.detail.item);
});
// Dropdown or mega panel closed
document.addEventListener('onav:close', function (e) {
console.log('Closed item:', e.detail.item);
});
// Mobile drawer opened
document.addEventListener('onav:mobile:open', function () {});
// Mobile drawer closed
document.addEventListener('onav:mobile:close', function () {});
Accessibility (WCAG 2.1 AA)
| Feature | Implementation |
|---|---|
| Keyboard navigation | Arrow keys traverse the top-level nav; ArrowDown enters a dropdown; Escape closes any open panel |
| ARIA roles | role="navigation" on the bar; aria-haspopup and aria-expanded on dropdown triggers; role="menu" / role="menuitem" on dropdowns |
| Focus visible | :focus-visible outlines on all interactive elements using --onav-link-active color |
| Mobile dialog | role="dialog", aria-modal="true", aria-label on the mobile drawer |
| Overlay focus trap | Mobile drawer traps focus while open; focus returns to hamburger on close |
| Screen reader text | Icon-only items have aria-label attributes |
Click analytics
Opt-in and off by default. Stores aggregate counts only.
| Detail | Value |
|---|---|
| Storage | wp_options under key onav_analytics |
| Data format | {"clicks": {"home": 42, "pricing": 17, …}, "last_updated": "…"} |
| AJAX endpoint | wp_ajax_nopriv_onav_track: accessible to logged-out users so all visitors are counted equally |
| Personal data | None stored. The plugin records only aggregate click counts. |
| Clear data | Permanently deletes all analytics from wp_options |
Import & export
Export
onav-config-YYYY-MM-DD.json is downloaded.The export contains the full config for all slots: items, mega panels, behavior, appearance, and analytics settings (but not analytics data).
Import
.json file and confirm. The current config is fully replaced.Multisite support
ONav stores its configuration per-site in wp_options. No network-wide shared config by default.
| Scenario | Approach |
|---|---|
| Per-subsite config | Each subsite has its own independent ONav config with no extra setup needed |
| Network deployment | Export from a "master" site and import on each subsite |
| Programmatic cross-site read | switch_to_blog() + ONAV_Config::get() to read another site's config |
| Future Pro feature | Network admin panel to define a shared base config with per-site overrides |
Config schema reference
Each slot's onav_slot_* option stores a JSON object with this structure.
JSON{
"primary": {
"items": [
{
"id": "string",
"type": "link|dropdown|mega|button|search|separator|cart|user|html",
"label": "string",
"url": "string",
"new_tab": false,
"children": [],
"mega_panel": {},
"button_style": "primary|secondary|outline|ghost",
"html_content": "string"
}
],
"behavior": {
"sticky": true,
"transparent": false,
"smart_hide": false,
"shadow_scroll": true,
"bg_type": "solid|blur|gradient",
"blur_amount": 12
},
"appearance": {
"nav_bg": "#0b0b0c",
"nav_bg_scroll": "#0b0b0c",
"link_color": "rgba(255,255,255,0.65)",
"link_hover": "#ffffff",
"link_active": "#ff6a2b",
"cta_bg": "#ff6a2b",
"cta_text": "#ffffff",
"cta_hover_bg": "#ff7a42",
"mega_bg": "#121214",
"mega_border": "#1f1f23",
"dropdown_bg": "#121214",
"font_size": 14,
"height": 64
}
},
"topbar_v2": {
"enabled": true,
"items": [],
"height": 36,
"bg": "#0b0b0c",
"text_color": "rgba(255,255,255,0.6)",
"link_color": "rgba(255,255,255,0.85)",
"descriptor": "",
"hide_mobile": true
},
"footer": {
"enabled": true,
"columns": [
{
"heading": "string",
"links": [ { "label": "string", "url": "string" } ]
}
],
"copyright": "© 2025 Your Brand",
"copyright_url": ""
},
"mobile": {
"items": [],
"use_primary": true,
"style": "accordion|slide-left|slide-right|fullscreen",
"breakpoint": 768,
"bg": "#0b0b0c",
"cta_label": "Get Started",
"cta_url": "/get-started/"
},
"analytics": {
"enabled": false,
"clicks": {}
}
}
What's shipped
- Full plugin from scratch (rebrand from fideograph-nav)
- Multiple menu slots: primary, topbar, footer, mobile
- 9 nav item types: link, dropdown, mega, button, search, cart, user, separator, html
- Mega panel builder: 1–4 columns, 10 block types
- Mobile drawer: accordion, slide-left, slide-right, fullscreen
- Nav behavior: sticky, transparent, smart-hide, shadow-scroll
- Appearance customizer: full CSS token system, height, font-size
- Live preview iframe in admin
- Import / export JSON config
- WP Menus one-click import
- Click analytics (opt-in, aggregate only)
- Keyboard navigation (arrow keys, Escape)
- ARIA roles throughout (WCAG 2.1 AA)
- Developer filters:
onav_primary_items; actions:onav_before_render,onav_after_render - Developer actions:
onav_before_render,onav_after_render - Helper functions:
onav_get_items(),ONAV_Config::get() - Clean install / uninstall hooks
- Single consolidated JS file (~8KB, vanilla JS)
- Orravo admin UI design system (exact Omailer match)
- Stored in
wp_optionsas JSON
Frequently asked questions
<?php do_action('onav_primary'); ?> to your header.php and <?php do_action('onav_footer'); ?> to your footer.php. That's it.wp_options. Reactivate and everything comes back exactly as you left it.onav_slot_* options and onav_analytics from wp_options. All data is permanently deleted.:root you can override them with your own media query: @media (prefers-color-scheme: light) { :root { --onav-nav-bg: #ffffff; } }functions.php: add_action('get_header', function() { do_action('onav_primary'); }, 1);. Alternatively, use OCodeInsert to add the hook without touching any theme files.do_action('onav_primary') twice renders it twice. For two different nav configurations on one page, use onav_get_items() with the onav_primary_items filter to return different items for each instance.Got a question about ONav?
Reach out directly. Kenneth replies within 24 hours.

