Define and render complex navigation menus for websites
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci
docs
lib
spec
.codeclimate.yml
.gitignore
.rubocop.yml
.yardopts
CHANGELOG.md
Gemfile
LICENSE
README.md
Rakefile
navtastic.gemspec

README.md

Navtastic

Build Status Code Coverage Inline docs Gem MIT License

Navtastic is way to create and display complex navigation menus for websites. It allows for runtime configurations of menus, depending on context.

  • Keep menu content and rendering logic separate
  • Automatically highlight the current page
  • Different output structures supported (Simple, Bootstrap4, Bulma, Foundation6)
    • HTML structure only, bring your own CSS.
  • Easily create your own renderer to fit your style.

The current renderers only support vertical menus. Horizontal (navbar) menus are planned.

Table of Contents

Installation

Add it to your Gemfile:

gem 'navtastic'

Run the following command to install it:

bundle install

Example

Define a menu somewhere:

Navtastic.define :main_menu do |menu|
  menu.item "Home", '/'
  menu.item "Posts", '/posts'
  menu.item "About", '/about'
end

Render it in your partials:

<%= Navtastic.render :main_menu, current_url %>

Using the default renderer, assuming that the current url starts with /posts, will result in:

<ul>
  <li>
    <a href="/">Home</a>
  </li>
  <li class="current">
    <a href="/posts">Posts</a>
  </li>
  <li>
    <a href="/about">About</a>
  </li>
</ul>

Rails

When using rails, a render_menu helper is added that automatically sets the current_url.

Also, put defined menus in app/menus to take advantage of hot reload.

Documentation

Submenus

Every item can have a submenu. They can be nested as deeply as you want.

Navtastic.define :main_menu do |menu|
  menu.item "Home", '/' do |submenu|
    submenu.item "Posts", '/posts'
    submenu.item "About", '/about'
  end

  menu.item "Settings" do |submenu|
    submenu.item "General", '/settings'
    submenu.item "Profile", '/settings/profile'
  end
end

By default, submenus will be rendered inside the <li> tag of the parent item.

<ul>
  <li>
    <a href="/">Parent</a>
    <ul>
      <li>
        <a href="/child">Child</a>
      </li>
    </ul>
  </li>
</ul>

Current item

The current active item is decided by the current_url parameter when rendering a menu. It is the item with the longest url that starts with the current_url.

For example, if there is a menu containing these urls:

  • /
  • /posts
  • /posts/featured

If the current_url is /posts/featured/2017, the /posts/featured item will be highlighted. If the current_url is /posts/123, then /posts is highlighted.

The root url / will always match, if no other items match the current url. If there is no item with / as url in the menu and no other urls match, nothing will be highlighted.

Runtime parameters

You can pass runtime parameters when defining a menu. For example, passing the current user and change the menu accordingly.

# Define the menu
Navtastic.define :main_menu do |menu, params|
  menu.item "Home", "/"

  if params[:current_user]
    menu.item "Profile", "/users/#{params[:current_user].id}"
    menu.item "Logout", "/logout"
  else
    menu.item "Login", "/login"
  end
end

# Render it with the current user as a parameter
Navtastic.render :main_menu, current_url, current_user: User.current

Global Configuration

Some global settings that Navtastic uses can be configured. Make sure the configuration happens before defining any menu (e.g. when using rails, add it to config/initializers/navtastic.rb).

These are the defaults values:

Navtastic.configure do |config|
  # This url to prepend before every item url
  config.base_url = nil

  # Set the renderer to use, can be one of :simple, :bootstrap4, :bulma, :foundation6
  # Can also be a class if you want to use a custom renderer
  config.renderer = :simple

  # Options that are passed to the renderer
  config.renderer_options = {}

  # Reload the renderer class every time menu is rendered (helpful during development)
  config.reload_renderer = false
end

Menu Configuration

Each individual menu can also be configured in some way:

Navtastic.define :user_menu do |menu, params|
  # The url to put before every item
  menu.config.base_url = '/users/' + params[:user_id]

  menu.item "Profile", '/profile' # will link to: /users/123/profile
end

Item Configuration

Every item can have options passed to it:

Navtastic.define :menu do |menu|
  # Add a css class to the container (e.g. <li> tag)
  menu.item "Home", "/", class: 'highlight'

  # Add a css class the content inside the container (e.g. <a> tag)
  menu.item "Posts", "/posts", content_class: 'important'

  # If `root` is true, this item will ignore any base urls
  menu.item "Somewhere", '/', root: true

  # Use the item url as the base_url for the submenu
  menu.item "Settings", '/settings', base_url: true do |submenu|
    # submenu.config.base_url is now set to '/settings'
  end
end

Renderers

The following renders are currently available:

  • Simple adds a current class to the basic list structure
  • Bootstrap4 is used with the Bootstrap 4 framework.
  • Bulma is used with the Bulma.io framework.
  • Foundation6 is used with the Foundation 6 framework.

Some renderers also support extra options. You can set them globally in the configuration or pass them at runtime when rendering a menu:

# Global options
Navtastic.configure do |config|
  config.renderer_options = { option: value }
end
# Runtime options
<%= Navtastic.render :menu, current_url, renderer: { option: value } %>

Globally defined options and options given at runtime are merged together, with those at runtime taking precedence.

Bulma Configuration

  • headers (default: false)

    Top level items are styled differently. Works best if they are only text, not links.


    left: headers: false, right: headers: true

Foundation Configuration

  • active_class (default: nil)

    CSS class to use for active items. Active items are items that have a child that is the current item. Useful to highlight the current item in a drilldown menu.

  • style (default: nil)

    Set to :drilldown to generate a drilldown menu. Make sure you include the required javascript files.


    left: default style, right: drilldown style

Development

  1. Checkout Repository: git clone https://github.com/aramvisser/navtastic.git
  2. Install Bundler: gem install bundler
  3. Run bundle install inside the project root to install the gem dependencies
  4. Run test cases: bundle exec rake

For testing visual changes, a test server is provided by running bundle exec rake demo. It's accessibly on http://localhost:9090.