Popular UI Volume 1 - Facebook Application Bar
If you are a Facebook user like myself and 350 million others then you probably noticed the application bar. If you don't know what I'm talking about then check out this screenshot.
The application bar is a menu fixed to the bottom of the Facebook site. It serves as navigation and also displays notifications such as updates or chat. At first I was weary of adding such an obtrusive element on top of the entire site, but have become quite fond of the idea. I really find it useful for its notification functionality. In fact, I have come to rely on it instead of refreshing the page or clicking on the "Home" tab again.
It is an extremely useful UI for such an active website. There are too frequent of updates to rely on an end user to refresh the content. Using a site-wide toolbar at the bottom of every page is a great way of keeping the user aware of important updates. I began to think of how useful it could be in other web applications and decided to try to build one myself.
Less talk, more code
Let's walk through the process of building a Facebook-like application bar using two ComponentOne controls, our ASP.NET Menu control and our ASP.NET ToolTip control.
Want to follow along? Download the code: PopularUI.zip or See it live: Application bar demo
File > New Website
To start I create a new ASP.NET 2.0 website in Visual Studio 2008. Keep in mind this could be done in .NET 3.0 and 4.0 as well. I just chose the lowest common denominator. I name the project PopularUI since I will be adding multiple samples in it. For this sample I will add a directory named FacebookAppBar. Inside it I create an Images folder and added a new WebForm, Default.aspx.
I then add the ComponentOne Palomino dll's to the Bin directory:
- C1.Web.UI.2
- C1.Web.UI.Controls.2
- C1.Web.UI.Design.2
Make a Container
The next step is to make a container to position the application bar in. I am going to use the same ID Facebook does just to make it a better reference. Here is the markup for the page so far:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Facebook Application Bar</title>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
<div id="presence">
<div id="presence_ui">
</div>
</div>
</form>
</body>
</html>
The application bar will go inside the div with id=presence_ui. The rest of the content for the app will go in the first div element in the DOM. The reason this is at the end of the page is to ensure it is not a priority for robots to index. Since this is on every page it should be low in priority in the DOM structure. It also does not need to have priority in tab order (unless you feel it otherwise necessary).
With this markup as-is the application bar will not always be visible. We need to use some CSS to get the right positioning similar to Facebook. To achieve the desired layout we will use fixed positioning. Fixed positioning is not very common since it fixed DOM element in the same place (relative to the window) no matter how the user scrolls the page. It can be a difficult layout option to pull off since the element positioned fixed can end up covering other elements on the page. For example, if Facebook did not correctly build their CSS then the footer of each page might be inaccessible due to the application bar covering it up. So we will add some bottom padding to the body to ensure this doesn't happen. Here is how our CSS looks so far:
Fix the Container
body
{
font-family: "lucida grande" ,tahoma, verdana,arial,sans-serif;
font-size: 11px;
color: #333;
margin: 0;
padding: 0 0 30px 0;
}
#presence
{
position: fixed;
bottom: 0;
left: 0;
width: 100%;
margin: 0;
padding: 0;
height: 25px;
}
#presence_ui
{
position: relative;
margin: 0 15px;
}
The #presence selector is fixing the outer div to the bottom left of the browser and stretching it across the screen. It is also setting the height to ensure it has layout properties and sizes correctly. The #presence_ui selector is positioning itself relative to the fixed container and giving itself some breathing room to the left and right via 15px of margin. I added the font family, size and color to match Facebook by applying it to the entire document.
Add the C1Menu
Now that we have the fixed box at the bottom of our page we can add the menu. First we need to add the declaration to the top of the page:
<%@ Register Assembly="C1.Web.UI.Controls.2" Namespace="C1.Web.UI.Controls.C1Menu" TagPrefix="c1" %>
Next we add the C1Menu control inside the div with id=presence_ui. It is hardcoded for demo purposes, but could be databound just the same. It could also link to URLs in your app or raise JavaScript/Code-behind events to handle. The menu markup is as follows:
<c1:C1Menu ID="C1Menu1" runat="server" Height="25px" ClickToOpen="True" VisualStylePath="~/C1WebControls/VisualStyles" WindowCollisionDetection="True" NestedGroupCheckable="False" UseEmbeddedVisualStyles="True" VisualStyle="ArcticFox">
<Items>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Applications">
<Items>
<c1:C1MenuItemHeader runat="server" NestedGroupCheckable="False" Text="Applications">
</c1:C1MenuItemHeader>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Video">
</c1:C1MenuItem>
<c1:C1MenuItemHeader runat="server" NestedGroupCheckable="False" Text="Bookmarks">
</c1:C1MenuItemHeader>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Ads and Pages">
</c1:C1MenuItem>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Photos">
</c1:C1MenuItem>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Groups">
</c1:C1MenuItem>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Events">
</c1:C1MenuItem>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Marketplace">
</c1:C1MenuItem>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Links">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Notes">
</c1:C1MenuItem>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Gifts">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Edit Applications">
</c1:C1MenuItem>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Browse More Applications">
</c1:C1MenuItem>
</Items>
</c1:C1MenuItem>
<c1:C1MenuItemSeparator runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" ToolTip="Ads and Pages">
</c1:C1MenuItem>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" ToolTip="Photos">
</c1:C1MenuItem>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" ToolTip="Groups">
</c1:C1MenuItem>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" ToolTip="Events">
</c1:C1MenuItem>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" ToolTip="Marketplace">
</c1:C1MenuItem>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" ToolTip="Links">
</c1:C1MenuItem>
<c1:C1MenuItemGroup runat="server" CssClass="right">
<Items>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" Text="Chat (14)">
<Items>
<c1:C1MenuItemHeader ID="C1MenuItemHeader1" runat="server" NestedGroupCheckable="False" Text="Chat">
</c1:C1MenuItemHeader>
<c1:C1MenuItem ID="C1MenuItem1" runat="server" Text="LinkItem1">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator ID="C1MenuItemSeparator1" runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem ID="C1MenuItem2" runat="server" Text="LinkItem2">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator ID="C1MenuItemSeparator2" runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem ID="C1MenuItem3" runat="server" Text="LinkItem3">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator ID="C1MenuItemSeparator3" runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem ID="C1MenuItem4" runat="server" Text="LinkItem4">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator ID="C1MenuItemSeparator4" runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem ID="C1MenuItem5" runat="server" Text="LinkItem5">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator ID="C1MenuItemSeparator5" runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem ID="C1MenuItem6" runat="server" Text="LinkItem2">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator ID="C1MenuItemSeparator6" runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem ID="C1MenuItem7" runat="server" Text="LinkItem3">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator ID="C1MenuItemSeparator7" runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem ID="C1MenuItem8" runat="server" Text="LinkItem4">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator ID="C1MenuItemSeparator8" runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem ID="C1MenuItem9" runat="server" Text="LinkItem5">
</c1:C1MenuItem>
</Items>
</c1:C1MenuItem>
<c1:C1MenuItemSeparator runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem runat="server" ImageUrl="Images/Facebook.png" ToolTip="Notifications">
<Items>
<c1:C1MenuItemHeader runat="server" NestedGroupCheckable="False" Text="Notifications">
</c1:C1MenuItemHeader>
<c1:C1MenuItem runat="server" Text="LinkItem1">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem runat="server" Text="LinkItem2">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem runat="server" Text="LinkItem3">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem runat="server" Text="LinkItem4">
</c1:C1MenuItem>
<c1:C1MenuItemSeparator runat="server">
</c1:C1MenuItemSeparator>
<c1:C1MenuItem runat="server" Text="LinkItem5">
</c1:C1MenuItem>
</Items>
</c1:C1MenuItem>
</Items>
</c1:C1MenuItemGroup>
</Items>
</c1:C1Menu>
Notice that I just used one icon to keep things simple, but it would be easy to add others for the different links. It looks close, but we need a little CSS help to get the Chat and Notification group aligned to the right of the application bar. Here is the CSS to tweak the menu:
.right
{
float: right;
}
div.C1Menu div.C1SubMenu
{
margin-top: -24px;
}
.C1Menu .c1-h-child .C1Opened .C1TextNode, .C1Menu .C1SubMenu .c1-h-child .C1Opened .C1TextNode, .C1Menu .c1-h-child .C1Closed .C1TextNode, .C1Menu .C1SubMenu .c1-h-child .C1Closed .C1TextNode
{
background: none;
padding-right: 0;
}
The odd looking negative margin is to make sure the submenus don't open on top of the application bar. I also took out the default background image for textnodes which is an arrow pointing down. It didn't make much sense to have a down arrow if the submenus opened upwards.
Add the C1ToolTip Just for Kicks
The only thing missing now is nice looking tooltips on each link. To get those we will use a single C1ToolTip control and specify a ToolTipZoneID. Doing this will turn every alt attribute on elements inside this zone into nice pretty tooltips. I am setting the ToolTipZoneID=presence_ui so only the menu items will get this special tooltip in my site. No other elements will be affected.
To get the tooltip we first need to add a reference to the C1ToolTip control like so:
<%@ Register Assembly="C1.Web.UI.Controls.2" Namespace="C1.Web.UI.Controls.C1ToolTip" TagPrefix="c1" %>
Next we need to add a C1ToolTip anywhere in the page. Here is the markup I used:
<c1:C1ToolTip ID="C1ToolTip1" runat="server" ToolTipZoneID="presence_ui" Position="TopCenter" UseEmbeddedVisualStyles="True" VisualStyle="ArcticFox">
</c1:C1ToolTip>
These are small tooltips that do not need a title in them. I am going to add some CSS to remove the title and also give a little padding inside the tooltip. Here is the last bit of code to complete the application bar:
.C1ttTitleBar
{
display: none;
}
.C1ttContentBar
{
padding: 4px;
}
Run it!
There you have it! A cool application bar just like Facebook has built in ASP.NET. Feel free to check out the online version of the application bar. It isn't quite as complex as Facebook's, but you get the gist of it. There are some other cool things we could do to make this even more like the Facebook application bar. Here are some of the ideas I can think of...
- Add drag and drop to move items in the menu
- Use AJAX to change content on the page when items are clicked
- Call a web service to check for updates and notify the user if there are
- Load the chat list dynamically
- Any other ideas? Post a comment!