Note: These are the notes on my talk about Mozilla Brick at Over The Air 2013. Sadly it wasn’t recorded, and I got kind of nervous and forgot to press the “REC” button in Quicktime, so I didn’t “screencast” it either. You can also check the original slides for maximum impact.
Mozilla Brick
UI components for modern web apps
Hello everyone!
I’m going to tell you all about Brick which is a set of UI components / library developed at Mozilla to make it easier to develop web apps.
So everyone is talking about components, and Web Components and stuff, but…
Hold on
What is a “component”?
I think it’s important we define what is a “component” beforehand.
“a constituent part; element; ingredient.”
That’s what the dictionary says. But sometimes it’s better to look at examples. So that could be…
Screws
(picture by apeofjungle)
Resistors
(picture by oskay)
Doorbell
(picture by neosnaps)
Or maybe even a doorbell!
What is common to all these things is they are like black boxes. You just use them. You could, of course, open them to see what is inside, but you generally don’t do it, unless you’re very curious (like me).
And a web component?
So how does it relate to web components?
It’s the same
It’s the same. Web components are things you use without having to know how they work in the inside.
Buttons
For example, buttons.
Range
Or the input type=range. It looks a bit silly that huge, doesn’t it?
Web-bell
Or even the web-bell! A web-bell?
That’s just a component I created! If you press it, it plays a doorbell sample.
I’ll come back to that later.
(See slides for running the web-bell)
So, web components
They are like any other HTML element but also have got…
Custom behaviour
Custom appearance
The key is custom
They will allow us to build components before they are standard, or anyone comes up with the conclusion that a new component is required.
Although the spec calls them widgets
But I don’t quite like the “widgets” word. Anyway! I know some people might be wondering…
Why Web Components?
Can’t we just use divs?
<div class="widget calendar ui theme-winter">
<div class="component-wrapper">
<div class="inner-content">
(ad nauseaum)
</div>
</div>
</div>
Why Web Components?
Or maybe some jQuery UI plugin
$( "#datepicker" ).datepicker( $.datepicker.regional[ "fr" ] );
$( "#locale" ).change(function() {
$( "#datepicker" ).datepicker( "option",
$.datepicker.regional[ $( this ).val() ] );
});
I promise I’m not making this up. This is copied and pasted from one of the examples in their website. How many times is ‘datepicker’ used in this example?
Amazing.
So yeah, basically my answer is…
No
Because…
With web components…
Encapsulation
Reusability
Robustness
Expressiveness
you get all these benefits!
Ingredients for successful Web Components
But every great recipe requires some basic ingredients. In the case of Web Components, a nicely working implementation would require the following:
document.register
HTMLTemplateElement
Shadow DOM
… where document.register is used for telling to the browser that we want to use a new, custom component with a certain name (i.e. registering this component with your browser before using it, so it knows what you mean when you call document.createElement).
HTMLTemplateElement, or simply, <template> is used to create templates for your elements that can be instantiated later.
And Shadow DOM is, as some people call it, “like a Tardis“, in that it is bigger in the inside than it looks from outside. It can contain a bunch of nodes and stuff, but the outside world just sees a “#shadow-dom” node, so it effectively encapsulates components.
But unfortunately the Shadow DOM is still not implemented in Firefox (bug 712622 is tracking it), which is why it’s highlighted in red.
So… not ready yet?
Is everything lost? Are we doomed to keep using divs? Or can we do anything about it?
X-Tag to the rescue
Thankfully there is a solution! X-Tag!
Because…
X-Tag Shims all the things!!!11
(where appropriate)
X-Tag is a library which makes it possible to start writing custom web components today, even if some features are not available in every browser. It will shim if required, or use the native features if there are present.
For example, since the <template> is already implemented in Firefox, it would use the native object instead of shimming it.
It also offers a unified interface across browsers–the same code you write is valid for all of them. And that’s what Brick uses!
How does mark-up with Brick look like?
I presume you might totally be looking forward to see how code using Brick looks like. So there we go. This would be a minimal app:
<x-layout>
<x-appbar>
<header>
Spiffy header!
</header>
</x-appbar>
Marvelous content!
<footer>
Magnificent footer!
</footer>
</x-layout>
As you can see we’re mixing standard HTML5 elements (like header, footer) with our custom x-layout and x-appbar components. This works because web components are not special–once they have been registered, they act as any other DOM element. They can be created, appended to or removed from the DOM tree, etc.
But I bet there’s something that might be itching you at this point…
Why the hyphen?
Why are we using that hyphen in each one of our new, custom components?
The spec says
The custom element type identifies a custom element interface and is a sequence of alphanumeric ASCII characters that must match the NCName production and contain a U+002D HYPHEN-MINUS character
(source)
Or in other words: the name of a custom element must contain a hyphen.
So we took the X from X-Tag
And added a hyphen.
As simple as that.
I think somebody asked at this point whether there was any sort of namespacing “authority”. There is none! So use your best judgment. Probably if a certain set of components becomes popular, they will “own” that namespace.
The imperative way
Creating bricks out of nowhere
But back to the components, up until this point we’ve been using them in a declarative way–defining them in our HTML code. Can we create them imperatively, i.e. from JavaScript?
Well, of course you can (and I think I might have mentioned that already)
It’s magic!
For example, for creating an instance of the calendar component that comes with Brick, you would just do the following:
var cal = document.createElement('x-calendar');
document.querySelector('section').appendChild(cal);
The Brick line up
These are the components that you get when you download Brick nowadays:
appbar
calendar
datepicker
deck
flipbox
iconbutton
layout
slidebox
slider
tabbar
toggle
togglegroup
tooltip
Some of them are quite explanative whereas others are more “abstract” and layout oriented–i.e you don’t quite see them but they serve to divide the screen space in parts, align things, etc.
Get all the Bricks
So how do you get started with Brick in your project?
Download the built files (brick.css & brick.js)
Include the css file in your <head>:
<link rel="stylesheet" type="text/css" href="css/brick.css" />
Include the js file at the end of your <body>:
<script src="js/brick.js"></script>
Instead of window.onload, listen for DOMElementsLoaded
Customising
Your bricks, the way you like them!
See, one finds quite weird things in the Internet. Apparently some people break bricks with their head? Well, if that’s what they like… So yeah, there are two things you can do with regards to customising Brick…
Customising the appearance
The first thing you can do is changing the way they look. Also known as…
Give them a new layer of paint with CSS
This is how you do it:
Include the
brick.css
file first
Include your css file afterwards
Since there’s nothing special about the CSS that Brick uses, we can just rely on the way CSS works.
Here’s an example where we modify the default appearance of the x-appbar element:
x-appbar {
background-image: linear-gradient(-180deg, #f0f 0%,
#f00 30%, #ff0 50%, #0f0 75%, #00f 100%);
color: #fff;
text-shadow: 1px 1px 1px #000;
padding: 1rem;
font-size: 2rem;
}
The default grey background was a little bit too neutral, so I made it rainbow-y. It’s a bit dangerous once you start playing with CSS gradients. You never know when to stop.
Customising the bundle
You can also customise the built files (brick.js and brick.css). This is specially useful if you just want to use a couple of components and want to reduce the size of your code.
Online
Offline, command line with Grunt – we’re on it
The online version will let you build your own Brick bundle once you tick a few checkboxes with the components you’re interested in.
Or when you know what you’re doing: no bundling
But you could go even further and use the “raw” components, without any type of bundling. This is what I do when I’m developing, because sometimes I need to modify the components themselves, or set breakpoints or any of those things we do when developing!
Although it’s not recommended to do it in “production” websites as it’s not exactly optimal.
clone the brick repo and run make – this will run some commands that will result in a bunch of folders in the brick/dist directory (one per component)
include dist/core/core.min.js
include the components you need, e.g. dist/calendar/calendar.min.js
And now, the moment you all have been waiting for:
Bake your own bricks
Three simple steps
These are the bare minimum steps you need to follow to get a brick of your own:
Include
dist/core/core.min.js
Write and include
your-brick.js
Write and include
your-brick.css
(optional)
What’s in your-brick.js?
The first thing you need to do is registering your new custom element with the browser. We do this using the X-tag’s register method:
(function() {
xtag.register('your-brick', {
lifecycle: {
created: function() {
this.innerHTML = 'I am a brick';
}
}
});
})();
The method accepts an object that defines how a component behaves. The minimum thing we have to do for it to be useful is at least do something when a new instance of the component is created. So we’ll act upon the ‘created’ lifecycle stage by setting our innerHTML to “I am a brick”.
In this context, this is the component instance, as you might have already deducted.
Adding events
Of course, we can also listen to events! Say we want to listen to ‘tap’ events (this will work for touch and screen devices):
(function() {
xtag.register('your-brick', {
// ... here goes the lifetime code of before
events: {
'tap': function(e) {
this.style.backgroundColor =
'#' + Math.round(0xFFFFFF * Math.random())
.toString(16);
}
}
});
})();
Whenever this component gets clicked, it will change its background colour to a randomly chosen one. See it in action.
Now you could open the web console in the example window, and type this:
for(var i = 0; i < 5; i++) {
var brick = document.createElement('your-brick');
document.body.appendChild(brick);
}
and that would end up adding five more bricks to the page. Each one is wholly independent from the rest, so you can click on each one and have it change its background, but not affect the others.
Something more advanced
So this is all fine and OK but perhaps not very exciting–could we build a complete app with Brick?
Pocket cutesy
So Ruth John –is Ruth in the room?– ah, here she is! So she made an app called Pocket Kitten which provides you with pictures of cats. And I quite liked the app, and thought I could maybe redo it but using Brick. Also it’s very convenient because it’s her birthday today! So let’s think of this as her present!
A new feature (apart from being built with Brick) would be that we will be showing animated gifs instead of static pictures. Also, since I wasn’t sure whether we’d have Internet at this event, I’ve already downloaded all the gifs, so we get faster cutesy. This also means I’ve got to do a lot of search… or research.
Anyway, here’s the app.
Interesting points to note:
The install button is hidden by default (with display: none), and shown only if a) the app is loaded in a runtime that supports installing, and b) the app hasn’t been installed yet. This prevents you from showing an install button in cases in which it doesn’t make any sense because there’s no support for installing the app. For example, in Safari.
The tooltip, which is another Brick component, is removed when you tap the screen once. Since it’s just a DOM element, we can safely remove it from the DOM and forget about it. Compare that with other UI libraries that require you to remove the listeners and the behaviours, and etc, before you can get rid of an element in the page.
We’re still in beta
The current version is Brick 1.0 ß7*
So, expect bumps. For example, I would love to show you this app working on the simulator, but there’s something breaking it, so I can’t show you that. There’s a bug already filed, so they know about that. It’s important to file bugs! Always file bugs.
*Actually it was ß7 at the time of the talk, but it is ß8 now because a new version addressing the simulator breaking bug was released!
But bumps are good, because they highlight problems we didn’t notice, and we try to fix them quickly. For example, the first day that it got to Hacker News’ front page, we started getting reports about the calendar demo crashing browsers (specially Chrome).
It was a slightly hard to reproduce bug because it only happened when the computer’s locale wasn’t US–which is what the main developers were using! Since the calendar was expecting a US date format, and the rest of the world use a different (sensible) one, the component would enter in an infinite loop and crash the browser. UUUGH.
But thankfully Leon –the very talented intern that worked on this project this summer– and Potch –his also very talented mentor– quickly noticed the pattern in the bug reports, and fixed it. Brilliant!
Brick roadmap
So what is in the future?
Q1 2014
Brick 1.0
Mortar beta
Brick 1.0 would include the following features:
✓skinnability
accessibility
new components
✓modularity
30+FPS in Firefox OS
✓Automated Testing
beautiful by default
Features with a checkmark mean they are already done.
Mortar is a series of templates that demonstrate how to build web apps, using a series of approaches. We have a basic stub, and are working on adding more, be it using Brick, or Brick with more frameworks such as Angular.
H1 2014
More components
Gaia skin (Firefox OS theme)
AppMaker integration – AppMaker is another Mozilla project to make building apps accessible to non-programmers
Brick 2.0
H2 2014
The second half of 2014 looks really exciting:
Flying cars
Ponies
Potch (project lead) in Fortune magazine
IPO
However…
Unicorns and rainbows are not in the roadmap
:-(
So I brought a few!!!
Thanks and… ask me questions!
@supersole
Slides and code
Interesting questions people asked
I don’t have the answer for all of them, but they’re here for reference–and of course, if you have the answer, please do leave a comment, or write to me, or anything! Let me know!
Q: Is it possible to dispatch/listen to custom events? Apart from the ones x-tag already defines that are definitely not standard (‘tap’ for example)
E.g. instead of listening for ‘tap’ events, you could listen for ‘ring’ events.
Answer by Arron Schaar (from X-tag fame): If ‘ring’ events are DOM events and are dispatched on the document then you can listen for them.
Q: Is it possible to mix Brick with Angular or other frameworks? How do you mix both types of views/widgets?
My answer during the talk: yes, and we’re working on releasing examples (mortar).
Arron’s more detailed answer, with link to an example: Mixing Angular and custom elements is actually very easy, especially if the custom element is controllable via attributes.
Check out this example where he’s using Angular data binding to populate a sparkline element:
<x-sparkline points="{{symbol.ticks}}">
Q: how are things added to the x-tag registry? How do you get tags into it?
I wasn’t too sure during the talk, but I asked Aaron and this is what he has to say: “If you click on the gear icon, there is a text box and an “Add” button that lets you add a component. There is also another registry at customelements.io. Bower is another option that allows developers to share components. All of our components are registered there–try
bower search x-tag
to search for registered components”
Q: How do you make a bundle that includes js+css+external resources such as fonts, images, audio…?
A: Currently we have to ensure they’re copied to wherever we use Brick but apart from base64-ing the hell out of the thing, I can’t really think of a better way to include everything in just a couple of files. Maybe we could think of another deploy/build step? Or maybe this is something that needs to be addressed in HTML/browser land? Let’s think about this if we have some spare moments/the will to do so!
Q: how close to Web Components is X-Tag? i.e. how much of an advantage X-tag has compared to just using raw web components support in the browser
X-Tag is “syntactic sugar” to make things a bit more consistent and kind of “defend you” against API changes. Specially since the spec is in flux and changes relatively often.
Update: pretty much as I was giving this talk, a post on Brick was published at the Mozilla Hacks blog. You should read it and watch the video if you’re interested in learning more about Brick + Firefox OS, and also because Christian Heilmann and Potch are both awesome!
You might also be interested in reading this article introducing Brick by Leon Zhang.