Build Design Systems With Penpot Components
Penpot's new component system for building scalable design systems, emphasizing designer-developer collaboration.

medium bookmark / Raindrop.io |
I work on a library called Polymer, which helps you write web components faster and easier. This is awesome, but it’s only awesome if you (yes, YOU) know what a web component is, and know that you want to write one. So here’s a story about what these things are and teaches you how to use them without showing you 10 pages of docs and getting you to install tools and CLIs. Maybe it’s for you. Maybe it isn’t. In either case, it has otters.
Web components aren’t a new library or framework, they’re a new browser feature, and they let you write encapsulated and reusable components (more details). If you’ve ever used an <input>
element, I like to think of it as the OG web component, because it’s exactly that. The thing
is that before web components came around, you had to wait on all browsers
to agree on a new element (like, a date picker). And even after they agreed
on a new element, it took them yeaaaaars to implement it. <input type="date">
was drafted in 2011 – today, 6 years later, not all browsers
have implemented it! With
web components, web developers get to write such elements, so that you don’t
have to wait for 10 years before all browsers agree that they should implement a date picker.
P cool, right?
<emoji-picker></emoji-picker>
, that just works out of the box.<input>
– whatever you can do<input>
you could do with a custom element.You write web components in ES6 JavaScript. Polymer is a JavaScript library that’s like jQuery for web components – you import it, it gives you a bunch of helper functions and saves you writing a lot of boilerplate code.
Also, bad habit: people (and me, I am those people) tend to use “custom element” and “web component” interchangeably. If you’re pedantic, they mean different things. Don’t be pedantic, it makes the otters sad.
If you’re starting to think about using web components in your app, there’s basically 2 situations you could be in, and I tend to reason about each differently
There’s other things that you might eventually care about, such as making your application production ready, and improving its performance. They are super important topics, but if you’ve never used a web component before, they’re also not the most important topics for you right now.
Web components tend to have dependencies on other web components, so you need a package manager to herd all them cats. Most of the web components out there use bower
. Another popular one is npm – you could think of npm
as a package manager for your server code and bower
for your client, and it wouldn’t be entirely incorrect.
The reason why you need a package manager and not just “download this element in a zip file” is that unless that element is really simple, it might have dependencies, and they’ll have dependencies, and that’s a thing for machines and not otters. If you really don’t want to use bower
, then you’ll have to sort out flattening your dependency tree on your own using something like webpack
. This is not the tutorial for you.
If you look up bower
on the web you’ll hear things like “but bower is deprecated now” (which is true, but it’s also been unmaintained for like a year and it worked fine, so nothing is really new on that front) and “but why not npm” (because you can only have one version of the same web component in your app, and that’s hard if your dependency tree is not flat. You probably don’t actually care this).
To install bower
, a package manager, you must first install npm
, a package manager. Take a moment for a concerned sigh, but install it anyway. Upshot: I promise this is the only tool I will ask you to install.
If you want to find otter web components, WebComponents.org is a universal catalog of web components (but not a package manager, because that would be cray). Go check it out.
Not all browsers implement features at the same rate, which means while you’re waiting for them to catch up, you need to care about polyfills. Fun fact: you know how when you have a hole in a wall, you have to put spackling paste in it to make the wall look like a wall again? Polyfilla is a brand of spackling, and that’s exactly what a polyfill is – it fills a hole in the browser, so that it looks even from the outside.
You have two choices:
<script src="some-path/webcomponents-lite.js"></script>
include.in your applications’s <head>
tag
Ok cool, so here we are. You have a web site, and you want to use someone else’s web widget in it. Let’s say that thing is paper-button which is a super fancy looking Material Design button. It’s beauty and it’s grace, it’s Miss United States.
Here is a glitch app if you want to follow along at home. Glitch is an online code editor, where you can build apps and modify other people’s – which is why it’s great for this example!
We need to do 3 things:
We do this by adding a dependency
to our bower.json
file. If you don’t already have a bower.json
file (who can blame you), create one by running bower init
, and answering the wizard’s questions. They kind of look like this, though, spoiler alert: there’s no actual wizard 😭
paper-button
as a dependency, you can either runbower install --save PolymerElements/paper-button#^2.0.0
bower.json
file in its dependencies
section:
"dependencies": {
"paper-button": "PolymerElements/paper-button#^2.0.0"
}
^2.0.0
just means “the latest version between 2.0.0 to 3.0.0”. The reason I picked that version is that it’s the latest one.bower.json
, you need to actually install it, so run bower install
.Right now you should have a bower_components
folder created, that contains a whole bunch of folders, one of which is called paper-button
.
This basically tells the browser where to find the definition for what this paper-button
tag is.
Much like how you import a CSS stylesheet with
<link rel="stylesheet" href="/style.css">
You import a web component with an HTML import:
<link rel="import" href="/bower_components/paper-button/paper-button.html">
Drop a <paper-button>Click me</paper-button>
somewhere in your html page.
Your index.html
should basically look like this:
<!DOCTYPE html>
<html>
<head>
<!-- Load the polyfill so that the demo works everywhere -->
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<!-- Import the custom element so that the browser knows what it means -->
<link rel="import" href="/bower_components/paper-button/paper-button.html">
</head>
<body>
<h1>Oh, hi there</h1>
<p>Have you seen this fancy button?</p>
<!-- Use the custom element! -->
<paper-button>Click me</paper-button>
</body>
</html>
See that line about loading the webcomponents-lite
polyfill? That’s the bit
that makes the demo work in browsers that don’t have web components yet 😎.
If you want to see what your app looks like without the polyfill, just comment
out that line and open your app in something like Firefox! It’s a good thing
to try out.
If we run that demo, it should look like this, plus or minus some
copy and styles that I’ve added:
Now, say it together with the otters!
You could, of course, add JavaScript to that custom element, like you would
with any other <button>
or <input>
. I could’ve added something like this:
document.querySelector('paper-button').addEventListener('click', function() {
alert('you did a click!');
});
Now that we know how to import someone else’s custom element, let’s write our own! Up until now we haven’t actually talked about Polymer at all. You can totally write web components without Polymer; you’ll just have to write a lot more boilerplate, and I don’t want that to turn you off web components.
The Polymer site actually has an awesome getting started tutorial, if you’d rather read that. But while I have you here, you’ll get the otter way.
In Polymer, every custom element is like a taco (bear with me). There’s something called a dom-module
(which is actually a custom element itself) that holds 2 things in it:
<template>
, or what your element looks like (html and css). A <template>
is an HTML element that’s inert – when the browser sees it, it skips it and doesn’t render it<script>
, which is what your element doesSidebar: This is one of the advantages of using Polymer – without
Polymer, you’d have to construct all your HTML and CSS in JavaScript, and somehow
add it to your custom element. Polymer makes it easier for you to point at
an implementation, and at a bunch of HTML/CSS and say “that look goes with that code”.
We add all our code to an .html
file (because remember: we’re going to do an HTML import to bring it in our app later). It ends up looking like this:
<dom-module id="my-element">
<template>
<!-- Any CSS your element needs for styling -->
<style>
/* This is a special selector that styles the element itself */
:host { ... }
/* Use the usual CSS selectors for its children */
p { color: tomato; }
</style>
<!-- that <p> style there applies here -->
<p>I should be a nice red!</p>
</template>
<script>
// Every custom element is an ES6 class.
// This is the implementation of the element.
class MyElement extends Polymer.Element {
...
}
// Every custom element needs to be registered.
// This tells the browser that the <happy-thing>
// tag uses _this_ implementation.
customElements.define(MyElement.is, MyElement);
</script>
</dom-module>
I tend to put one element per html
file, and then name the file after the tag of the element,
so I can keep track of it. I would save that into a my-element.html
file, and then import it in our app, just as before with:
<link rel="import" href="my-element.html">
Now, what goes inside your custom element is really up to you. The way I write elements is
<new-tweet>
element”)As a slightly more complicated example, I made a <happy-thing>
element in this
glitch app (check out the
code). It basically takes whatever content you give to it, and when you hover over, it does a little shimmy animation:
I also made that element with plain JavaScript, without Polymer, if you want to compare it. You’ll notice the second example has a lot more boilerplate code,
which Polymer abstracted out for you.
I hope this helped! I’m going to write another post in more detail about actually
getting started with Polymer, and what kind of things you can do with it soon!
In the meantime, here’s some other links to get you going:
AI-driven updates, curated by humans and hand-edited for the Prototypr community