What do you do with links/buttons/actions that are likely to be infrequently used, but should still be available to users anywhere in the system?  That’s the question I had to answer for the new InSpire search engine we’re working on at my day job.  The sort of links I am talking about are logout, preferences, help, and various admin commands (for administrators only).  These actions are not really part of the application per se, they are more part of the basic application framework that needs to be available to the user.  We didn’t want to take up valuable space in our UI with these things (plus we wanted to keep the UI as basic as possible), so where do you put these things?

I decided I would try an auto-hiding sliding menu.  The behavior I wanted was identical to the Windows task bar when the Auto-hide the task bar option is selected.  After a little jQuery and CSS magic, and some help from Jeff Robbin’s great article on an auto-hiding search box, I had a solution that works in IE 8, Firefox, and Chrome.

First, check out the demo.  The menu bar is themed using jQuery UI, so if your app uses jQuery UI, you will get a consistent look-and-feel.  Also note that my menu bar doesn’t suffer from the same bug that Jeff Robbin’s article does: when you mouse-over and mouse-out my menu bar very quickly a few times, it doesn’t get stuck in a show/hide loop.  Let’s look at the code to see why.  First, the markup and CSS:

<style type="text/css">
#siteMenuBar
{
    position: fixed;
    top: 0px;
    left: 0px;
    width: 100%;
    height: 30px;
    margin-top: -27px;
}

#siteMenuBar > #menuContainer
{
    margin-left: auto;
    margin-right: auto;
    width: 100%;
    height: 25px;
    padding-top: 5px;
}

#siteMenuBar ul
{
    float: right;
    list-style-type: none;
    margin: 0;
    padding: 0;
    font-size: 0.9em;
}

#siteMenuBar li
{
    display: inline-block;
    margin: 0;
    padding: 0 5px 0 5px;
    margin-right: 10px;
}

#siteMenuBar ul:first-child
{
    float: left;
    margin-left: 10px;
}
</style>
...
<div id="siteMenuBar" class="ui-widget">
    <div id="menuContainer" class="ui-widget-header">
        <ul>
            <li><a href="#">Administration</a></li>
            <li><a href="#">Design Guidelines</a></li>
            <li><a href="#">Other Link</a></li>
        </ul>
        <ul>
            <li><a href="#">Preferences?</a></li>
            <li><a href="#">Logout</a></li>
        </ul>
    </div>
</div>

The markup is pretty clean.  There is an outer container for the menu, then an inner container for the actual menu.  The inner container is probably not necessary, but having it allows you the opportunity to do some neat style nesting.  The actual menu is implemented as two unordered lists.  The CSS floats one of the menus to the left, and the other to the right, giving you two groups to add menu items to. 

The styles are a little more complex.  The outer container is giving a fixed position at the top of the window, then positioned mostly off screen with negative margin.  This leaves a small handle visible that the user can mouse-over to show the menu.  The inner container applies a little padding to the menus and could be used to make the menu bar appear to be less than 100% of the window width (though in this case it is allowed to fully fill the menu bar area).  Next, the actual menus are styled and positioned.  Note that both are initially floated to the right, but using the pseudo-selector first-child, we bump the first menu back to the left. 

Now let’s look at the code:

var timeout = null;
var initialMargin = parseInt($("#siteMenuBar").css("margin-top"));

$("#siteMenuBar").hover(
    function() {
        if (timeout) {
            clearTimeout(timeout);
            timeout = null;
        }
        $(this).animate({ marginTop: 0 }, 'fast');
    },
    function() {
        var menuBar = $(this);
        timeout = setTimeout(function() {
            timeout = null;
            menuBar.animate({ marginTop: initialMargin }, 'slow');
        }, 1000);
    }
);

Note the timeout variable.  This is key in fixing the bug that exists on auto-hiding search box.  For flexibility, we also grab the top margin so that we can hide the menu back to its original state.

The real core of the technique is the jQuery hover handler.  We supply two functions: one to execute when the mouse hovers over the menu bar, the other to handle mouse out.  The first time the mouse over handler is executed, the timeout will be null, so it will immediately animate the menu bar, removing the negative margin and making it visible.  On mouse out, the setTimeout function is used to schedule the menu to be hidden one second later.  Note that I’m assigning the return of setTimeout to my timeout variable.  This is what prevents the menu bar from ending up in a bounce-loop like the search box.  It allows me to cancel the hide action.  If the bar is scheduled to be hidden and the user moves the mouse back over the menu bar, the mouse over handler clears the timeout.  Without that bit of logic, even if you move mouse back over the menu bar, the setTimeout function will hide the menu out from under the user, which can lead to that funky show/hide cycle. 

So, there you have it: a simple, clean auto-hide menu with jQuery.  This could easily be encapsulated in a jQuery plug-in for easy re-use (not really needed in my case though since the master page is responsible for rendering it).  Anyway, let me know if you have any suggestions!