P. 1
Designing and Developing Trello for Multiple Devices

Designing and Developing Trello for Multiple Devices

|Views: 47,017|Likes:
Published by Bobby Grace

More info:

Published by: Bobby Grace on Mar 22, 2012
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

07/10/2013

pdf

text

original

Designing and Developing Trello for Multiple Devices

Bobby Grace - March 2012

Thursday, March 22, 12

Our approach... one site and one codebase for all devices.

Thursday, March 22, 12

Why

Thursday, March 22, 12

People get a consistent experience.
No redirects. Links work seamlessly. Don’t have to learn a new interface. All the same features. Can read pitch, watch video, sign up and start using it.

Thursday, March 22, 12

We can deliver updates seamlessly.
Mobile site is always up-to-date. Don’t have to retro-fit features for mobile. One place to deploy, easy updates.

Thursday, March 22, 12

Everything we do for mobile translates back to a better desktop experience.
Intuitive interactions Big, finger-friendly hit targets Super fast

Thursday, March 22, 12

What about native apps?

Thursday, March 22, 12

We love native apps! We have an iPhone app and are working on an Android app.
Gives us native speed, native look and feel, push notifications, offline support...

Thursday, March 22, 12

But we didn’t want to ignore the mobile web because of native apps.

Thursday, March 22, 12

How

Thursday, March 22, 12

Optimizing UI Components for Mobile

Thursday, March 22, 12

finger-friendly hit targets

280px

Pop over menus
These context menus are used to log in, show card actions, view notifications, and lots more.

Narrow enough for mobile devices

Thursday, March 22, 12

Only one menu is visible at a time. Simplifies navigation and works on mobile. There are view transitions, though.
1. 2.
Back to Card Actions

Thursday, March 22, 12

This is not going to work for us...
Lots of hover events and complicated nesting. Will work for a desktop-only environment, though.

Thursday, March 22, 12

Shows an action menu button

Dialog windows
These layout elements are used for the “back” of cards, for user pages, and elsewhere.

Collapses to single column

Thursday, March 22, 12

Touch fallbacks

Would normally show up on hover on desktop. Always visible on mobile.

Thursday, March 22, 12

Icons

Thursday, March 22, 12

Sprite your icons.

Thursday, March 22, 12

We use Illustrator for icons so we can easily export high-res versions.
We load them with CSS media queries for high DPI devices like the iPhone 4 and the third-gen iPad.

Thursday, March 22, 12

The CSS looks like this...

Our compiler embeds an inline base64 encoded datauri of the image. One less request.

.app-icon { background-image: embed(../images/icons-1x.png); background-position: -9999px -9999px; &.board-icon { background-position: -60px -30px; } }

(This is LESS.)

@media screen and (-webkit-min-device-pixel-ratio: 1.5), screen and (-webkit-min-device-pixel-ratio: 2) { .app-icon { background-image: url(../images/icons-2x.png); background-size: 690px 144px; } }
This image is 1380x288 (2x), but we use the 1x background-size so all the icon-specific background-positions line up.
Thursday, March 22, 12

Detecting Window Width

Thursday, March 22, 12

We listen for window resizes with JavaScript and add an appropriate class to the body element. CSS takes care of everything else.

Thursday, March 22, 12

The code looks like this...
window.WindowSize = new class calc: => width = $(window).width() @fExtraLarge = @fLarge = @fMedium = @fSmall = @fExtraSmall = false if width > 1280 @fExtraLarge = true else if width > 850 @fLarge = true else if width > 700 @fMedium = true else if width > 500 @fSmall = true else @fExtraSmall = true $("body") .toggleClass("extra-large-window", @fExtraLarge) .toggleClass("large-window", @fLarge) .toggleClass("medium-window", @fMedium) .toggleClass("small-window", @fSmall) .toggleClass("extra-small-window", @fExtraSmall)
Thursday, March 22, 12

(This is CoffeeScript.)

For example...
body.extra-small-window body.large-window

Thursday, March 22, 12

This method gives us an easy way to check the window size in view code.

if WindowSize.fLarge or WindowSize.fExtraLarge renderHugeThing()

We also have a Browser.isTouch() method to selectively load components.

Thursday, March 22, 12

Views

Thursday, March 22, 12

We use Backbone for views. It makes views straightforward and keeps code flexible.

Thursday, March 22, 12

A view look like this...
class CardView extends ViewWithId className: "list-card" events: "click .js-card-menu": "openCardMenu" render: => data = cardModel.toJSON() $(@el).html( Mustache.to_html( templates.card_in_list, data ) ) openCardMenu: (e) => Util.stop(e) PopOver.toggle elem: e.target top: 23 view: cardModel.getView(CardMenuView)

Thursday, March 22, 12

...and this.
class CardMenuView extends EditableView events: "click "click "click "click "click "click

.js-change-members": "changeMembers" .js-edit-labels": "editLabels" .js-move-card": "moveCard" .js-due-date": "changeDueDate" .js-vote": "vote" .js-close-card": "close"

render: => data = {foo: ‘bar’} $(@el).html( Mustache.to_html( templates.popover_card_menu, data ) ) changeMembers: (e) => Util.stop(e) PopOver.pushView view: model.getView(CardMemberSelectView) # ... editLabels(), moveCard(), etc.

Push another view (select members) onto the stack. PopOver will load the view and handle transitions.

Thursday, March 22, 12

Templates

Thursday, March 22, 12

We use Mustache for templates. They are strictly logic-less, which keeps code clean.

Thursday, March 22, 12

Templates look like this...
card_in_list.html ----------------<div class="card-labels clearfix"> {{#labels}} {{#isActive}} <div class="card-label {{color}}-label"> </div> {{/isActive}} {{/labels}} </div> {{#__ed}} <span class="card-operation app-icon dark-hover small-icon menu-icon js-card-menu"></span> {{/__ed}} <a href="{{url}}" class="list-card-title clear"><span class="card-short-id hide">#{{idShort}} </ span>{{name}}</a> <div class="badges"></div> Dynamically loaded <div class="list-card-members"></div>

elsewhere in the view

Note: The view wraps this with an element with class View.className, in this case ‘.list-card’. Make good use of className so you don’t end up with useless divs.

Thursday, March 22, 12

Thanks!
trello.com twitter.com/trello twitter.com/bobbygrace

Thursday, March 22, 12

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->