 Thanks for sticking around, everybody. We're going to talk about how to use web components to build progressive web applications and the notion of progressively enhancing your markup using custom elements. So this is me. It's at eBitle on Twitter and GitHub. I got crazy sometimes. I'm a digital Jedi at Google, which basically just means I'm a web developer that helps other web developers outside of Google build really awesome web apps. And I built a number of web apps at my time at Google. So we've worked on things like developer sites for HTML5 Rocks. We built developers.chrome.com, Polymer's website, chromestatus.com, SantaTrikers on a developer site, obviously, but it's kind of a fun project that we work on on developer relations. So you can track Santa around the globe, see where he delivers presents. We built the Codelab site that you see here today at the show in Polymer. And we've also worked on the Google I.O. Progressive Web app the last couple of years. Speaking of the last couple of years, I've gotten really excited about web components. All these emerging standards, several new APIs allow us web developers to build applications. Code reuse, reusability, these are really good things for the web. And it's important to know it's a set of emerging standards. So it's not just one API, it's a few. And you can use them each individually, that's totally cool, but together it becomes a web component and it becomes very powerful. So they allow us to extend and create new HTML elements. That's the core. That's the principle here. And over the last four or five years since the standards kind of first started to evolve, we've grown the community quite a bit. So there's webcomponents.org, which you can check out. It's got articles. It's got people there contributing. That's also where the polyfills are hosted. If you want to actually write an app in production, you can do that using the polyfills. So check that out. It's a great resource. But browser support's actually been lacking. So I think Chrome 36 was the first browser to land all of the web component APIs. So you can create a component without the use of a library. That's really awesome. But browser support's been lacking. So if you take away nothing today from this presentation, take away this slide. Basically, what's happened is that Chrome implemented the APIs very early on, so Shadow DOM, Custom Elements, Template, and HTML imports. This is what the API calls looked like. These are called now the v0 APIs. What's happened is that the browsers recently got together and said, hey, we want to tweak a little things here and there about each of these specs. And they decided and came to consensus. And what's going to happen now is there's a new version of Shadow DOM and Custom Elements. We call these the v1 APIs. So if you've learned about web components in the past, all the concepts still apply. Same stuff still applies. It's basically just syntax and name changes. In this presentation, I'm not going to talk about template, which is actually supported in all the modern browsers now, which is great. You can use that without a polyfill. And I'm not going to talk about HTML imports. I'm just going to focus on the two that have changed. And implementation in the browser is well underway. So Chrome has started in on Custom Elements and Shadow DOM. You can play with these today in Canary with a flag. Over at Firefox, Wilson Page, who's an advocate there, tweeted this recently. So they're actually started in on Shadow DOM v1. Custom Elements has an open bug. They haven't started that yet. Safari last week, in fact, at WWDC, announced Safari 10 will ship with Shadow DOM. So that's two browsers this year alone. We'll have Shadow DOM. And they've also started in on the new Custom Elements API. We thought that might land in Safari 10, but they just didn't get in on time. And over at Microsoft, Edge is playing a crazy catch of implementing all these things. Service worker push notifications. You see Shadow DOM and Custom Elements and web payments on there. So very exciting times for web developers. This stuff is coming in hot. Love it. Browser support really matters. Turns out native support really matters. We don't want to use polyfills for the rest of our lives, right? We don't want to drop in a needless library that we don't have to. And the notion that polyfills goes away over time is the promise of a polyfill. The other reason browser support really matters to me is because if you look today at all these libraries and frameworks, they all produce and allow developers to create components. But there's no standard way to build the component. Some use a lot of JavaScript. Some use more HTML and JavaScript. Some just use a massive amount of HTML. So the goal of creating a tab strip is the same, right? You want to create a reusable tab strip. But the way you get there is very different across the board. And so that's what web components is here for. It's here to have a standard way to create reusable components. So a web component tab strip would look something like this. It would be declarative. It would be my-tabs. We'll just call it that. It's got a selected attribute that you can use to select the tab that should be selected. And it's got div for its content. It's got HTML attributes. It's very readable and very clear what's going on here. The other thing that people often forget about is the fact that it's just DOM and HTML that we're creating means we're integrated with the browser. We're integrated into the platform. So Rob mentioned all these great accessibility features that the browser and the HTML elements already give you. We're integrated with that. We can take advantage of what's already there and don't have to reinvent the wheel ourselves. And we're also integrated with every web developer's best friend, which is the DevTools. And I'll show you an example of this. This is Polymer's old site. And I'll just fire up the DevTools and show you what happens and how you can kind of debug a web component. So this is a tab, a selecting tab strip that we have for our code that you can kind of poke around, see the code. And then you see the live output on the right there. So I'm just going to open the DevTools, open the inspector. And immediately, it's just DOM and HTML. So I can just poke around with the inspector, see what's going on, and see how this custom element is built. You see that there's a shadow DOM attached to some of these elements. I can open up the console, and I can start tweaking properties, DOM properties of this element. So I can change its selected property. And you can see a live update in the DOM. Since we're integrated with the platform in all ways, we can actually change CSS and affect how this component looks just by changing the color of the text of one of its panels. I can discover it's got a panel's property, and it's got an API. It's got methods, so things like updated panels. We can call that, and it does something. Who knows what it does? But we're discovering that in the DevTools. And it's got a bottom property. This one happens to actually change the way this thing renders. And by changing that, you can see the live DOM update. So this is really cool. And the fact that we're integrated with the tools and the platform means we can build apps even better. So for the rest of the presentation, I'm going to show a lot of code. Web Components is one of those things where it's a developer feature. It's for us. It's not a fancy feature like WebRTC or WebGL. So it's not sexy. It's actually for ergonomics. It's for you guys to produce a reusable code. So let's dive in. Let's talk about custom elements. Custom elements is sort of the foundational piece of Web Components. It allows you to create new HTML and tell the browser about that HTML. So let's build a button. There's no better way to actually learn this stuff than to actually build something. So we'll start simple. We'll build this very simple component, a button component. Now, if you probably know, right, HTML already has a button. But a lot of people stopped using button over the years. It doesn't look that great. It renders differently in different browsers. But it's got a lot of great built-in features if you think about it. Rob talked about focusability and keyboard behavior. It's got that built in. When you tab into this thing, it actually highlights itself. And it has this effect, this gradient that applies. It's got special properties to treat it like a button. It's got a disabled attribute that you can apply that actually affects the rendering of this element. And if you put this in a different context, if you put a button inside of a form and actually does something different, right, it submits the form and participates in the form submission. So this is magical and kind of cool. We get all this stuff for free just by declaring this on the page. But of course, we want to create a leave and better button. We'll call it a fancy button that's got a nice little ripple animation when the user clicks on it. It's got a box shadow if you apply this raised attribute. And we can make this thing behave exactly like button. So I'm going to do what Rob told you not to do, which is create a div button. Don't do this. This is just building up the example. But this is the way you might start off with this, right? And you could start off by using button and then remove the default styles the browser applies. But we're just going to have a blank slate here. Create a div, give it a class better button. And essentially, that class is just going to style this thing to look like a button. So it's got a box shadow. It's got some border radius. It handles disabled state if you have this disabled class on it. So we're just making a thing that looks like a button. But of course, if you want this thing to quack like a button, you have to do some things. So we'll add a tab index 0 and a roll equals button. We'll actually tell the screen reader that this thing is going to be a button, and we'll allow users to keyboard into our button. And maybe we want to have this ripple effect. That's the extra functionality we're adding to the button. So we'll rip the element out of the DOM and attach an event listener for that. And if the button isn't disabled, we'll allow people to click on it and we'll draw the ripple animation. So very simple, not much going on here. But this has a couple problems. The first is that users have to know how to style this thing themselves. They have to kind of know all that magic that we gave them, put that on their page. And the second is that we have to add a click handler for all instances of the button that are used on the page. It's not very reusable. I can't really reuse this thing. Users have to add their own tab index equals 0 and roll equals button. It's not very componenty. So of course, we can do better. And the answer is to use a custom element for this. We can create something that's reusable. So the first thing I've done here is just replace div with the name better-button. I'm creating a custom element, and custom elements have to have a dash in their name. That's just part of the specification. We are calling our button a better button. And instead of CSS classes to style this thing, I'm just going to use HTML attributes. It's a little cleaner to read, and it's going to map really well to the JavaScript properties we're going to define on this button. In my CSS, all I've done is just replace classes with that new tag name. Nothing's changed about the appearance of this thing. Of course, we can do even better. We can progressively enhance this markup from itself right now to something better. We can give it an API and use JavaScript to do that. And so the way you create a custom element is just define an ES6 class. We'll call it better-button, and it's going to extend the browser's native HTML element. So it's going to gain all of the DOM API. And since we're creating a button, maybe you want to have a disabled property just like the normal HTML button has. So we can do that in ES6, just for define a getter and a setter for disabled. And in this case, what I'm doing here is I'm keeping the attribute in sync with the JavaScript property. So if somebody changes the JavaScript property in JavaScript, we're going to actually reflect that value back out into HTML and set the attribute on the HTML tag in the live DOM. And other properties on the web today do this, too. The hidden property, the ID property, if you set them in JavaScript, they'll actually update the markup as well. So we can do that in custom elements. Something else you can do is go the other way. So if somebody tweaks an attribute, you want to get a notification about that. You want to react to that. And so for that, there's two special things you can do in element code. The first is to define and observe attributes array. This is sort of a whitelist to say, any attributes in this array, I want to get a callback for. And so what the browser is going to do, if it observes a change to one of these attributes, is call it your attached attribute change callback. It's going to be provided the name, the old value, and the new value that the attribute is changed to. And here what I've done is basically just look at the disabled property when that happens and set a tab index in an already disabled attribute accordingly. So we're kind of mimicking the button again by adding this functionality ourselves. Something else you can do is run code every time an instance or your element is decreated and declared on the page. So to do that, we'll just define a constructor. And the first thing you need to do in element constructor is call super. That's just part of the spec. It needs to set up the prototype correctly. And then from there, you can put in whatever you want. So in our case, we're going to define a key down listener. We want to actually have when people press Enter on our button to react to that. And that's what this code does. And then we'll add that click listener that actually adds the ripple animation. So if the button's not disabled, we'll allow people to click it and draw the ripple at the user's click location. We can also react to when our element is added to the DOM or removed from the DOM. And so for that, we can use the connected callback. This is a great time to do any setup work. In our case, we're adding the role for screen readers, and we're adding tab index 0 at that time. And disconnected while we're not using it in this component is actually very valuable for things like cleanup. So if you add a bunch of event listeners in your component or do other kinds of setup, you can remove it at this time. The browser will call that method. If you're curious on how drawRipple is implemented, it's pretty simple. This is the way I've chosen to implement it. Just a div with a ripple class that styles this thing to look like a ripple effect. So it's a div with a border radius that kind of just grows and fades out. Pro tip, I'm using CSS containment here. We're creating a reusable component that self-contained. Mine as well tell the browser to optimize this for us so it knows to scope layout and paint. That's awesome. We can just basically drop that in our web components. And the other thing I want to point out about this code is I'm basically creating a declarative style API and providing a little bit of functionality and flexibility for this component. So if some user that uses better-dash button styles the color, the font text with red, we're basically styling that the same as the background ripple is going to be styled the same as the font color. So this is kind of cool. You can do these things in your components and document how this stuff works for users. Now we've got a component. We've defined its ES6 class. The last thing we need to do is actually tell the browser about this new element. And so the way you do that is to use the custom elements interface and call the define method. You pass it the tag that you want to create and the class definition that you just created. And then from there, the users can use this element as if it was a div or a span or any normal HTML element. They can declare it on their page. They can use the new operator in JavaScript with the element constructor. Or they can call document create element. The same tricks apply that always apply to the web. So that's a lot of stuff, right? If you think about it, there's a lot of CSS involved to make it look like a button. We have a class that mimics all the behavior of a button. And the last thing we do is have the registration. We actually tell the browser about our new element. We can do better. We can progressively enhance what's already available in the web platform. So again, we have a button already in HTML. Why are we reinventing the wheel? Why are we mimicking everything it does for us? Why don't we just progressively enhance the button element? Well, sure enough, we can do that. Custom elements allows you to extend HTML that's already existing in the web. So instead of extending the HTML element, we're going to extend the HTML button element. We're going to extend the specialized version of that element. And then what happens is this is our entire class definition. So all that work we had to do before with tab indexing and key down listeners, all of that stuff goes away because we get the DOM properties and methods that button has for us just for free. And then we add the extra functionality. In this case, it's that ripple animation with the click handler. So this is really convenient. This is called a customized built-in element. And the way someone declares this on their page is a bit different. So instead of using better dash button, they're going to actually declare a button, and it's going to be an is better button. So this button is a better button. That's how that reads. So we've done a lot. We've made a custom element. It's reusable. It's a fancy button, a little sexier than the normal HTML button, but it's got all the benefits that the original one had in it. I want to take it a little bit aside and talk about this call here. The notion that you call custom elements dot define with the tag name, and you kind of upgrade the element. What's happening is what is called an element upgrade. This is part of the custom element spec. You kind of endow your markup with an API by defining some JavaScript that gives it its API and its methods and properties. So you take an HTML element, and you make it something better. So the notion here is that custom elements are really just progressively enhanced markup. You're taking something that doesn't have any functionality, and you're progressively enhancing it to have functionality. We've taken advantage of this notion of element upgrades on the developer's code lab site. We built it in Polymer. And if you dissect this thing, you can actually see where the components live on the page. So our search bar is a component. Our sorting and filtering widgets are components. And also this main section in the center is a card sorting element that knows how to rearrange its children based on the user's sort and filtering. So that's how this thing is kind of structured. I want to show what happens when we load this page. I'm going to slow it down to a 3G connection so you can really see the effect. So we'll navigate to the page, and instantaneously it paints. The browser, it turns out, is really good at just painting pixels, HTML, CSS, very small payload. And then eventually what happens is the components fade in. We'll see that one more time because it was kind of fast. So first paint is really fast. And then as the components upgrade and get their supercharged API, they fade in asynchronously. So it turns out this is really fast. I clocked this at about 2.2 seconds for a first paint on a Nexus 5 3G connection. And of course, this would get even faster with a service worker if we had caching and the user came back to the site. So the way you do this is to use another feature of Custom Elements. It's the CSS colon define. So you can basically pre-style elements before they're ready, before they get their JavaScript API and you call customElements.define. So in our case, I'm styling that paper tabs that selecting widget, basically giving it a little layout, giving it initial height to kind of replicate the styles that paper tabs defines in it. And I'm also just hiding it, right? On page load, it's just hidden. And then when the browser removes this defined pseudo class, our element will transition in. So the effect is that these things kind of just take up placeholders and you see them just fade in when they're ready. The rest of the page is very simple. Just a little bit of markup at the top to describe the website. We have that sorting and filtering section that's got some custom elements in it, the paper tabs element. And the main bulk of that intersection is this card sorting element. It's just a custom element. It's on the page ready to go. Everything's server-side rendered, so all these links just show up on page load. And they're styled to look like a codelab card. So this is great. This paints really fast. The contents there, available to users, they can start reading it right away. And then eventually, at some point in the future, we actually register these elements in the browser. And at that point, that's when the card sorting element gets its API, gets its filtering API and its sorting API. That's not critical on page load, so it's a great story for progressive enhancement. So let's think about what we've done so far. In a very short period of time, we've created a reusable component. It's got custom elements API. It's got reusable styles. If you drill down into the DevTools, you can actually see a problem, though. One of the implementation details is kind of leaking. This ripple div that we're creating dynamically is kind of mucking with the user's DOM. It's taking up space. Implementation detail, they really shouldn't see that. We can fix that. The answer here is to use another part of web components, which is ShadowDown. So if you think about today's elements, there's the select element, right? And you drop a couple of option tags in it, give one of them the selected attribute, and somehow the browser magically knows to render this thing as a dropdown widget and select the correct element. That's kind of cool. If you add the multiple attribute to this HTML element, it completely changes the way it looks. So instead of a dropdown, you get this multi-select widget. Pretty magical. The video element, a couple of attributes on the single tag. You get an auto-playing video with video controls for free. Where did these UI controls come from? And input type equals date, or any of the various specialized versions of input are pretty cool. Instead of a text box, text input, you get a UI that allows you to select a date. So this, my friends, is ShadowDown. ShadowDown allows us to do the same thing the native browser vendors have been using for a long time. They use ShadowDown to create these widgets and hide away markup and CSS. We can do that inside of our component as well. So in order to use ShadowDown inside of a custom element, it's just one or two lines. So inside of the element constructor, we can call this.attachShadow. That's going to create a document fragment, a shadow root that's going to kind of attach itself to our element. And we can fill that document fragment with anything we want, any markup you want. In our case, we're bringing in those styles from the page, so users don't have to define them themselves. This is great because styles inside of ShadowDown are scoped to your element. So that means styles and selectors aren't going to bleed out into the page, and page styles aren't going to bleed into your component. So that's why you see I've replaced some of the selectors here. I've changed better dash button to use colon host. That's the way you style the element itself inside of ShadowDown. And my selector for the ripple div has gotten simpler. We're just using dot ripple now. And that's because, again, these styles are scoped. We can use common IDs again. We can use common class names again. They're not going to collide with the main page because we're inside of ShadowDown, which has this scoping for us. And the last thing you see is I've moved in this ripple div. It's become part of kind of the implementation detail of my component. Users are not going to see this inside of their DOM. So let's take a look at this. When you do this, when you call this.attachShadowRoot, what happens is that you get a shadow root attached to your better button. That's great. We have ShadowDown in the works. And you can see that we have the styles scoped to this element. You can see the actual style information. This thing looks like the button, but it's actually lost something. It's lost that fancy button text that we have and that users have declared. And so the reason for this is that ShadowDown's kind of like a party. You have to invite things into it. You have to invite things in the outside world to render inside of your ShadowDown. For this, you use composition with the slot element. Slot's another element that's part of ShadowDown that you can use for bringing those things into your ShadowDown. So let's say I have a ShadowDown that looks like this. I have a style information and a slot element. What's going to happen here is that when someone declares a better button on their page, fancy button text is going to get projected into this slot. It's going to render at that location inside of my ShadowDown. And the effect is that you get the text back. That's exactly what we want. You can also have default content. So if someone doesn't provide the text themselves when they use our component, you can render just a button as the default text. And you can have an entire DOM tree in here if you wish. It doesn't have to just be text. And there's also a more advanced form. It's called name slots. So we can have as many slots in your component in your ShadowDown as you want. In this case, we're defining a slot with the name equals icon and a default slot that doesn't have a name. When someone uses our button like this, maybe they want to have a little gear icon next to some text. What's going to happen is that the name slot is going to get projected into that location. It's going to render in that slot. And the settings text is going to render in the other slot because it's not using a name. The effect is exactly what you'd expect, which is that gear icon in a settings text. So I think of composition, I think of a slot element as kind of a declarative API for your element. It's a way to really provide a level of functionality and customization. And this is exactly what the select element and those other native elements are doing, allowing for you to configure their UI based on attributes. But let's say somebody wanted to use our button like this. They want a ginormous pink button with a lot of padding and a different ripple color. Well, since we brought the styles into our component, how do you actually allow for this type of customization? The answer here is to use another new web platform feature, which is CSS custom properties, essentially CSS variables. So what we can do inside of our ShadowDown CSS is basically have placeholders for users to fill if they want, if they so choose. Support for this is really good right now, actually. Everyone but Edge has this available as a native feature. So when someone uses your custom element, they define some CSS for better button. They can fill in the values if they so choose. So they'll define, in this case, they're defining the button padding and they're defining the size of that ripple animation we're going to create. And so in this case, we'll use those values. But if they didn't provide them, again, we'll just use our defaults that we set up ourselves. So CSS custom properties is a great way to have placeholders and allow people to customize your component and the styling of your internal elements in your component. So that was fast. Let's recap what we did. In a very short period of time, in less than 30 minutes, we created a reusable button. It's progressively enhanced from the native HTML button, which means we have all the benefits that the browser in that element already gives us. It's got keyboard behavior, all the stuff that Rob talked about baked in. It's self-contained using DOM and CSS scoping of Shadow DOM. It has an imperative API, a JavaScript API, thanks to custom elements. It's got a declarative API, thanks to composition and the slot element in Shadow DOM. And it's also configurable. So people can use it in different ways with HTML and they can also configure the CSS. That's pretty cool. So this is why I'm so excited about web components, because it allows for this flexibility, allows for the good reuse on the web again. And this is just a button. You can imagine building an entire app out of components. If you don't want to get started, so if you do want to get started, go back, you can actually check out and try to use web components yourself. So Polymer has put together a really awesome set of reusable and very useful components for different types of things. And there's also custom elements.io that has a list of web components you can check out. So with that, that's all the time I have. Again, this is me on Twitter if you want to hit me up with questions. I think now we're gonna transition to a break. We're gonna take 20 minutes because those guys went over. But I really do appreciate you guys sticking around. Thanks for your time. Go componentize the web.