# Tabulous Reference ## Contents * [Tabsets](#tabsets) * [Multiple Tabsets](#multiple-tabsets) * [Tab Order](#tab-order) * [Subtabs](#subtabs) * [Tab Names](#tab-names) * [Tab Declarations](#tab-declarations) * [text](#text) * [link_path](#link_path) * [http_verb](#http_verb) * [visible_when](#visible_when) * [enabled_when](#enabled_when) * [active_when](#active_when) * [Customizing](#customizing) * [renderer](#renderer) * [active_tab_clickable](#active_tab_clickable) * [when_action_has_no_tab](#when_action_has_no_tab) * [render_subtabs_when_empty](#render_subtabs_when_empty) * [CSS Scaffolding](#css-scaffolding) * [Helpers](#helpers) * [Generators](#generators) ## Tabsets A tabbed navigation bar, which we will call a tabset, is specified using a tabs block: tabs do unicorns_tab do ... end rainbows_tab do ... end end ### Multiple Tabsets You can have more than one tabset on a page by passing in a name to the tabs block: tabs(:fun) do unicorns_tab do ... end rainbows_tab do ... end end tabs(:colors) do red_tab do ... end blue_tab do ... end end Then, in your layout, you need to tell tabulous which tabset to draw: <%= tabs(:fun) %> <%= subtabs(:fun) %>
some markup
<%= tabs(:colors) %> <%= subtabs(:colors) %> ### Tab Order Tabs are displayed in the order they appear. So if you want a set of tabs that looks like this: ____________ ____________ __________ _| UNICORNS |_| RAINBOWS |_| PONIES |_ your tabs block should look like this: tabs do unicorns_tab do ... end rainbows_tab do ... end ponies_tab do ... end end ### Subtabs Any tab can have several subtabs associated with it that become visible when the parent tab is clicked. Declare subtabs just like tabs, except make sure that their name ends in \_subtab. Subtabs should be declared immediately after their parent tab. Parent tabs must include a_subtab_is_active in their active_when declaration: tabs do unicorns_tab do ... end rainbows_tab do ... active_when { a_subtab_is_active } end monorainbows_subtab do ... end double_rainbows_subtab do ... end ponies_tab do ... active_when { a_subtab_is_active } end shetland_ponies_subtab do ... end end ### Tab Names It doesn't matter what you call a tab, but it must end in \_tab or \_subtab, and it can't have the same name as another tab. tabs do unicorns do # BAD: does not end in _tab ... end rainbows_tab do ... end end ## Tab Declarations Each tab has five required declarations (text, link_path, visible_when, enabled_when and active_when) and one optional declaration (http_verb). The text, link_path, visible_when and enabled_when declarations do not need to be given a block. If given a block, the block will be executed in the context of the layout where the tabs are rendered. You can place any Ruby code in the tabulous blocks; it will be executed as if it were in a view. Here is an example of a tab with the five required declarations: unicorns_tab do text 'Unicorns' link_path '/unicorns' visible_when { current_user.loves_unicorns? } enabled_when true active_when { in_action('any').of_controller('unicorns') } end ### text text must evaluate to a string. This string will be what users see written on the tab. ### link_path link_path must evaluate to a string which is a valid URL or path. This is the URL that the browser will load when the tab is clicked. narwhals_tab do ... link_path { narwhals_path } ... end Since a block given to link_path is evaluated in the context of a view layout and not any particular view, you should not reference HTTP params: narwhal_tab do ... link_path { narwhal_path(params[:narwhal_id]) } # WRONG ... end ### http_verb http_verb is an optional declaration that must be either :get, :post, :put, :patch or :delete. It defaults to :get. When http_verb is not :get, a data-method attribute will be added to the tab's anchor tag. This is useful for adding a "sign out" subtab action link, for example. narwhals_tab do ... http_verb :delete ... end ### visible_when If visible_when evaluates to false (or a falsy value like nil), the HTML for that particular tab will not be generated. This could be used to hide a tab conditionally, for instance: visible_when { current_user.present? } could be used to hide a tab from anonymous users. ### enabled_when If enabled_when evaluates to false (or a falsy value like nil), li tag for that tab will have a "disabled" class. ### active_when Tabulous sets a tab as active depending on the controller action that generated the web page. active_when should list out all of the actions for which the tab should be selected: unicorns_tab do ... active_when do in_action('index').of_controller('unicorns') in_action('show').of_controller('unicorns') in_action('new').of_controller('unicorns') in_action('create').of_controller('unicorns') in_action('edit').of_controller('unicorns') in_action('update').of_controller('unicorns') in_action('destroy').of_controller('unicorns') end end As a convenience, you can list more than one action at a time using in_actions: unicorns_tab do ... active_when { in_actions('index', 'show', 'new', 'create', 'edit', 'update', 'destroy').of_controller('unicorns') } end Since it is common for there to be a one-to-one correspondence between a controller and a tab, you can list the 'any' action as a catch-all: unicorns_tab do ... active_when { in_action('any').of_controller('unicorns') } end The actions that make the tab active do not have to be limited to one controller: unicorns_tab do ... active_when do in_action('any').of_controller('unicorns') in_action('show').of_controller('horses') end end Namespaced controllers, such as Admin::UserAccountsController, can be referenced like so: unicorns_tab do ... active_when { in_action('any').of_controller('admin/user_accounts') } end It is an error for active_when rules of different tabs to overlap or conflict with each other: unicorns_tab do ... active_when { in_action('any').of_controller('unicorns') } end list_unicorns_tab do ... active_when { in_action('index').of_controller('unicorns') } # WRONG, conflicts with above active_when end If a tab has subtabs, it is automatically set to active if any of its subtabs is active. To make this behavior explicit, the parent tab must specify a_subtab_is_active as one of the rules in active_when. ## Customizing Tabulous tries to provide good default behavior to make it easy to quickly add tabs to your app. Tabulous gives you control over some of its choices if you don't like the defaults. ### renderer This specifies the class that the tabs and subtabs view helpers use to generate the tab markup. customize do renderer :default end There are four other renderers you can use: * **:html5** -- uses nav tags instead of divs * **:bootstrap** -- generates markup compatible with Twitter Bootstrap; it creates a ul tag with a "nav-tabs" class * **:bootstrap_pill** -- generates markup compatible with Twitter Bootstrap; it creates a ul tag with a "nav-pills" class * **:bootstrap_navbar** -- generates markup compatible with Twitter Bootstrap's navbar; it creates a ul tag with a "navbar-nav" class If this doesn't suit your needs, you can write your own custom renderer. Here's an example of a custom renderer class: class CustomRenderer < Tabulous::DefaultRenderer def tabs_html <<-HTML.strip_heredoc