WIP

Contents

  1. Progressive Enhancement
  2. Web Components
  3. Property Descriptors

Progressive Enhancement

When it comes to designing robust systems, laziness can be an asset. Anyone who knows me knows I tend to recoil at re-implementing basic interaction patterns or functionality - why should I code something native HTML elements can handle already? Not only is it relatively boring, it's more code that I'll have to maintain that is, as with any code, susceptible to bugs and gaps in support. Who needs the headache?

Pushing native HTML and CSS too far can get you into trouble too, (I had to re-write my tabs pattern tutorial a few times as my clever tricks weren't exactly universally compatible), but their functionality is a good foundation to build on top of. Many complex patterns can be, at least in part, created out of more atomic components.

One such example is a multi-select listbox. Listboxes have a lot of ergonomic interactivity like type-ahead and a single tab stop, but boiled down to base it is a grouping of options, each of which may be selected or not. A <fieldset> of checkboxes affords that. It just lacks some of the convieniences.

When I was relatively new at my job, I heard the phrase graceful degredation for the first time. This was in the context of browser support - if something we were designing couldn't be handled by Internet Explorer, how could we offer contingencies that got users a good-enough experience? We ended up writing more code, specifically for this case that didn't naturally fit with our base design. When we dropped support some years later, the result was technical debt we had to lug around.

Progressive enhancement is a design philosophy which flips graceful degredation on its head. Instead of starting at a jet and working backwards to handling unpowered flight, you design from basic avation principles up to super-sonic capabilities.

Progressive enhancement is fantastic for maintainability and fault tolerance since irrespective of whatever situation you're in, you know the bare bones of your design are solid.

Web Components

As you may be able to tell by the rest of this site, I'm a fan of Web Components and custom elements. They're great for making reusable, flexible controls, or even just for being able to repeat content around a site. One approach I've been using more lately is to wrap some existing markup in a custom element which enhances its existing structure with new capabilities. As previously alluded to, one example I've made is the gw-checklistbox, which turns a set of checkboxes into a listbox.

This is one way progressive enhancment can work well, since the basic strucutre is apparent and will render on the page as-is should the custom element fail in some way. If the custom element can use the underlying markup directly as its state, surrounding code won't even need to know that the custom element is present or account for it. In this way, the enhancement can be transparent to surrounding code - so clear in how it operates that it can simply be ignored.

We can run into a bit of a snag here, though, in that changing the state of native HTML elements is not always something that can be easily tapped into. While clicking a checkbox bubbles up an event the custom element can listen to and setting attributes directly can be observed, modifying a property directly with code can happen silently. For example, if another bit of code sets the checked property from false to true, the custom element may never know.

Property Descriptors

What is the checked property anyway? To understand that, we need to talk about Objects in JavaScript for a moment.

JavaScript objects are mutable collections of properties[MDN]. They're often represented as key value pairs enclused in curly braces, e.g. {Name: "Vera", Cats: 3}. Here, Name and Cats are properties. The values of these properties may changed by assignment, for example obj.Cats = 4. Easy, right? There is a bit more going on here, though.

Properties are not simple string keys that point directly to values, they each have a descriptor which defines their behavior. Lets take a look at the descriptors on our example object.

Object.getOwnPropertyDescriptors({Name: "Vera", Cats: 3});
⬅️Object { 
⬅️  Cats: Object {
⬅️    configurable: true,
⬅️    enumerable: true,
⬅️    value: 3,
⬅️    writable: true
⬅️  }
⬅️  Name: Object {
⬅️    configurable: true,
⬅️    enumerable: true,
⬅️    value: "Vera",
⬅️    writable: true
⬅️  }
⬅️}
        
Console output

Each descriptor is its own Object with a set of properties and values. Does anyone else hear the Inception theme playing?