Starting with Spree 5.2, the navigation system uses a declarative API accessible via
Spree.admin.navigation. This allows you to programmatically add, modify, and remove navigation items directly in your initializers.Basic Usage
Add navigation items in yourconfig/initializers/spree.rb file:
config/initializers/spree.rb
Available Options
All navigation items support the following options:The text label for the navigation item. Can be a symbol (translation key using
Spree.t) or a string.The URL for the navigation item. Can be a route helper symbol (
:admin_brands_path) or a lambda returning a URL.Icon name from Tabler Icons.
Numeric position in the menu. Lower numbers appear first.
Lambda to determine if the link should be highlighted as active. Receives view context.
Conditional display logic. The item only appears if this lambda returns true. Has access to view context helpers like
can?, current_store, etc.Badge text/count to display next to the label. Can be a string or lambda that returns a value.
CSS class for badge styling (e.g.,
'badge-info', 'badge-warning').Tooltip text shown on hover.
Link target attribute (e.g.,
'_blank' to open in a new tab).Creates a section divider with the given label instead of a clickable link.
The key of an existing navigation item to nest this item under. This is the simplest way to add items to existing submenus.
Navigation Contexts
The navigation system supports multiple contexts. Spree provides predefined contexts for common use cases, and you can register custom contexts for your specific needs.Sidebar Navigation
The main sidebar navigation:Settings Navigation
Navigation in the Settings area:Page Tab Navigation
Spree provides several predefined tab contexts for common admin pages:Registering Contexts
Useregister_context to create a new navigation context:
The unique name for the navigation context. Will be converted to a symbol internally.
Spree::Admin::Navigation - The navigation context instance
Note: Calling register_context multiple times with the same name returns the same instance (idempotent).
Custom Tab Contexts
You can create custom tab contexts for your own admin pages usingregister_context:
config/initializers/spree.rb
render_tab_navigation helper:
app/views/spree/admin/brands/index.html.erb
Listing All Contexts
You can list all registered navigation contexts:Checking If a Context Exists
Creating Submenus
Add a parent item, then add child items using theparent option:
config/initializers/spree.rb
Parent items are automatically marked as active when any of their children are active. You don’t need to manually define the
active option for parent items.Modifying Existing Navigation
Finding Navigation Items
Adding to Existing Submenus
Use theparent option to add an item to an existing submenu:
Removing Navigation Items
Updating Navigation Items
Replacing Navigation Items
Moving Navigation Items
Advanced Examples
Navigation with Dynamic Badge
Section Dividers
Dynamic URLs
Complex Conditional Display
Complex Active State Logic
Best Practices
Authorization
Always use
if: -> { can?(...) } to ensure users only see navigation items they have permission to access.Translations
Use symbols for labels (e.g.,
label: :brands) to support internationalization via Spree.t.Active States
Define clear active state logic using lambdas to highlight the current section properly.
Positioning
Use consistent position intervals (e.g., 10, 20, 30) to leave room for future additions.
Common Positioning Reference
Main sidebar navigation positions:- Getting Started: 5
- Home: 10
- Orders: 20
- Returns: 25
- Products: 30
- Customers: 40
- Promotions: 50
- Reports: 60
- Storefront: 70
- Integrations: 80
- Settings Section: 90
- Settings: 100
- Admin Users: 110
Troubleshooting
Navigation item not appearing
Navigation item not appearing
Active state not working
Active state not working
- Ensure
active:lambda returns true/false - Check that controller_name or other conditions match correctly
- For submenus, ensure parent uses same active logic as children
Badge not displaying
Badge not displaying
- Ensure the badge lambda returns a non-nil value
- Check that the badge value is truthy (empty strings won’t display)
- For numeric badges, ensure the count is greater than 0
Previous versions
How it works
The admin navigation system works through injection points defined throughout the sidebar. You can inject custom navigation items into these predefined locations, add new top-level menu items, or create nested submenus.Navigation Injection Points
The main navigation file is located atadmin/app/views/spree/admin/shared/sidebar/_store_nav.html.erb and provides several injection points:
Available Injection Points
store_nav_partials
store_nav_partials
store_products_nav_partials
store_products_nav_partials
store_orders_nav_partials
store_orders_nav_partials
store_settings_nav_partials
store_settings_nav_partials
settings_nav_partials
settings_nav_partials
Using the nav_item Helper
Thenav_item helper method is provided by Spree::Admin::NavigationHelper and makes it easy to create properly formatted navigation items.
Method Signature
Parameters
The text label for the navigation item. Can be HTML-safe content.
The URL the navigation item links to. Use the
spree. route helper prefix.Optional icon name from Tabler Icons. The icon will be displayed before the label.
Manually set whether the link should be marked as active. If not specified, it will be auto-detected based on the current URL.
Additional data attributes to add to the link element.
Basic Usage
With Active State
With Block Content
Adding a Simple Navigation Item
Let’s add a new “Inventory” navigation item to the main sidebar.Step 1: Create the Partial
Step 2: Add Navigation Code
app/views/spree/admin/shared/_inventory_nav.html.erb
Step 3: Register the Partial
Add this to yourconfig/initializers/spree.rb:
- Spree 5.2+
- Spree 5.1 and below
config/initializers/spree.rb
Step 4: Add Translations
In yourconfig/locales/en.yml:
config/locales/en.yml
Step 5: Restart Your Server
Restart your web server to load the initializer changes. The navigation item should now appear in the sidebar.Creating Nested Navigation (Submenus)
To create a navigation item with a submenu, you need to use thenav-submenu class and manage the visibility based on the active state.
Example: Adding a Nested Menu
Key Points for Submenus
-
Active State Variable: Define a variable to track when any item in the menu group is active:
-
Parent Navigation Item: Use the active state variable for the parent item:
-
Submenu Container: Use the
nav-submenuclass and conditionally addd-noneto hide when inactive: -
Child Items: Add child navigation items within the submenu:
-
Nested Injection Point (Optional): Add an injection point within the submenu for further extensibility:
Advanced Examples
Navigation with Badge
Navigation with Complex Active Logic
Extending Existing Submenus
To add an item to an existing submenu (e.g., Products), use the appropriate injection point: Create:app/views/spree/admin/shared/_custom_products_nav.html.erb
config/initializers/spree.rb:
- Spree 5.2+
- Spree 5.1 and below
config/initializers/spree.rb
Navigation in Settings Mode
When the admin is in “Settings mode” (the dedicated settings view), use thesettings_nav_partials injection point:
- Spree 5.2+
- Spree 5.1 and below
config/initializers/spree.rb
Best Practices
Authorization
Always use
can?() checks to ensure users only see navigation items they have permission to access.Translations
Use
Spree.t() for all navigation labels to support internationalization.Icons
Use consistent icons from Tabler Icons that match Spree’s design language.
Active States
Define clear active state logic to highlight the current section in the navigation.
Route Helpers
Always use
spree. prefixed route helpers to reference admin routes correctly.Injection Points
Add your own injection points in submenus to allow further extensions by other developers.
Common Patterns
Multiple Controller Check
Path-based Check
Controller and Action Check
Parameters-based Check
Troubleshooting
Navigation item not appearing
Navigation item not appearing
Icon not displaying
Icon not displaying
- Verify the icon name exists in Tabler Icons
- Check that you’re using the correct parameter name:
icon:noticon_name: - Ensure the icon name is a string, e.g.,
icon: 'boxes'
Submenu not showing/hiding properly
Submenu not showing/hiding properly
Translation missing
Translation missing
- Add the translation key to your locale file
- Ensure the locale file is in the correct location
- Restart your server after adding translations
- Check for typos in the translation key
Related Documentation
- Extending Admin UI - Learn about other UI injection points
- Helper Methods - Explore other admin helper methods
- Permissions - Understand the authorization system


