https://github.com/artofcode-/structured_menus
An easy way to create flexible menus for Rails apps.
https://github.com/artofcode-/structured_menus
dropdown menus rails ruby
Last synced: about 1 month ago
JSON representation
An easy way to create flexible menus for Rails apps.
- Host: GitHub
- URL: https://github.com/artofcode-/structured_menus
- Owner: ArtOfCode-
- License: mit
- Created: 2018-07-29T18:35:38.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2023-03-08T19:51:27.000Z (about 2 years ago)
- Last Synced: 2025-02-13T19:45:56.318Z (3 months ago)
- Topics: dropdown, menus, rails, ruby
- Language: Ruby
- Size: 53.7 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# `structured_menus`
An easy way to create flexible menus for Rails apps.## Installation
Add this line to your Gemfile and run `bundle install`:gem 'structured_menus'
Next, create a configuration file in `config/initializers`, probably called `structured_menus.rb` because convention, and add the following to it:```ruby
StructuredMenus::Configurator.configure do |config|
# You don't have to add anything here, if you like the defaults, but you still need to call `configure`.
end
```## Quick Start
Once you've done the above, create `app/menus/menu.yml`, and add the following to it:```yaml
- name: FAQ
icon: question
link: /faq
```In the view in which you want to display the menu, add this code:
```erb
<%= Rails.menus.show :menu, :dashboard, current_user %>
```You can substitute `:dashboard` for `:dropdown` if you want a Bootstrap dropdown menu instead; if you don't have a `current_user` method, use `nil`.
Continue reading for more detailed usage options.
## Usage
StructuredMenus enables you to create menus for your app by writing YAML files in (by default) `app/menus`. Each file is a menu; each item in the file
becomes an item on your menu, displayed according to the adapter (more on that later) and options you specify. Such a file might look like this:```yaml
- name: Admin
icon: cogs
link: /admin
if: 'lambda { |u| u&.has_role?(:admin) }'- name: CRM
icon: users
link: /crm- name: Orders
icon: money-bill-alt
link: /orders
```Save that as `mymenu.yml`, and you'll be able to call `Rails.menus.show :mymenu, :dashboard, current_user` to pop it up anywhere in your app.
### Adapters
Adapters are the bits that control how the menu is actually displayed. There are two included by default: `:dashboard` and `:dropdown`. Both are
designed to work with Bootstrap and FontAwesome (yes, I'm opinionated). Each adapter supports different options - see the definitions in
`lib/structured_menus/adapters` for details on what they are.- **Dashboard** is designed to be a full-screen main menu type thing, probably for apps with lots of navigation. The example menu YAML shown above
looks like this when shown (some custom CSS - the topbar is not part of the menu):
[](https://i.stack.imgur.com/n0sbQ.png)
Use `:dashboard` in your call to `Rails.menus.show` to get this adapter.
- **Dropdown** is, well, a Bootstrap dropdown menu. It doesn't include icons by default, but you can make it do so if you want them. The same YAML
looks like this with the dropdown adapter:
[](https://i.stack.imgur.com/rc1Ww.png)
Use `:dropdown` in your call to `Rails.menus.show` to get this adapter.
#### Custom adapters
If those two don't suit your needs, you can write your own custom adapter. Essentially, this needs to emulate one of the two stock adapters, in that:- It must respond to `#show`
- Calls to `#show` must respond with the string of raw HTML that you want to render.
For reference, here's what the dashboard adapter looks like:```ruby
module StructuredMenus::Adapters
class DashboardAdapter
include ActionView::Helpers::UrlHelper
include ActionView::Helpers::OutputSafetyHelper
def self.show(menu, user, **options)
inst = new
width = options[:width] || 4
cards = menu.map do |i|
next unless !i['if'] || instance_eval(i['if']).call(user)cls = options[:class] || 'dashboard-menu-card'
inst.raw("#{inst.link_to inst.raw(" #{i['name']}"), i['link']}")
end.compactinst.raw(cards.in_groups_of(12 / width).map(&:compact).map do |g|
'' + g.map { |c| "'#{c}" }.join("\n") + '
end.join("\n"))
end
end
end
```The parameters that will be passed to `#show` are as follows:
- `menu` - a parsed YAML file, in the form of an array. Each element is a hash representing a single menu item as specified in the file.
- `user` is the value passed to `Rails.menus.show`, which should be a reference to the current user. This can be `nil`.
- `**options` is a hash of additional options - it's up to you what you want to support. Look at the adapter files in `lib/structured_menus/adapters`
to see the options that the stock adapters support.
Once you've written your adapter, tell structured_menus about it by adding it to the configuration file:```ruby
StructuredMenus::Configurator.configure do |config|
config.adapters << YourCustomAdapterClass
end
```## Contributions
Welcome. Ping me a PR. For large changes you should probably open an issue first to discuss.## License
Available under the terms of the MIT license.