Cross-Platform Preprocessing Unit

Today while thinking about the platform translation Arcade has to do, I had a question:

To my surprise, there wasn't really a good answer. And I feel like there should be.

When creating a design token source, you want to write them to be platform-agnostic so they're ready to be translated to whichever platform you need.

So storing a variable's value as 24px, for example, would be incorrect. The px unit indicates CSS or and is too specific for a token.

Why not? The problem arises in transformation. Let's take a few approaches and see why.

The first would be blanket transformation, where we assume each number has to be transformed to Swift's pt values. So with a value of 24px, you'd strip the unit from the number, divide the px unit by three, and add "pt" to the end. Boom, you've successfully translated a CSS value to Swift.

But then what happens when we have a font-weight property? Usually those are stored in a unit-less number like 600. With a blanket transformation, since it's a number you'd turn your 600 font-weight into 200pt. Ew.

So, let's specify type! We can say what numbers are sizes and what numbers are font-weights. This will let our transformer know which values to translate into pts and which one to keep. This approach would work! Explicit types is a great aproach.

However, what if we want some sizes to stay as px values? How do we know those values should be transformed? Their types are both size, so type isn't quite the whole answer.

Style Dictionary kinda solves this by allowing you to use unit-less numbers. So in this example, "1" would translate to 16px.

This still requires explicit types on each number value so you know whether you're working with a font-weight or size.

While explicit type setting is good for tokens, that one extra input value is annoying to me. For Arcade, I want to keep token creation as easy as possible with the lowest cognitive load. I don't want any token to require more than a name and value. Everything else is extra.

So, I propose the creation of a unit that describes a platform-agnostic, pre-processed value (before transformation).

By using this unit, you'll know exactly what values should be transformed and which ones shouldn't. If another unit is used, we'll keep that unit. If there's no unit, we'll assume you want to keep it unit-less. And if the special unit is used, we'll try our best to transform the value to its appropriate platform value.

This enables implicit types for rapid token creation and maintains the cross-platform nature of token storage.

Maybe this idea sucks, I don't know. Or maybe it doesn't.

One way to find out.