Context menu or Action buttons ?

Recently I was drawn into one of those UI “religious” disputes that has no easy answers and usually both sides are right. One of our web developers was trying out new web tech (with pretty rich widget library) and started to question himself about some basic usability decisions. The low level problem in this case is usually brought to “which widget should I use ?”. I’m not fond of bringing the usability problems to questions: Should I use Tabs over Menu ? Or should I use Context menu instead of buttons panel ? But sometimes if time is crucial factor and other usability levels are by default not addressed at all – better developer that asks those basic questions than developer that do not question himself at all.

Recently I was drawn into one of those UI “religious” disputes that has no easy answers and usually both sides are right. One of our web developers was trying out new web tech (with pretty rich widget library) and started to question himself about some basic usability decisions. The low level problem in this case is usually brought to “which widget should I use ?”. I’m not fond of bringing the usability problems to questions: Should I use Tabs over Menu ? Or should I use Context menu instead of buttons panel ? But sometimes if time is crucial factor and other usability levels are by default not addressed at all – better developer that asks those basic questions than developer that do not question himself at all. One of often “problematic” choice that is bring up by web developers is should user launch actions on selected objects (one of many or some of many) by “Context menu” or “Action buttons”. Basic example is shown below and it is usually a table or list of components that has some defined actions (i.e. on table where rows are single orders change status of selected order would be on of possible actions). Of course there are many other solutions that can be implemented (some actions can be handled directly in table row or cell) but narrowing choice to those two was subject of mentioned discussion. During those hot and fast discussions I wasn’t able to point out pros and cons of both solution that’s why I decided to grab them all in this one short post. I hope it will be helpful for same lone developers that thirstily look for best practise or choice while the answer is usually much contextual…

Action button panel

example_view_1

(plus) Pros

  • Clear indication of where and how many actions you can apply to selected row (or other selected object)
  • If action panel is visible all the time theme has expectable behaviour (at least if you are consistent at where you position your action panel)
  • Accessible solution on most mediums (mouse, touch screens, other pointing devices), panel can be bookmarked to be heard on reading devices
  • Action panel can be combined with Details panel (if there is enough space)
  • Actions can be described very precisely

(minus) Cons

  • Space consumption, even if some actions can be hidden under “Advanced” button, this design is always more “stuffed”
  • Can generate (sometimes really long) extra mouse moves and additional clicks
  • Keyboard support may be difficult if rows or selected widgets also use navigations buttons (tab key, arrows etc.)

Context menu

{#Test-Contextmenu}

example_view_2

(plus) Pros

  • If you stick to short action names space consumption is minimal and since it’s used only during action selection it’s also less perceptible
  • Much faster if you use mouse or keyboard (with context menu shortcut / button)
  • Actions can be organised in tree like hierarchy which can be navigated (expanded) with minimal mouse moves and no additional mouse clicks
  • Nicely combines with drag&drop or multi record actions

(minus) Cons

  • Since context menu is invisible until explicitly called some people may not be aware that there are any actions available on selected objects
  • Poor support on some touch pads or touch screens, problematic support on screen readers
  • If used in web applications it overrides default browser context menu which can be a nuisance for some users

Why not both ?

{#Test-Whynotboth%3F}

example_view_3

(plus) Pros

  • Beginners has clear indication of where and what actions are available on selected objects
  • Advanced users can use faster context menu approach, that do not confuse beginners (they still has their action buttons)
  • Action buttons panel can be compressed to minimum, only to show most important actions (other actions can be hidden under “Advanced” button)
  • Action panel can be combined with Details panel, since action buttons would be minimal, there should be more space for details
  • Hide action panel option if workspace size is crucial (i.e. some clients has limited screen size) and users are aware of context menu

(minus) Cons

  • Initially you still loose some fix space
  • Redundancy may be confusing for some users (although this con is questionable – unaware beginners do not see any redundancy, advanced users can hide action panel if it REALLY bothers them)

Summary Choice between Context menu or Action buttons panel is pretty contextual and “right” choice strongly depends on supported media and user group. However there is pretty good “mix” solution that gives more pros than cons (unless redundancy is big problem for you) and will satisfy unaware beginners and users that strives for fast actions. If you come to mentioned choice, always give a chance to “why not both ?” scenario.

You May Also Like

Spock, Java and Maven

Few months ago I've came across Groovy - powerful language for JVM platform which combines the power of Java with abilities typical for scripting languages (dynamic typing, metaprogramming).

Together with Groovy I've discovered spock framework (https://code.google.com/p/spock/) - specification framework for Groovy (of course you can test Java classes too!). But spock is not only test/specification framework - it also contains powerful mocking tools.

Even though spock is dedicated for Groovy there is no problem with using it for Java classes tests. In this post I'm going to describe how to configure Maven project to build and run spock specifications together with traditional JUnit tests.


Firstly, we need to prepare pom.xml and add necessary dependencies and plugins.

Two obligatory libraries are:
<dependency>
<groupid>org.spockframework</groupId>
<artifactid>spock-core</artifactId>
<version>0.7-groovy-2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupid>org.codehaus.groovy</groupId>
<artifactid>groovy-all</artifactId>
<version>${groovy.version}</version>
<scope>test</scope>
</dependency>
Where groovy.version is property defined in pom.xml for more convenient use and easy version change, just like this:
<properties>
<gmaven-plugin.version>1.4</gmaven-plugin.version>
<groovy.version>2.1.5</groovy.version>
</properties>

I've added property for gmaven-plugin version for the same reason ;)

Besides these two dependencies, we can use few additional ones providing extra functionality:
  • cglib - for class mocking
  • objenesis - enables mocking classes without default constructor
To add them to the project put these lines in <dependencies> section of pom.xml:
<dependency>
<groupid>cglib</groupId>
<artifactid>cglib-nodep</artifactId>
<version>3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupid>org.objenesis</groupId>
<artifactid>objenesis</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>

And that's all for dependencies section. Now we will focus on plugins necessary to compile Groovy classes. We need to add gmaven-plugin with gmaven-runtime-2.0 dependency in plugins section:
<plugin>
<groupid>org.codehaus.gmaven</groupId>
<artifactid>gmaven-plugin</artifactId>
<version>${gmaven-plugin.version}</version>
<configuration>
<providerselection>2.0</providerSelection>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupid>org.codehaus.gmaven.runtime</groupId>
<artifactid>gmaven-runtime-2.0</artifactId>
<version>${gmaven-plugin.version}</version>
<exclusions>
<exclusion>
<groupid>org.codehaus.groovy</groupId>
<artifactid>groovy-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupid>org.codehaus.groovy</groupId>
<artifactid>groovy-all</artifactId>
<version>${groovy.version}</version>
</dependency>
</dependencies>
</plugin>

With these configuration we can use spock and write our first specifications. But there is one issue: default settings for maven-surefire plugin demand that test classes must end with "..Test" postfix, which is ok when we want to use such naming scheme for our spock tests. But if we want to name them like CommentSpec.groovy or whatever with "..Spec" ending (what in my opinion is much more readable) we need to make little change in surefire plugin configuration:
<plugin>
<groupid>org.apache.maven.plugins</groupId>
<artifactid>maven-surefire-plugin</artifactId>
<version>2.15</version>
<configuration>
<includes>
<include>**/*Test.java</include>
<include>**/*Spec.java</include>
</includes>
</configuration>
</plugin>

As you can see there is a little trick ;) We add include directive for standard Java JUnit test ending with "..Test" postfix, but there is also an entry for spock test ending with "..Spec". And there is a trick: we must write "**/*Spec.java", not "**/*Spec.groovy", otherwise Maven will not run spock tests (which is strange and I've spent some time to figure out why Maven can't run my specs).

Little update: instead of "*.java" postfix for both types of tests we can write "*.class" what is in my opinion more readable and clean:
<include>**/*Test.class</include>
<include>**/*Spec.class</include>
(thanks to Tomek Pęksa for pointing this out!)

With such configuration, we can write either traditional JUnit test and put them in src/test/java directory or groovy spock specifications and place them in src/test/groovy. And both will work together just fine :) In one of my next posts I'll write something about using spock and its mocking abilities in practice, so stay in tune.