There is no file with the name of README.
App Navigation Links
Sets the content and behavior of the app navigation sidebar (on the left-side of a desktop app).
General
Unlike other layout hooks, you should not provide your own HTML to the app_navigation_links
option. The sidebar navigation is a relatively complex HTML component, so the gem provides a simple interface that you can use to specify your application's navigation: an array of hashes. For example, the sidebar navigation shown in the example image above was rendered with this data:
[ { title: 'Navigation Links', href: root_path, icon: 'home', active_when: controller_path == 'application' }, { title: 'Manage Resources', href: '#', icon: 'pencil' }, { title: 'Dropdown Section', children: [ { title: 'Option 1', href: '#' }, { title: 'Option 2', href: '#' }, { title: 'Nested Dropdown', icon: 'bullseye', children: [ { title: 'Some Page', href: '#' }, { title: 'Other Page', href: '#', icon: 'cogs' }, ] } ] } ]
You may use { static: content }
to add arbitrary content to the sidebar. Otherwise, you must follow the rules of a navigation link:
A typical navigation link:
- must have a
title
- must have either an
href
orchildren
- must not have both an
href
andchildren
- the
children
key must be an array of navigation link hashes
- the
- may have an
icon
- the
icon
key must be the name of a FontAwesome 5 icon - it should contain the fully-qualified prefix (e.g.
icon: 'fas fa-eye'
for the solid eye icon) - the
icon
key may omit thefa fa-
prefix and just use the icon name (e.g.icon: 'map'
andicon: 'fa-map'
both producefa fa-map
)
- the
- may have an
active_when
boolean value- determines if the navigation link is shown as being active
- defaults to
false
- may have an
external
boolean value- determines if the navigation link should open in a new tab
- defaults to
false
Thus, the simplest possible navigation link hash would have this shape:
{ title: 'Navigation Link', href: some_path }
The most complex navigation link hash would have this shape:
{ title: 'Dropdown Section', icon: 'bookmark', html: { link: { props: :values }, item: { props: :values } } active_when: some_condition_is_met?, children_are_open: true, children: [ { title: 'First Page', href: some_path, active_when: true }, { title: 'Second Page', href: '/second_page', external: true } ] }
How to specify links
You can specify this array of navigation link hashes in any of the 3 locations; however, for most applications, it will probably make the most sense to specify your app_navigation_links
in a controller method that you make available as a helper_method
. This will allow you to use the controller context to manage which navigation link is shown as active. Consider this example:
class ApplicationController < ActionController::Base # ... def app_navigation_links [ { title: 'Dashboard', href: root_path, active_when: controller_path == 'application' }, { title: 'Manage Things', href: things_path, icon: 'edit', active_when: controller_path == 'things' }, { title: 'Manage Roles', children: [ { title: 'By Person', href: roles_users_path, active_when: controller_path == 'roles/users' }, { title: 'By Resource', href: roles_resources_path, active_when: controller_path == 'roles/resources' }, ] } ] end helper_method :app_navigation_links end
Using this mechanism, you can ensure that the appropriate navigation link is shown as active, using controller_path
, action_name
, and/or params
as determining factors.
If you need to specify a special set of app_navigation_links
for one or a few particular views, you need to use the set_app_navigation_links
helper method, and not simply pass the array of hashes to content_for
(as content_for
requires strings and doesn't handle more complex objects like arrays or hashes).
Accentuating the "active" link
A navigation link will be styled in an "active" state if it's associated active_when
attribute resolves to true
when the view is resolved. The specific style is attached to the link's parent li
by toggling the active
class on that element.
You can easily use any logic available to the controller at the time the view is rendered. For example you could use the following ActiveController methods:
def app_navigation_links [ # ... { title: 'View Applicants', href: applicants_path, active_when: controller_path == 'applicants' && action_name == 'index' } # ... ] end
The item above would be displayed as active when viewing the applicants#index
action, and any parent navigation links would be expanded to ensure it was visible. The same is true of any parent navigation link if it has a child with an active_when: true
attribute, or one that resolves to true.
Gotchas
An html
hash can be passed in for navigation links and their containers ("items") like so:
# within app_navigation_links array { title: 'Cool beans' , icon: 'beans', href: beans_path, html: { item: { class: 'bean-class', data: { is_beans: true } }, link: { class: 'underline' } } }
This can be useful for attaching data attributes and classes as shown above. It is worth noting that if you have CSP headers that prevent inline styles, attaching custom styles to navigation links via html: { link: { style: ... } }
will not display in the browser. If your browser's console shows any such warnings it is advisable to apply styles using either Tailwind's functional classes or your own classes and targeted CSS.
Custom static content: adding elements that are not app nav links
For advanced or specific cases, you can also add arbitrary "static" content to the app navigation sidebar by including an entry in the array you supply to app_navigation_links
. This type of sidebar element is not covered by the standard Frontend Team Warranty.
An example of the interface is as follows:
def app_navigation_links [ # ... { static: helpers.tag.div('', class: 'w-full mx-8 border border-grey-light') }, # ... ] end
NOTE you will have to monitor this static element carefully and potentially tune its content or styles by hand. Very tall or wide content may produce odd scrolling or unexpected overflow. Caveat lector.
The item must be a hash with a key/value pair of static
and something that can be inserted directly into a view partial. You can use the helpers
variable to access methods used only in views, like tag
. You can also insert an HTML-Safe String among other things.
Use cases
This type of entry can be used to insert non-link content such as a horizontal divider (as in the example above) or an "empty state" when the sidebar is empty but will contain user-configured entries (like adding favorites in the My Dot Med Gateway).
NOTE Please consider every other option before adding custom interactive elements to the sidebar. The app navigation sidebar is universally used for app navigation—adding other elements risks breaking its semantic importance.