amzn / style-dictionary

A build system for creating cross-platform styles.
https://styledictionary.com
Apache License 2.0
3.86k stars 539 forks source link

[proposal] group property transforms #541

Open tlouisse opened 3 years ago

tlouisse commented 3 years ago

Group Property Transforms

In our current setup we want to add certain attributes to all properties inside an object (a 'group').

Why do I need this?

Let's assume we have a switch component... By default, I want all my properties to be not outputted as css variables, unless they should be globally switched for dark/light mode. The component itself would be outputted to a JS object, that can be applied in a css-in-jss like manner.

Dictionary

{
  component: {
    switch: {
      '@group': {
        isComponent: 'switchTokens',
        inherit: { outputCssVariable: false },
      },
      thumb: {
        fill: { value: '{color.primary.value}' }, // inherits @group meta
      },
      track: {
        fill: { value: '{color.secondary.value}', outputCssVariable: true }, // overrides @group meta
      },
      ... // lots of other props inheriting the default
    }
  }
}

Results

This outputs (via multiple formatters):

:root {
  --component-switch-track-fill: #0000ff;
}
html[theme="dark"] {
  --component-switch-track-fill: #ff00ff;
}
import { css } from '@lion/core';

export const switchTokens = {
  thumb: {
    fill: css`#0000ff`,
  },
  track: {
    fill: css`var(--component-switch-track-fill)`,
  },
 ...
}

Possible implementation

The idea is to register a group transform that preprocesses the complete dictionary and adds attributes. Concretely this could mean something like this:

 StyleDictionaryLib.registerTransform({
    name: 'group/inherit',
    type: 'group',
    transformer: (prop, { groupMeta } = {}) => {
      if (groupMeta) {
        // eslint-disable-next-line no-param-reassign
        prop = { ...groupMeta.inherit, ...prop };
      }
      return prop;
    },
  });

I would have a working proof of concept in a branch if interested.

chazzmoney commented 3 years ago

This might be most easily doable with your own custom properties and a custom filter...

@dbanksdesign thoughts?

tlouisse commented 3 years ago

I'm not sure if I understand what you mean. Could you maybe give a concrete example?