about:me
+Eric Bidelman
@ebidel
On deck...
State of the union
Problems solved by web components
"Thinking in components"
Once upon a time...
What about us regular developers?
2010
Start of a very looonnng journey
lists.w3.org/Archives/Public/public-webapps/2010OctDec/0951.html
Google I/O 2013
webcomponentsshift.com
W3C standards
Templates
Custom Elements
Shadow DOM
HTML Imports
W3C standards
Templates
Custom Elements
Shadow DOM
HTML Imports
36
FF is implementing everything
Safari removed Shadow DOM :(
but they're adding it back! :)
lists.webkit.org/pipermail/webkit-dev/2014-February/026251.html
?
Hope!
People built stuff.
polymer-project.org
chromestatus.com
Chrome Feature Dashboard
chromestatus.com
WinJS + Polymer experiments!
Github.com
Bower Metrics Dashboard
polymerlabs.github.io/bower-metrics-dashboard
Chrome OS Keyboard
Chrome OS Media Player
What problems do web components solve?
Before
Components
Existed
Problems
Solved
custom elements
define new HTML/DOM elements
HTML didn't keep up
Let's create a tab strip!
No common structure / pattern
APIs are all different
Overloading HTML
Custom elements
define new HTML
declarative, readable
meaningful HTML
common way to extend → reusable
vanilla
polymer
usage
Is this really better than before?
YES!
DOM → integrated
Mutation Observers, querySelector
addEventListener, parsing/caching pipelines
interoperability every framework is compatible with DOM
accessibility keyboard, focus, ARIA
devtools support 1st-class integration
html templates
native client-side templating
Templating
Hacky
pushing around strings
XSS vulnerable
<script type="text/x-handlebars-template"> <div class="entry"> <h1>{{title}}</h1> <div>{{body}}</div> </div> </script>
var MyView = Backbone.View.extend({ el: 'div', className: 'entry', template: '<div>...</div>', render: function() { ... } });
HTML Templates
native client-side templates
use DOM to scaffold DOM → no XSS
parsed, not rendered
content is inert until cloned/used
doc fragment → not part of the page
<template> <div class="comment"> <img src="image.png"> </div> <script>...</script> </template>
vanilla
<template> ... </template>
polymer
<polymer-element name="user-list" noscript> <template> <ul> <template repeat="{{user,i in users}}"> <li>{{user.name}}</li> </template> </ul> </template> </polymer-element>
shadow dom
DOM/CSS "scoping"
Composibility. Scoping.
Data / services Input / selection App utilities Views App layout
vanilla
polymer
Shadow DOM example
scoping & composibility
Usage:
html imports
loading web components
Example: Bootstrap
Find
Import
Use
Find
$ bower install Polymer/core-toolbar
$ bower install Polymer/core-icon-button
Import
<head>
<link rel="import" href="core-toolbar.html">
<link rel="import" href="core-icon-button.html">
</head>
Use
<core-toolbar>
<core-icon-button icon="menu"></core-icon-button>
<span flex>Toolbar</span>
<core-icon-button icon="refresh"></core-icon-button>
<core-icon-button icon="add"></core-icon-button>
</core-toolbar>
HTML Imports
<head>
<!-- 1. import -->
<link rel="import" href="profile-card.html">
</head>
<body>
<!-- 2. use -->
<profile-card></profile-card>
</body>
vanilla
&
polymer
<link rel="import" href="polymer.html">
<link rel="import" href="paper-tabs.html">
<link rel="import" href="paper-tab.html">
<polymer-element name="menu-bar" noscript>
<template>
<paper-tabs selected="0" noink nobar>
<paper-tab>ONE</paper-tab>
...
</paper-tabs>
</template>
</polymer-element>
use
<link rel="import" href="menu-bar.html">
"Thinking in components"
How we use HTML
Types of HTML elements
Visual elements - render UI to the screen
Non-visual elements - provide utility
<head>
<title>
<meta>
<link>
<style>
<script>
<template>
<datalist>
<source>
Polymer's core elements
Non-visual core elements
<core-localstorage>
<core-ajax>
<core-shared-lib>
<core-media-query>
<core-collapse>
<core-selector>
<core-input>
, <core-range>
Visual core elements
<core-icon>
, <core-tooltip>
<core-overlay>
<core-list>
, <core-drawer-panel>
<core-scaffold>
<core-scroll-header-panel>
<core-toolbar>
, <core-menu>
Polymer's material design elements
highly visual & interactive
How we interact with APIs / libs / services
Google Maps API
Render a map. Add marker at user's current location.
<style>
#map {
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>');
}
});
}
</script>
Polymer version
Render a map. Add marker at user's current location.
<geo-location latitude="{{lat}}" longitude="{{lng}}"></geo-location>
<google-map latitude="{{lat}}" longitude="{{lng}}" zoom="{{zoom}}">
<google-map-marker latitude="{{lat}}" longitude="{{lng}}"></google-map-marker>
</google-map>
<paper-slider min="0" max="21" value="{{zoom}}" pin></paper-slider>
250+ APIs
googlewebcomponents.github.io
How single page apps are built
Signal page app
Re-think: What it means to be responsive
Creating responsive elements
using core-media-query inside of Polymer
<polymer-element name="responsive-toolbar" noscript>
<template>
<core-media-query query="max-width:480px"
queryMatches="{{isPhone}}"></core-media-query>
<template if="{{isPhone}}"> <!-- phone markup -->
<content></content>
</template>
<template if="{{!isPhone}}"> ...</template>
</template>
</polymer-element>
<responsive-toolbar>
<a href="">...</a>
</responsive-toolbar>
Styling components
1. Element styles itself
2. User styles the element / overrides
3. Theming
Element styles itself
:host selects the Shadow DOM host
:host {
display: inline-block;
text-transform: uppercase;
cursor: pointer;
}
:host(.hover:hover) {
background: gray;
}
:host([raisedButton]) {
background: gray;
}
<paper-button label="Default" class="hover">
<paper-button label="Raised" raisedButton>
Element styles itself ( based on its surrounds )
:host-context matches any ancestor
:host-context(paper-tabs) {
background: purple;
color: white;
}
:host-context(.epic-theme) {
background: purple;
color: white;
}
<paper-tabs>
<paper-tab>Tab</paper-tab>
</paper-tabs>
<body class="epic-theme">
<paper-button label="Purple"></paper-button>
</body>
User styles / overrides
::shadow and /deep/ penetrate Shadow DOM
paper-button {
background: blue;
color: white;
fill: currentcolor; /* icon */
}
paper-button:hover {
background: pink;
}
paper-button::shadow #ripple {
color: black; /* ripple */
}
Theming
paper-button /deep/ #icon {
fill: #fff;
}
<body class="mytheme">
<theme-able></theme-able>
</body>
<paper-button label="Original" raisedButton></paper-button>
Do we need web components?
YES!
Web components bring much to the table
Productivity
rapid development, high productivity
Declarative
meaningful, intuitive, powerful markup
Composibility
apps from building blocks
Maintainability
read an app, understand it
Reusability
sharable: don't start from scratch)
Extensibility
common way to extend native / custom elements
"Scoping"
per-element CSS / DOM / APIs
Interoperability
integrated at the lowest level (DOM)
Accessibility
on by default
Web components bring much to the table
Custom Elements is a bedrock API. We should be able to build all HTML elements with it.
<select-element>
What if...
the entire web platform was hosted on Github?
Let's componentize the web!
Create building blocks for the web!!!
don't get left behind
<thank-you>