Let the Browser Handle Your UI Logic for You

At Parse, we’re in the middle of refreshing our frontend stack, and much of that has meant reevaluating the way we write browser-bound code. We’ve begun developing new custom inputs such as date pickers, dropdowns, or toggles in a way that leverages default browser behaviors to let us write less JavaScript (and reduce opportunities for bugs). Nearly every web developer has seen or implemented a date input that looked like a calendar, and chances are it contained plenty of logic to ensure that only one day could be selected at a time. This is the exact type of logic we’re trying to let the browser handle as we rebuild our interfaces.

It all starts with a simple checkbox

Let’s consider the scripting that might go into implementing a checkbox-style switch. When we click a switch that’s “off,” we change its state to “on” and get some visual feedback. We’d probably store its state in a boolean variable somewhere, add a click handler that updates the boolean, and then add or remove CSS classes based upon its current value. From a logic standpoint, it’s a duplication of something the browser can already do with <input type="checkbox">, but we put up with it for years because it let us have pretty switches.

Then the technique of using checked state to style checkboxes hit the mainstream. Using a combination of new CSS selectors and older browser behavior, it was possible to have visual elements that were tied to invisible inputs without writing a single line of JS. We use this same technique for many of our basic toggle switches today, but we’ve also taken it to new extremes with many of our UI components.

When building components, examine their core behavior

When we build new UI components for Parse.com, we follow a simple strategy: use the most similar browser element as a starting point. This goes beyond the obvious cases — such as using an anchor tag for something the user clicks — and looks at the inner behavior of a complex element. Remember the date picker we discussed earlier? The core interaction relies on being able to select a single day out of the month and visually represent that selection. Your browser already knows how to handle this: it’s behaviorally identical to a set of radio buttons! In fact, you’d be amazed by how many complex elements boil down to the radio button’s select-one-of-many behavior. They’re at the core of our own date picker, our fully styled dropdown menus, and a number of other switches and toggles. Knowing that the browser will ensure a single element is selected at any time allows us to eliminate a concern from our client logic.

uie_blog_2

Simultaneously, we avoid having to synchronize our data with our visualization, because a single interaction within the browser updates both. Along those same lines, at Parse we refrain from storing any data within a component that could be reasonably derived from its inner elements. For our specialized numeric inputs, we get the value by parsing the contents of an inner text input on demand, rather than returning an in-memory value that we update with an onChange handler. This guarantees that our JS component and its visual appearance never get out of sync.

Enough talk, let’s see a demo

My favorite implementation of this technique is found in our Hosting product. It’s a file tree that features complex interactions with absolutely no JavaScript.

uie_blog_3

When I designed the tree, I broke it down into its core behaviors: it has folders that open and close to display contents, and an overall set of files that can be individually selected. If you’re following along, it should make sense that the folders are backed by checkboxes while the files themselves are a single set of radio buttons.

<!-- Files are a set of radio buttons with the same name field -->
<input type="radio" name="hosted_files" id="f_myfile_js" value="MyFile.js">
<label for="f_myfile_js">MyFile.js</label>

<input type="radio" name="hosted_files" id="f_another_js" value="Another.js">
<label for="f_another_js">Another.js</label>

<!-- Folders are checkboxes that toggle the visibility of divs -->
<input type="checkbox" id="f_myfolder">
<label for="f_myfolder">My Folder</label>
<div class="dir_wrapper">
  Folder contents...
</div>

In CSS, we simply provide default styles for labels, and additional styles for when they follow a checked input.

label {
  color: #ffffff;
}
input[type=radio]:checked + label {
  color: #5298fc;
}

For folders, we also toggle the display property of a .dir_wrapper element that comes after a selected checkbox.

.dir_wrapper {
  display: none;
}

input[type=checkbox]:checked + label + .dir_wrapper {
  display: block;
}

With these styles, I don’t need to worry about having numerous click handlers to open or close folders, and a single change handler on the radio buttons can tell me when a new file is selected.

You can examine a slightly modified version of our file tree at this CodePen.

So what?

As web developers, we tend to lean a lot on JavaScript to build fancy interfaces and effects. I know I certainly do. But the next time you set out to build something new, look at its core behaviors and ask yourself if there is some pre-written, standardized part of the web browser that can handle some of the work for you. Yes, there is a bit of a tradeoff with markup instead of code, but I’d rather write code to generate HTML than deal with synchronizing data and visualization, handling a plethora of clicks, taps, and keyboard inputs, and ultimately replicating behavior that’s already embedded in the browser.

With these methods, you can build custom inputs that play nicely with the existing web. They fire native change events, they don’t risk side-effects in your view logic, and in many cases they even improve screen reader accessibility. If you take a look at the HTML5 spec for radio buttons, you’ll see that it only talks about behavior, not appearance. It’s no long stretch to reuse that behavior in new and creative ways, and I look forward to seeing how others employ it for interface construction.

Andrew Imm
November 10, 2014

Introducing the new ParseUI for iOS

ParseUI iOS

A couple of months ago, iOS added new screen resolutions for developers to support in their apps.  As a result, many developers needed to update their user interfaces to look native on these new screen sizes.

Today we’re introducing ParseUI for iOS, a collection of user interface components aimed to streamline and simplify user authentication, data list display, and other common app elements. You might be familiar with these components already, as they were previously packaged inside the main Parse iOS SDK. With this release, we’ve updated how they look and made them resolution-independent to ensure a polished presentation on any screen.

A New Look

Inside this release you’ll find all new designs for every component with simplified user interfaces plus many under-the-hood improvements, such as smoother animations and faster rendering. To give you an example, here’s how `PFLogInViewController` looked before and how it looks today:

ParseUI iOS New Look

Resolution-Independent

All components were rebuilt from scratch to be resolution-independent, meaning they both look great and are native on any screen resolution. This resolution-independent approach also introduces support for more presentation options. It gives you the flexibility to comprehensively customize everything within your application’s navigation and layout.

ParseUI iOS

Open Source

ParseUI is all open source, and you can view the code on GitHub. You can also access the new version of the Parse iOS SDK here.

We’re really excited to be open sourcing more and more of our product. Check out these other projects on GitHub: BoltsFramework, Parse PHP SDK, ParseUI for Android and App Links Analytics.

We can’t wait to see what you build with it! Send us your feedback!

Nikita Lutsenko
November 6, 2014

A New Design for the Dashboard

blog_post_dashboard

The Dashboard is an essential piece of the Parse experience. We care deeply about it, and know how much you love having this web user interface to see the analytics of your apps, to follow up on your Cloud Code deploys, to visualize and edit your data in the Data Browser, and to schedule advanced Push notifications. Today, we’re very excited to introduce a redesign of the Dashboard that we hope you will love just as much as we do.

With the new design, we’ve made sure that the UI gets out of the way, so you can focus more on what you’re doing, as well as your data. We’re also very excited that the Dashboard is now stretchable, which means you can expand your Data Browser or the documentation without going into full screen mode.

We’re dedicated to making the best web application to manage your Parse apps, and we hope you like the new features in the dashboard!

Christophe Tauziet
May 6, 2013

Animating the New Parse About Page

Parse

One of our last projects of 2012 was to give our About page a fresh new look. The day we started working on its redesign, we knew we wanted it to really express what Parse is about, and that we wanted it to be beautiful and enjoyable to go through.

Because we received such great feedback on our previous Cloud Modules animated icon tutorial, today I’m offering you some insight on how we built the new about page top animation using some of the newest CSS3 features. We’ll be using SASS/Compass for more clarity in the code.

Read more…

Christophe Tauziet
January 10, 2013

Parse.com now looks even better on mobile phones

Because many of you like to check our website while traveling, or to check our docs very quickly on-the-go, creating a mobile-friendly version of Parse.com has always been something we wanted to do. The Parse team has been working hard on it for months, trying to figure out the best way to do it, and designing the best possible surfing experience.

As we knew how cool and useful having mobile-ready Parse documentation would be, we took extra care in making it enjoyable to read. This is just the first step, but we think it’s a big one.

From now on, you can go to our website from your favorite smartphone and find out about our products, our company, or read our documentation. We’re incredibly excited about this announcement and hope you’ll like it as much as we do.

Christophe Tauziet
December 4, 2012

Animating the Cloud Modules Icon

Every time we launch a new product, we try to offer our users a delightful experience on our landing pages. This sometimes involves creating a nice animation that gives life to the product icon. We received so much great feedback for our Cloud Code icon animation that we really wanted to do something cool for our new Cloud Modules feature.

Today I’m giving you some insight on how we built the Cloud Modules icon animation, using JavaScript and a little bit of CSS3.

Let’s start by creating the HTML for this animation.

<div class="icon">
  <div class="bricks"></div>
  <div class="final_icon"></div>
</div>

We only need a div that will contain our little “bricks”, a div that will contain the final icon that will fade in at the end of the animation, and a wrapper div to correctly position the icon in the page.

Then we need to write the CSS that will make things look good.

.icon {
    position: relative;
    width: 435px;
    height: 284px;

    .bricks {
        .brick {
            width: 11px;
            height: 11px;
            @include border-radius(3px);
            @include background-image(linear-gradient(#FFFFFF, #B9B9B9));
            @include box-shadow(rgba(#FFFFFF, 0.7) 0px 0px 1px, rgba(#000000, 0.6) 0 2px 3px);
            position: absolute;
            @include single-transition(all, 0.5s, ease);

            &.displayNone {
                display: none;
            }

            &.illuminated {
              -webkit-animation: illuminatedBrick 0.7s ease-out 1;
              -moz-animation: illuminatedBrick 0.7s ease-out 1;
              animation: illuminatedBrick 0.7s ease-out 1;
            }
        }
    }
    .final_icon {
        display: none;
        margin-top: -17px;
        margin-left: -20px;
        width: 467px;
        height: 318px;
        position: absolute;
        background: url(/images/products/cloud_code/cloud_modules_final_icon.png) no-repeat;
        @include image-2x("/images/products/cloud_code/cloud_modules_final_icon@2x.png", 462px, 318px);
    }
}

Here we’re using some SASS mixins provided by Compass and a custom mixin for providing Retina assets from Jason Zimdars’s solution, and we’re also using a CSS animation called illuminatedBrick that we first need to declare.

@keyframes illuminatedBrick {
    0% {
        background-image: none;
        background-color: white;
        @include box-shadow(rgba(white, 0.7) 0px 0px 1px, rgba(#da79f3, 0.6) 0 0px 3px);
    }
    100% {
        background-image: none;
        background-color: #da79f3;
        @include box-shadow(rgba(white, 0.7) 0px 0px 1px, rgba(#da79f3, 0.6) 0 0px 25px 5px);
    }
}

Note that we also need to declare @-webkit-keyframes and @-moz-keyframes if we want to support all WebKit based browsers and Firefox.

Let’s now write the JavaScript magic that will create all the bricks and animate them.

We first declare a matrix of all the relative coordinates of the bricks. Each brick position depends on its predecessor. This way, it becomes very easy to change the positioning or behavior of the animation if needed. And we add the bricks to the bricks div using a loop.

var matrix = [[0,0], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], 
[0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [0,-12], 
[0,-12], [0,-12], [0,-12], [0,-12], [0,-12], [-2,-12], [-5,-12], [-5,-12], [-9,-11], [-10,-10], 
[-11,-9], [-12,-7], [-12,-5], [-12,-4], [-12,1], [-12,1], [-12,3], [-12,4], [-12,5], [-12,7], 
[-10,10], [-8,11], [-7, 11], [-3,12], [-12,5], [-12,5], [-12,6], [-11,9], [-11,9], [-10,10], 
[-6,12], [-6,11], [-5,12], [-3,12], [-1,12], [0,12], [0,12], [2,12], [4,12], [4,12], [9,10], 
[9,11], [10,10], [10,10], [11,8], [-4,12], [-2,12], [3,12], [6,12], [6,12], [11,10], [11,8], 
[12,4], [12,1], [3,12], [6,12], [10,10], [10,10], [11,7], [12,4], [12,3], [12,0], [12,-2], 
[12,-2], [12,-2], [12,-8], [10,-10], [8,-11], [7,-12]];

// Creation of the bricks
for (i=0; i<matrix.length; i++) {
  $(".bricks").append("<div class='brick displayNone'></div>");
}

Then we position the bricks, using the first brick as a reference.

// Positioning of the first brick
var currentY = 218;
var currentX = 361;

// Positioning of the rest of the bricks, using the matrix and the first brick as a reference.
for (i=0; i<matrix.length; i++) {
  currentY += matrix[i][0];
  currentX += matrix[i][1];
  var currentBrick = $(".brick")[i];
  $(currentBrick).css("top", currentY +"px");
  $(currentBrick).css("right", currentX +"px");
}

We now show the bricks one by one, with a little animation.

var x = 0;
$(".brick").each(function(index) {
  // here we calculate the timeout we'll add to each brick, so they show up one after 
  // the other, and we add a deceleration at the end to make it look better
  x += 20+(x/60);
  if(index > 80){
    x += (x/50);
  }

  var brick = $(this);
  setTimeout(function() {
    $(brick).removeClass("displayNone");
    $(brick).animate({
      top: '+=50'
    });
  }, x);
});

At the end, we illuminate the bricks using our illuminated class that uses the CSS3 animation.

setTimeout(function() {
  $(".brick").addClass("illuminated");
}, x + 500);

Then we hide all the bricks and fade in the final icon.

setTimeout(function() {
  $(".brick").fadeOut(300);
  setTimeout(function() { $(".bricks").hide(); }, 400); // this prevents some weird bugs
  $(".final_icon").fadeIn(1000);
}, x + 900);

To summarize, we’re using JavaScript to create and position the bricks using relative coordinates, and animating them using timeouts and the jQuery .animate() function, and then we use a CSS3 animation to light up the bricks before they disappear.

As an example, here’s a light version of the animation (no illumination of the bricks before showing the final icon).

Christophe Tauziet
November 9, 2012

Fresh New Look for our Blog

When it became clear that a blog redesign was necessary, we wanted to create the same great user experience we’ve tried to achieve with the rest of the Parse website. We care a lot about our blog so we put the same amount of energy in its redesign as we did for our new homepage or for our new product pages.

As of today, the new blog design is fresher, nicer, and simpler. We worked hard to make sure it will offer the best reading experience possible, and we really hope you’ll love it as much as we do.

Christophe Tauziet
September 14, 2012

The New App Dashboard

Parse lets you easily manage the backend for all your apps through a powerful dashboard. This is an important interface where developers spend a lot of time completing tasks like setting up classes, permissions, data, and push notifications.

Today we’re introducing a redesign of our dashboard that we hope will simplify your daily workflow. It’s friendlier and focuses on the important aspects of managing your application with less visual clutter. Also, switching between apps is now easier than ever.

As developers, we know it’s important for some folks to have a dark theme on a tool they’re using on a daily basis. So we’re also added the ability to switch between a light and a dark theme on your dashboard. Check out the little switch on the bottom left of the interface.

As always, we’re working hard to design the best possible tools to manage your apps, and your feedback is very important to us. If you have questions or suggestions, feel free to contact us.

Christophe Tauziet
June 18, 2012

A Redesigned App Management Console

The main idea behind Parse is to simplify developer’s lives by offering tools to make building apps easier and faster. We keep this goal in mind with everything we build.

Every day, we continue to add more features to our APIs. But making a successful platform isn’t always about adding new features. It can also be about improving the design of the workflows.

Today, we’re introducing a redesign of our application management console. We’ve dramatically improved and simplified the experience, while keeping all of the great features you love. Specifically, it’s now much easier to manage the various settings on your app.

But, this is just the first step. We’re already working hard on some of the next iterations. Stay tuned!

Christophe Tauziet
May 10, 2012