Components
UI building blocks
Action bars
Action bars serve as your main navigation throughout your app. These hold the app icon, app title, action buttons, and can also hold tabs.
App icons must be 32px in height. It can have any width though as long as your prototype doesn't break its layout.
<header class="action-bar"> <a href="javascript: void(0);" class="app-icon action"> <i class="icon-fries"></i> </a> <h1 class="title">Title</h1> </header>
Action bar with subtitles
You can also create an action bar with a title and a subtitle
<header class="action-bar"> <a href="javascript: void(0);" class="app-icon action"> <i class="icon-fries"></i> </a> <h2 class="title">Title <span class="subtitle">Subtitle</span></h2> </header>
Action overflows
Currently, in Fries, you can only add a maximum of two (2) action buttons to the action bar when the device width is less than 480 pixels (which will most likely change in future updates to follow the official Android rules for setting overflows) and you have an app icon and title. This is where action overflows come in.
Action overflows automatically convert action buttons into a Spinner when there are more than two buttons in your action bar. Fries will automatically use the value of the button's title
attribute to generate a Spinner item. So make sure that you add a title
to your action buttons.
<header class="action-bar fixed-top"> <a href="javascript: void(0);" class="app-icon action"> <i class="icon-fries"></i> </a> <h1 class="title">Action Buttons</h1> <ul class="actions pull-right"> <li><a href="javascript: void(0);" class="action" title="Search"><i class="icon-search"></i></a></li> <li><a href="javascript: void(0);" class="action" title="Copy"><i class="icon-copy"></i></a></li> <li><a href="javascript: void(0);" class="action" title="Cut"><i class="icon-cut"></i></a></li> <li><a href="javascript: void(0);" class="action" title="Settings"><i class="icon-settings"></i></a></li> </ul> </header>
Bottom-fixed action bars
You can also fix your action bars at the bottom of the page by adding .fixed-bottom
class to your action bars.
<nav class="action-bar fixed-bottom"> <ul class="actions flex"> <li><a href="javascript: void(0);" class="action" title="Map"><i class="icon-location-marker"></i></a></li> <li><a href="javascript: void(0);" class="action" title="Calendar"><i class="icon-calendar"></i></a></li> <li><a href="javascript: void(0);" class="action" title="Dial"><i class="icon-dial"></i></a></li> <li><a href="javascript: void(0);" class="action" title="Hang up"><i class="icon-hang-up"></i></a></li> </ul> </nav>
Tabs
Tabs are usually used to navigate between multiple screens.
The following example is rendered by the code below it.
<nav class="tab-fixed"> <ul class="tab-inner"> <li class="active"><a href="#item1" data-ignore="true">Tab 1</a></li> <li><a href="#item2" data-ignore="true">Tab 2</a></li> <li><a href="#item3" data-ignore="true">Tab 3</a></li> </ul> </nav>
The content that slides when a tab is clicked should follow the following markup. Notice that the href
attributes of the tabs above match the id
attributes of each .tab-item
.
<div class="content"> <div class="slider"> <ul> <li id="item1" class="tab-item active"> <!-- Any content can go here --> <div class="inset"> <p>Item 1</p> </div> </li> <li id="item2" class="tab-item"> <!-- Any content can go here --> <div class="inset"> <p>Item 2</p> </div> </li> <li id="item3" class="tab-item"> <!-- Any content can go here --> <div class="inset"> <p>Item 3</p> </li> </ul> </div> </div>
Spinners
Spinners come in handy when you want to save up on horizontal real estate and works like a dropdown UI component. Currently, Fries does not change the value of the selected spinner item. It's up to you to do that for now.
<div class="form-spinner"> <a href="javascript: void(0);" class="toggle-spinner">Home</a> <ul class="spinner"> <li class="spinner-item"><a href="javascript: void(0);">Work</a></li> <li class="spinner-item"><a href="javascript: void(0);">Secondary</a></li> </ul> </div>
An action overflow is also an example of a spinner.
Lists
Lists can be used to organize your data.
- Single Line List
- List item number one
- Second list item
- This is the third item and this is a very long line.
<ul class="list inset"> <li class="list-divider">Single Line List</li> <li class="list-item-single-line">List item number one</li> <li class="list-item-single-line">Second list item</li> <li class="list-item-single-line">This is the third item and this is a very long line.</li> </ul>
2-Line Lists
- 2 Line List
-
First Item
Lorem ipsum dolor sit amet.
-
Second Item
Another list item's description.
<ul class="list inset"> <li class="list-divider">2 Line List</li> <li class="list-item-two-lines"> <h3>First Item</h3> <p>Lorem ipsum dolor sit amet.</p> </li> <li class="list-item-two-lines"> <h3>Second Item</h3> <p>Another list item's description.</p> </li> </ul>
Multi Line Lists
- Multi Line List
-
Multi Line List Item
Suspendisse potenti. Mauris accumsan consequat urna ut ornare. Nunc velit magna, vulputate ac faucibus eu, laoreet eget eros. Quisque tortor dui, gravida in condimentum non, tempus et nibh. Integer congue felis et diam hendrerit imperdiet. Sed pellentesque, ipsum nec vehicula molestie.
-
Second Multi Line List Item
Nunc velit magna, vulputate ac faucibus eu, laoreet eget eros. Quisque tortor dui, gravida in condimentum non, tempus et nibh.
<ul class="list inset"> <li class="list-divider">Multi Line List</li> <li class="list-item-multi-line"> <h3>Multi Line List Item</h3> <p>Suspendisse potenti. Mauris accumsan consequat urna ut ornare. Nunc velit magna, vulputate ac faucibus eu, laoreet eget eros. Quisque tortor dui, gravida in condimentum non, tempus et nibh. Integer congue felis et diam hendrerit imperdiet. Sed pellentesque, ipsum nec vehicula molestie.</p> </li> <li class="list-item-multi-line"> <h3>Second Multi Line List Item</h3> <p>Nunc velit magna, vulputate ac faucibus eu, laoreet eget eros. Quisque tortor dui, gravida in condimentum non, tempus et nibh.</p> </li> </ul>
Forms
The default style of the form component is at block level. All elements are sitting on its own line.
<form class="inset"> <label class="block-label">Email</label> <input type="email" name="email" placeholder="Email" class="input-text"> <label class="block-label">Password</label> <input type="password" name="password" placeholder="Password" class="input-text"> <div class="form-actions"> <input type="submit" class="btn btn-block" value="Submit"> <button type="button" class="btn btn-block">Cancel</button> </div> </form>
Flexible Forms
Flexible forms utilize the layout mode flexbox to fill out each elements parent container either growing to fill unused space or shrinking to avoid overflowing the parent. You can use this form layout by adding the form-flex
class to the <form>
tag.
In a Fries prototype, elements inside a flex-group
container are flexible by default.
<form class="form-flex inset"> <label class="block-label">Full Name</label> <div class="flex-group"> <input type="text" placeholder="First Name" class="input-text flex1"> <input type="text" placeholder="Last Name" class="input-text flex1"> </div> <label class="block-label">Address</label> <div class="flex-group"> <input type="text" placeholder="Address" class="input-text flex2"> <div class="form-spinner"> <a href="javascript: void(0);" class="toggle-spinner">Home</a> <ul class="spinner"> <li class="spinner-item"><a href="javascript: void(0);">Work</a></li> <li class="spinner-item"><a href="javascript: void(0);">Secondary</a></li> </ul> </div> </div> </form>
You can use the classes flex1
, flex2
, and flex3
to tell how each form element flexes and just remove them if you want to fill the whole line.
<form class="form-flex"> <div class="flex-group"> <input type="text" placeholder="Full Name" class="input-text"> </div> <div class="flex-group"> <input type="text" placeholder="Flex 1" class="input-text flex1"> <input type="text" placeholder="Flex 2" class="input-text flex2"> </div> </form>
Dialogs
A dialog is a small window that prompts the user to make a decision or enter additional information. A dialog does not fill the screen and is normally used for modal events that require users to take an action before they can proceed.
The .dialogs
container must be on the same level as .action-bar
and .tab-fixed
. This container holds all your dialogs.
<!-- Button to show the dialog --> <a href="javascript: void(0);" class="btn" id="show-dialog">Show Dialog</a> <!-- Required container for dialogs --> <div class="dialogs"> <div id="my-dialog" class="dialog"> <header class="dialog-title-region"> <h1 class="title">Hello Fries</h1> </header> <div class="dialog-content"> <p>Hi, I'm a dialog.</p> </div> <ul class="dialog-actions"> <li><a href="javascript: void(0);" class="dialog-cancel-button">Cancel</a></li> <li><a href="javascript: void(0);" class="dialog-ok-button">OK</a></li> </ul> </div> <!-- Other dialogs go here --> </div>
Then in your JavaScript code:
var dialog = new fries.Dialog({ selector: '#my-dialog', callbackOk: function () { // Do something here this.hide(); // hide the dialog }, callbackCancel: function () { // Do nothing, the user cancelled this.hide(); // hide the dialog } });
Then show the dialog with:
dialog.show();
Toast Notifications
A Toast notification provides a subtle feedback to the users that something happened.
The good thing about Toast notifications in Fries is that no markup is needed, just JavaScript. Check out the following code to see how to create Toast notifications:
// Add this to a 'click' or 'touchend' event of a button var toast = new fries.Toast({ content: "Message saved as draft." });
Pretty cool right? The code above creates a Toast notification with the message "Message saved as draft" and shows it to the user.
You can also change the duration which the Toast is show by passing the length (in milliseconds) or by using either fries.Toast.duration.SHORT
or fries.Toast.duration.LONG
as a parameter when creating your Toast notifications.
// A short Toast lasts 3 seconds var shortToast = new fries.Toast({ content: "I'm a short Toast.", duration: fries.Toast.duraton.SHORT }); // A long one lasts 5 seconds var longToast = new fries.Toast({ content: "I'm a long Toast.", duration: fries.Toast.duration.LONG }); // Or custom timing var custom = new fries.Toast({ content: "Custom Toast", duration: 7500 // in milliseconds });
Helpers
There are a few helpers that you might want to take note of when you're creating Fries prototypes.
Inset
The .inset
class adds a 15px padding to all sides of a container.
Selectable
The .selectable
class adds a highlight to an element when it's in its active
state. This is usually added to list items so they get highlighted when clicked or touched.
Pretty Input
By default, Fries styles text boxes such as <input type="text">
just as how they would normally look in a native Android app. This is done by wrapping these elements in <span class="input-pretty"></span>
. This span adds those small lines on the edges of the element. However, you can turn this feature off by excluding forms.js
in your build.
Stack.js
Stack.js is an engine adapted from Ratchet's push.js to seamlessly piece together Fries pages. It dynamically loads HTML on the fly and inserts it to your app. This works by firing an AJAX request to get the target HTML and replacing the contents of .page
div.
Same as push.js, stack.js uses the HTML5 History API so the Android device's back button functionality doesn't break.
<!-- An action button that inserts map.html's .page into the current page's .page --> <a href="map.html" class="action" title="Map"><i class="icon-location-marker"></i></a>
You can also specify the transition by adding the data-transition
attribute. You can choose from push
and pop
transitions when stacking pages.
<!-- An action button that pushes map.html --> <a href="map.html" class="action" title="Map" data-transition="push"><i class="icon-location-marker"></i></a>
Since Stack.js listens for all touches, some of your links might not work. To solve this, you can add the data attribute data-ignore="true"
so Stack.js ignores that link.
You may, however, use your own paging engine for your prototypes. Just exclude Stack.js from your build and run your app normally. You'll lose the page animations this way though.