Towards the formalization of Intuitive UI

Jul 02, 2010 17:12


Some time has passed since the creation of sviperll_navigation. I've updated the plugin following the Michael Snoyman's post about yesod. And things started to be more interesting. I have removed tags from sviperll_navigation. Tags were used to filter nodes on menu generation. Here is the description of current plugin version.

I've used the following code in the layout to show left menu in my application.

<% navigator.children(:left).each do |node| %> <%= link_to node.title, node.path, node.options %> <% end %>
The description of pages in configuration file looked like

user.node :left, 'Orders', user_orders_path, :class => 'orders' user.node :left, 'Lists', user_lists_path, :class => 'lists'
When I needed tabbed navigation, I used the following in the layout

<% navigator.siblings(:tab).each do |node| %> <%= link_to node.title, node.path, node.options %> <% end %>
The following snippet described pages in the configuration file

user.vnode :left, 'Orders', :class => 'orders' do |orders| orders.node :tab, 'New order', new_user_order_path orders.node :tab, 'Previous orders', user_orders_path end
Tabs at the top of the page were encoded with the :tab tag in the navigation config-file. But this information is redundant, since parent page for the tabs is always virtual page. :tab tag is totally useless in this respect.

:left tag is useless too, since left menu is the main navigation element and :left is used almost everywhere, It is better to encode exceptions. So I've removed tags from navigation plugin entirely and navigation config-file started to look like this

user.vnode 'Orders', :css_class => 'orders' do |orders| orders.node 'New order', new_user_order_path orders.node 'Previous orders', user_orders_path end user.node 'Lists', user_lists_path, :css_class => 'lists' user.node 'Transactions', user_transactions_path, :css_class => 'transactions', :menu => :right
Wich seems much clearer for me.

I've needed to change layout code to generate navigation elements after this change. Left menu generation has become

<% navigator.children.each do |node| %> <% if node.options[:menu].nil? || node.options[:menu] == :left %> <%= link_to node.title, node.path, :class => node.options[:css_class] %> <% end %> <% end %>
Tabs generation has become

<% if !navigator.parent.nil? && navigator.parent.virtual? %> <% navigator.siblings.each do |node| %> <%= link_to node.title, node.path %> <% end %> <% end %>
Tabs are shown only if parent page is virtual page. Being virtual means that it is totally impossible to be shown. Virtual pages serves the purpose to group some pages together, to organize pages' structure. When you click on a virtual element in the menu you get not to the virtual page but to the first not-virtual one in the hierarchy. Tabs are used to support navigation in this case.

Code that generate navigation elements become more smart with the removal of tags. Now it is possible to express in code some ideas of how good UI must be organized.

For example it is good to show "back" link on the pages. But it it not so good for the pages that are shown in tabs. User may arrive to the page by clicking on the tab and not by choosing this page from left menu, in this case "back" link is counter-intuitive. We can express this concerns in the layout code, and It will be used on all pages of application.

<% if !navigator.parent.nil? && navigator.parent.virtual? %> <%= link_to 'Back', navigator.parent.path %> <% end %>
So the main contribution of the plugin is an ability to express properties of UI. In common practice UI properties are stated in some design document. UI is implemented as lots of navigation elements scattered across application pages. Consistency and conformance of implemented UI to design principles in documentation can't be automatically verified. With the abstraction provided by sviperll_navigation plugin, some properties of UI can be expressed with the code within application and UI elements can be consistently used all over the application.

I'm going to publish the plugin on the GitHub under BSD license with one major change. I'm going to change plugin's name. Sviperll navigation is cool but sviperll is my nickname and it is very strong connection to myself. I'm thinking about some name mentioning Magellan or some other great sailor and being a new word not overloaded with any meaning.
Previous post Next post
Up