Tonic — A thin wrapper around Web Components

A Low Profile Component Framework – Stable, minimal, easy to audit, zero-dependencies and build-tool-free.

Basic component definition is really simple:

import Tonic from "https://cdn.skypack.dev/@optoolco/tonic"

class MyGreeting extends Tonic {
  render () {
    return this.html`<div>Hello, ${this.props.name ?? 'Stranger'}.</div>`
  }
}

Tonic.add(MyGreeting);

Tonic will automatically convert the CamelCased class name to the proper custom element name.

<my-greeting></my-greeting>
<my-greeting name="Bramus"></my-greeting>

Here’s the code above running on CodePen:

See the Pen
Tonic Web Components Demo
by Bramus (@bramus)
on CodePen.

Also comes with an SSR package.

Tonic →
Tonic (GitHub) →
Tonic SSR (GitHub) →

Alpha Paintlet

Dave Rupert created a little lovely Houdini Paint Worklet that allows you set a background color with an alpha on elements. The Worklet’s code is as simple as this:

registerPaint('alpha', class {
  static get inputProperties() {
    return ['--bg-alpha', '--bg-color']
  }

  paint(ctx, size, props) {
    ctx.globalAlpha = props.get('--bg-alpha');
    ctx.fillStyle = props.get('--bg-color');
    ctx.fillRect(0, 0, size.width, size.height);
  }
})
🎩 Houdini, ain't that a magician?

Houdini is a set of low-level APIs that exposes parts of the CSS engine, giving developers the power to extend CSS by hooking into the styling and layout process of a browser’s rendering engine. Houdini is a group of APIs that give developers direct access to the CSS Object Model (CSSOM), enabling developers to write code the browser can parse as CSS, thereby creating new CSS features without waiting for them to be implemented natively in browsers.

It really is magic, hence it's name Houdini. I'd recommend this slidedeck and this video to get you started

Using the two custom properties --bg-alpha and --bg-color you can control how it should look (in browsers that support Houdini, i.e. Chromium).

See the Pen
Alpha Paintlet Demo
by Dave Rupert (@davatron5000)
on CodePen.

~

In the video below you can see the conversation that builds up to it.

~

🎨 Alpha Paintlet (Blogpost) →
alpha-paintlet Source (GitHub) →

Natively Format JavaScript Dates and Times

Elijah Manor digs into Date’s toLocaleDateString() and toLocaleTimeString() methods to format Dates and Times in JavaScript, with respect to a passed locale.

const date = new Date();

console.log(date.toLocaleDateString('en-US'));
// 7/19/2020

const dateOptions = {
  weekday: 'long',
  year: 'numeric',
  month: 'long',
  day: 'numeric',
};

console.log(date.toLocaleDateString('en-US', dateOptions));
// Sunday, July 19, 2020

console.log(
  date.toLocaleDateString('fr-FR', {
    month: 'long',
  }),
);
// juillet

Also comes with a short video.

Natively Format JavaScript Dates and Times →

On Using Custom Properties

To me, the single greatest addition to CSS over the past 20 years is Custom Properties. They’ve opened up a ton of possibilities, and make us CSS Authors way more productive. The way they are specced — as properties and not simply variables — is pure genius and gives them their true power.

~

💁‍♂️ I heard spec author Tab Atkins talk about them for the first time at CSS Day 2013, but it wasn’t until Lea Verou‘s talk CSS Variables: var(--subtitle); in 2016 that it really clicked for me.

~

Over at CSS-Tricks, Chris Coyier writes about the Different Degrees of Custom Property Usage: how do you provide defaults, and how far do you go when splitting things up into several parts?

Regarding the fallback part Chris sticks to what we already know: a 2nd argument to var():

el {
  border: .1em solid var(--color, hsl(200deg 15% 73%));
}

The interesting part is on splitting things up: do you provide one single hsl color, or do you split out all the individual parts?

el {
  --color: hsl(200deg 15% 73%);
  border: .1em solid var(--color);
}
el {
  --color-h: 200deg;
  --color-s: 15%;
  --color-l: 73%;
  --color-hsl: var(--color-h) var(--color-s) var(--color-l);
  --color: hsl(var(--color-hsl));
  border: .1em solid var(--color);
}

Just like Chris I’m more leaning towards using --color here because although these Custom Properties are very nice, they do come at a cost: complexity. As I’ve tweeted back in February:

Thankfully there’s DevTools’s “Computed Styles” pane to somewhat help me out there 🙂

Additionally, settings these individual props on :root and then overriding --color-h for some specific element won’t work, because --color will already have been computed before it is passed down the inheritance tree. This is what Chris calls The Big Gotcha With Custom Properties.

~

Over at her blog, Lea Verou also wrote about Custom Properties and how to provide defaults. Interestingly, Lea opts to no directly use the passed in Custom Property, but resorts to something she calls “pseudo-private custom properties” that get an extra _ prefix.

My preferred solution is what I call pseudo-private custom properties. You use a different property internally than the one you expose, which is set to the one you expose plus the fallback.

Like so:

el {
  --_color: var(--color, hsl(200deg 15% 73%));
  border: .1em solid var(--_color);
}

As an extra she also taps into Houdini’s powerful @property to register a default value. Unfortunately Houdini is only supported in Chromium at the time of writing.

🎩 Houdini, ain't that a magician?

Houdini is a set of low-level APIs that exposes parts of the CSS engine, giving developers the power to extend CSS by hooking into the styling and layout process of a browser’s rendering engine. Houdini is a group of APIs that give developers direct access to the CSS Object Model (CSSOM), enabling developers to write code the browser can parse as CSS, thereby creating new CSS features without waiting for them to be implemented natively in browsers.

It really is magic, hence it's name Houdini. I'd recommend this slidedeck and this video to get you started

~

👀 Don’t try this at home

Because the contents of Custom Properties are not parsed until they are used (using var()), you can store anything in them. That means you could abuse them to create faux Single-line Comments in CSS:

~

Non-Euclidean Worlds Engine

Here’s a demo of a rendering engine I’ve been working on that allows for non-euclidean worlds.

What kind of sorcery is this?! 🤯

I do wonder what would happen when multiple players are walking around simultaneously, and how objects that pass through the tunnels would behave.

NonEuclidean (GitHub) →

How I Structure My CSS

Matthias Ott:

In this post, I will share my current take on CSS structure. It does not religiously follow any particular methodology, although people familiar with Harry Roberts’ ITCSS (“Inverted Triangle CSS”) will definitely recognize parts of his methodology.

The folder structure indeed looks very familiar:

/scss/
├── 1-settings
├── 2-design-tokens
├── 3-tools
├── 4-generic
├── 5-elements
├── 6-skeleton
├── 7-components
├── 8-utilities
├── _shame.scss
└── main.scss

Thanks for sharing, Matt. Always great to compare (and in this case validate) my own approach to other people’s work.

How I Structure My CSS →

Customise the React Native Developer Menu with Dev Settings API

Azim Ahmed comes with a few practical code snippets to alter the React Native Developer Menu from within your code, via the DevSettings Module:

  1. Toggle why-did-you-render
  2. Perform an action on the current route
import {DevSettings} from 'react-native';
import React, {useEffect, useState} from 'react';

if (process.env.NODE_ENV === 'development') {
  const whyDidYouRender = require('@welldone-software/why-did-you-render');
  whyDidYouRender(React, {trackAllPureComponents: false});
}

const App = () => {
  const [trackAllPureComponents, setTrackAllPureComponents] = useState(false);

  useEffect(() => {
    if (process.env.NODE_ENV === 'development') {
      const whyDidYouRender = require('@welldone-software/why-did-you-render');
      whyDidYouRender.wdyrStore.options.trackAllPureComponents =
        trackAllPureComponents;
    }

    DevSettings.addMenuItem('Toggle whyDidYouRender', () => {
      setTrackAllPureComponents(val => !val);
    });
  }, [trackAllPureComponents]);

  return null;
};

export default App;

React Native: 3 ways to use Dev Settings API →
React Native DevSettings API Example App →

HTML with Superpowers

Earlier this year Dave Rupert spoke at An Event Apart’s Spring Summit with a talk on Web Components:

It’s the year 2021. Lots of us are building our websites and apps with components and design systems, perhaps leveraging a JavaScript framework to help glue all the pieces together. The web has matured in the last 5 years and it might be time to start looking at how the Web’s native component system can give our HTML super powers. We’ll talk about how to create, style, and use Web Components in your project today as well as look at how the components you build today may offer a pathway to web standardization and help inform and influence the Web for future generations.

After an introduction on how to use Web Components with HTML, Dave digs into styling Web Components (which CSS selectors/properties pierce the Shadow DOM Boundary and which don’t?) to end with a section on building Web Components with JavaScript (Vanilla and Lit).

HTML with Superpowers (Blogpost)
HTML with Superpowers (Slides)

Lando — Instant Dev Environments For Every Project

If you’re goofing around with docker-compose, then be sure to give Lando a try:

Lando is a free, open source, cross-platform, local development environment and DevOps tool built on Docker container technology. Designed to work with most major languages, frameworks and services, Lando provides an easy way for developers of all skill levels to specify simple or complex requirements for their projects, and then quickly get to work on them.

Comes with easy recipes (Drupal, Laravel, Mean, Symfony, WordPress, …) and shortcut-commands that immediately (e.g. lando node --version runs immediately in your container)

At a recent PHPWVL meetup, Ike Devolder gave a talk on Lando that’s worth checking out.

Lando →
Talk: Getting Started with Lando →
Repo: Lando Playground →

Fixing the Drift in Shape Rotations

Steve Ruiz recently noted that in many design tools a group of shapes would end up at a different position after you rotate them and then successively rotate them back.

The problem here is that the average center of the group — the point on which the group rotates — changes after the first rotation. Knowing this, the solution — first detailed on Twitter and later on his blog — is pretty straightforward …

Fixing the Drift in Shape Rotations →