GDG UI Devfest, November 2014
+Ibrahim
Oluwadamilare
@IODamilare
#itshackademic@polyme
Agenda
Overview
Components
Join the revolution
Web Components: Overview
What problems are we solving?
@polyme #itshackademic
http://drbl.in/esYL
Building UI
tabs
should be
easy!
@polyme #itshackademic
@polyme #itshackademic
@polyme #itshackademic
@polyme #itshackademic
@polyme #itshackademic
<paper-tabs>
<paper-tab>KNOWLEDGE</paper-tab>
<paper-tab>HISTORY</paper-tab>
<paper-tab>FOOD</paper-tab>
</paper-tabs>
Less Code. Less confusion.
Web
Components
What are Web Components?
Custom Elements
define new HTML/DOM elements
<paper-tabs selected=“1”>
<paper-tab>Tab 1</paper-tab>
<paper-tab>Tab 2</paper-tab>
<paper-tab>Tab 3</paper-tab>
</paper-tabs>
declarative,
readable
meaningful
HTML
common way to extend →
reusable
Custom Elements
define new
HTML
@polyme #itshackademic
declarative,
readable
meaningful
HTML
common way to extend →
reusable
Custom Elements
define new
HTML
var tabs = document.querySelector('paper-tabs');
tabs.addEventListener('core-activate', function() {
console.log(this.selected);
});
@polyme #itshackademic
Templates
native client-side templating
<template>
<div class=“comment”>
<img src=“image.png”>
</div>
<script>...</script>
</template>
use DOM to scaffold DOM → no
XSS
content is inert until
cloned/used
doc fragment → not part of the
page
HTML Templates
native client-side templates
parsed, not rendered
@polyme #itshackademic
Shadow DOM
DOM/CSS scoping
<video src=“foo.webm” controls></video>
@polyme #itshackademic
<video src=“foo.webm” controls></video>
Actually Shadow DOM
@polyme #itshackademic
<video src=“foo.webm” controls></video>
HTML Imports
loading web components
@polyme #itshackademic
@polyme #itshackademic
Custom Elements
Create new HTML elements and extend existing ones
Templates
Native templating in the browser
Shadow DOM
Scoped CSS!!! + encapsulated markup
HTML Imports
Load custom element definitions and resources
@polyme #itshackademic
@polyme #itshackademic
@polyme #itshackademic
@polyme #itshackademic
Browser support
Summer 2014
Polyfills Web Components
with platform.js
Adds syntactic “sugar”
with polymer.js
Browser support
Summer 2014 (with Polymer)
Browser support
Summer 2014 (with Polymer)
Sugaring: Custom Elements
vanill
a
polym
er
<polymer-element name=“paper-tabs”>
…
</polymer-element>
usag
e
<paper-tabs>…</paper-tabs>
// document.createElement(‘paper-tabs’);
document.registerElement(‘paper-tabs’, {
prototype: Object.create(HTMLElement.prototype)
});
@polyme #itshackademic
document.registerElement(‘paper-tabs’, {
prototype: Object.create(HTMLElement.prototype)
});
vanill
a
polym
er
<polymer-element name=“paper-tabs”>
…
</polymer-element>
usag
e
<paper-tabs>…</paper-tabs>
// document.createElement(‘paper-tabs’);
@polyme #itshackademic
vanill
a
polym
er
<polymer-element name=“paper-tabs”>
…
</polymer-element>
usag
e
<paper-tabs>…</paper-tabs>
// document.createElement(‘paper-tabs’);
document.registerElement(‘paper-tabs’, {
prototype: Object.create(HTMLElement.prototype)
});
@polyme #itshackademic
vanill
a
polym
er
<polymer-element name=“paper-tabs”>
…
</polymer-element>
usag
e
<paper-tabs>…</paper-tabs>
// document.createElement(‘paper-tabs’);
document.registerElement(‘paper-tabs’, {
prototype: Object.create(HTMLElement.prototype)
});
@polyme #itshackademic
vanill
a
polym
er
<polymer-element name=“super-button” extends=“button”>
…
</polymer-element>
usag
e
<button is=“super-button”>…</button>
// document.createElement(‘button’, ‘super-button’);
document.registerElement(‘super-button’, {
prototype: Object.create(HTMLButtonElement.prototype),
extends: ‘button’
});
@polyme #itshackademic
vanill
a
polym
er
<polymer-element name=“super-button” extends=“button”>
…
</polymer-element>
usag
e
<button is=“super-button”>…</button>
// document.createElement(‘button’, ‘super-button’);
document.registerElement(‘super-button’, {
prototype: Object.create(HTMLButtonElement.prototype),
extends: ‘button’
});
@polyme #itshackademic
vanill
a
polym
er
<polymer-element name=“super-button” extends=“button”>
…
</polymer-element>
usag
e
<button is=“super-button”>…</button>
// document.createElement(‘button’, ‘super-button’);
document.registerElement(‘super-button’, {
prototype: Object.create(HTMLButtonElement.prototype),
extends: ‘button’
});
@polyme #itshackademic
vanill
a
polym
er
<polymer-element name=“super-button” extends=“button”>
…
</polymer-element>
usag
e
<button is=“super-button”>…</button>
// document.createElement(‘button’, ‘super-button’);
document.registerElement(‘super-button’, {
prototype: Object.create(HTMLButtonElement.prototype),
extends: ‘button’
});
@polyme #itshackademic
Sugaring: Templates
vanill
a
polym
er
<polymer-element name=“user-list” noscript>
<template>
<ul>
<template repeat=“{{user, i in users}}”>
<li>{{user.name}}</li>
</template>
</ul>
</template>
</polymer-element>
<template>
…
</template>
@polyme #itshackademic
vanill
a
polym
er
<polymer-element name=“user-list” noscript>
<template>
<ul>
<template repeat=“{{user, i in users}}”>
<li>{{user.name}}</li>
</template>
</ul>
</template>
</polymer-element>
<template>
…
</template>
@polyme #itshackademic
vanill
a
polym
er
<polymer-element name=“user-list” noscript>
<template>
<ul>
<template repeat=“{{user, i in users}}”>
<li>{{user.name}}</li>
</template>
</ul>
</template>
</polymer-element>
<template>
…
</template>
@polyme #itshackademic
Sugaring: Shadow DOM
var shadow = el.createShadowRoot();
shadow.innerHTML = “<style>h2 { color: red; }</style>” +
“<h2>I’m a profile-card</h2>”;
vanill
a
<polymer-element name=“profile-card” noscript>
<template>
<link rel=“stylesheet” href=“styles.css”>
<h2>I’m a profile-card</h2>
</template>
</polymer-element>
polym
er
@polyme #itshackademic
var shadow = el.createShadowRoot();
shadow.innerHTML = “<style>h2 { color: red; }</style>” +
“<h2>I’m a profile-card</h2>”;
vanill
a
<polymer-element name=“profile-card” noscript>
<template>
<link rel=“stylesheet” href=“styles.css”>
<h2>I’m a profile-card</h2>
</template>
</polymer-element>
polym
er
@polyme #itshackademic
var shadow = el.createShadowRoot();
shadow.innerHTML = “<style>h2 { color: red; }</style>” +
“<h2>I’m a profile-card</h2>”;
vanill
a
<polymer-element name=“profile-card” noscript>
<template>
<link rel=“stylesheet” href=“styles.css”>
<h2>I’m a profile-card</h2>
</template>
</polymer-element>
polym
er
@polyme #itshackademic
Components
<ul
><p
>
<h1>
<menu-button>
<page-scaffold>
<animated-pages>
What if we designed HTML
for the mobile web?
<core-icon>
<paper-fab>
<core-drawer-panel>
<core-field>
http://bit.ly/1jkTo5c
core-
elements
Image: http://bit.ly/1mZjnTu
<core-
toolbar>
A basic container for controls
like tabs or buttons
MY
APP
@polyme #itshackademic
<link rel=“import”
href=“core-toolbar.html”>
<core-
toolbar>
A basic container for controls
like tabs or buttons
MY
APP
@polyme #itshackademic
<core-toolbar>
<div>MY APP</div>
</core-toolbar>
<link rel=“import”
href=“core-toolbar.html”>
<core-
toolbar>
A basic container for controls
like tabs or buttons
MY
APP
@polyme #itshackademic
<core-toolbar>
<core-icon-button icon=“menu”>
</core-icon-button>
<div>MY APP</div>
</core-toolbar>
<link rel=“import”
href=“core-toolbar.html”>
<core-
toolbar>
A basic container for controls
like tabs or buttons
MY
APP
@polyme #itshackademic
A simple container with a header
section and a content section
<core-header-
panel>
MY APP
<core-header-panel flex>
<core-toolbar>
<core-icon-button icon=“menu">
</core-icon-button>
<div>MY APP</div>
</core-toolbar>
<div class=“content”>…</div>
</core-header-panel>
A simple container with a header
section and a content section
<core-header-
panel>
MY APP
<core-header-panel flex>
<core-toolbar>
<core-icon-button icon=“menu">
</core-icon-button>
<div>MY APP</div>
</core-toolbar>
<div class=“content”>…</div>
</core-header-panel>
A simple container with a header
section and a content section
<core-header-
panel>
MY APP
<core-header-panel flex>
<core-toolbar>
<core-icon-button icon=“menu">
</core-icon-button>
<div>MY APP</div>
</core-toolbar>
<div class=“content”>…</div>
</core-header-panel>
A simple container with a header
section and a content section
<core-header-
panel>
<core-header-panel flex>
<core-toolbar>
<core-icon-button icon=“menu">
</core-icon-button>
<div>MY APP</div>
</core-toolbar>
<div class=“content”>…</div>
</core-header-panel>
MY APP
<core-header-panel mode=“scroll" flex>
<core-toolbar>
<core-icon-button icon=“menu">
</core-icon-button>
<div>MY APP</div>
</core-toolbar>
<div class=“content”>…</div>
</core-header-panel>
<core-header-
panel>
Toolbar will scroll with the page
A responsive container that
combines a left- or right-side drawer
panel and a main content area.
<core-drawer-
panel>
<core-drawer-panel>
<div drawer> Drawer panel... </div>
<div main> Main panel... </div>
</core-drawer-panel>
<core-drawer-panel>
<div drawer> Drawer panel... </div>
<div main> Main panel... </div>
</core-drawer-panel>
A responsive container that
combines a left- or right-side drawer
panel and a main content area.
<core-drawer-
panel>
<core-drawer-panel>
<div drawer> Drawer panel... </div>
<div main> Main panel... </div>
</core-drawer-panel>
A responsive container that
combines a left- or right-side drawer
panel and a main content area.
<core-drawer-
panel>
paper-
elements
<paper-input floatinglabel
label="Type only numbers... (floating)"
validate="^[0-9]*$"
error="Input is not a number!">
</paper-input>
@polyme #itshackademic
<paper-checkbox></paper-
checkbox>
<div class=“card”>
<img src=“science.svg”>
<paper-ripple fit></paper-ripple>
</div>
A reactive ink effect for indicating touch
and mouse actions
<paper-
ripple>
<div class=“card”>
<paper-shadow z=“5” animated>
</paper-shadow>
</div>
A dynamic shadow for conveying
z-depth and spatial relationships
<paper-
shadow>
@polyme #itshackademic
Styling
<paper-slider min=“0” max=“100”>
</paper-slider>
allows you to style nodes
internal to an element’s
shadow dom
::shado
w
@polyme #itshackademic
allows you to style nodes
internal to an element’s
shadow dom
::shado
w
paper-slider::shadow #sliderKnobInner {
background-color: #f4b400;
}
<paper-slider min=“0” max=“100”>
</paper-slider>
@polyme #itshackademic
html /deep/ paper-ripple {
background-color: #E91E63;
}
styles will pierce all
shadow boundaries
/deep/
@polyme #itshackademic
With ::shadow and /deep/
you
can apply sitewide themes
source: ebidel.github.io/material-playground
polymer-
project.org/apps/topeka/
polymer-
project.org
We’re not
alone
Mozilla Brick
<brick-appbar>
<brick-deck>
<brick-tabbar>
<core-icon>
<x-instagram>
(not shown)
Web Components
can work together
Not just browser makers
<app-router>
github.com/erikringsmuth/app-router
my-site.com/order/:id
<app-router>
<!-- matches an exact path -->
<app-route path="/home" import="/pages/home-page.html"></app-route>
<!-- matches using a path variable -->
<app-route path="/order/:id" import=“/pages/order-page.html"></app-route>
</app-router>
<page-er>
github.com/addyosmani/page-er
<page-er perpage="5" previous=“<< Previous" next=“Next >>"></page-er>
var pager = document.querySelector("page-er");
document.addEventListener("polymer-ready", function() {
pager.data = model.items;
});
<ajax-
form>github.com/garstasio/ajax-form
Full Name
Country City
Join newsletter
<form is="ajax-form" action="my/form/handler">
<label>Full Name
<input type="text" name=“full_name">
</label>
…
</form>
√
Apps
polymer-project.org
chromestatus.com
polymer-
project.org/tools/designer/
github.com/ForceDotComLabs/mobile-ui-elements
github.com/ForceDotComLabs
APIs
APIs (as elements)
I want to add a marker
to a Google map.
@polyme #itshackademic
height: 400px;
}
</style>
<div id="map"></div>
<script src=“http://maps.googleapis.com/maps/api/js?callback=mapReady">
</script>
<script>
var marker = null;
function getCurrentLocation(callback) {
navigator.geolocation.watchPosition(callback);
}
function addMarker(opts, info) {
var marker = new google.maps.Marker(opts);
var infoWindow = new google.maps.InfoWindow({content: info});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.open(opts.map, marker);
});
return marker;
}
function mapReady() {
var container = document.querySelector('#map');
var map = new google.maps.Map(container, {
zoom: 14, disableDefaultUI: true
});
getCurrentLocation(function(pos) {
var current = new google.maps.LatLng(pos.coords.latitude,
pos.coords.longitude);
map.setCenter(current);
// Re-position marker or create new one.
if (marker) {
marker.setPosition(map.getCenter());
} else {
marker = addMarker({
position: current, map: map, title: 'Your location'
}, '<b>Your location</b>');
}
});
So much code
for one map
marker!
@polyme #itshackademic
@polyme #itshackademic
googlewebcomponents.github.io
github.com/GoogleWebComponents
youtube.com/watch?v=eORqFaf_QzM
Join the revolution
Learn
polymer-project.org
Build
Start with <seed-
element>github.com/PolymerLabs/seed-
element
youtube.com/watch?v=2toYLLcoY
14
http://goo.gl/UjLvb
2
Chrome Dev
Editor
Share!
customelements.i
o
{
"name": "my-element",
"version": "0.0.0",
"description": "My awesome Custom Element",
"license": "MIT",
"keywords": [
"web-components"
],
"ignore": [
"**/.*",
"node_modules",
"bower_components"
]
bower.json
@polyme #itshackademic
EXPLO
RE
<thank-you>
+Ibrahim
Oluwadamilare
@IODamilare

Polytechnic speaker deck oluwadamilare