Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Having a default property in a namespace #119

Open
dbanksdesign opened this issue Aug 22, 2018 · 20 comments
Open

Having a default property in a namespace #119

dbanksdesign opened this issue Aug 22, 2018 · 20 comments
Labels
Core Architecture This is an issue related to the core architecture of Style Dictionary discuss enhancement

Comments

@dbanksdesign
Copy link
Member

A few people have tried to create a structure where there is a "default" or "base" property on a given namespace, without having to name the property "default" or "base". For example, rather than doing this:

{
  "color": {
    "font": {
      "base": { "value": "#111" },
      "secondary": { "value": "#333" },
    }
  }
}

Doing this:

{
  "color": {
    "font": {
      "value": "#111" ,
      "secondary": { "value": "#333" },
    }
  }
}

This is so you could reference color.font as well as color.font.secondary or $color-font in scss. This is not possible today and would require some code changes to how style dictionary traverses the properties object.

Let's use this issue to discuss the pros/cons of this approach.

@chazzmoney
Copy link
Collaborator

chazzmoney commented Sep 7, 2018

Would it be confusing to support this as well?

{
  "color": {
    "font": {
      "base": "#111" ,
      "secondary": "#333",
    }
  }
}

I know people used to complain about having to add the object and value properties. With our added support for comments (and maybe additional properties in the future), I'm wondering if we want to establish / formalize the object at the end.

@chazzmoney
Copy link
Collaborator

chazzmoney commented Sep 25, 2018

Thinking more on this, I feel weird making "base" an automatic sub-key.

@elliotdickison had some good thoughts on base -> components and base -> theme -> components as a dependency chain of design tokens. He also mentioned @bradfrost post on theming with design tokens as similar thinking in this regard.

We should make sure our solution is thoughtful here.

@chazzmoney
Copy link
Collaborator

chazzmoney commented Sep 27, 2018

@dbanksdesign, @elliotdickison, @didoo thoughts?

@chazzmoney
Copy link
Collaborator

chazzmoney commented Sep 27, 2018

I guess I'm more willing to have "value" be optional. So using Danny's original example could be rewritten as:

{
  "color": {
    "font": {
      "base": "#111",
      "secondary": "#333",
    }
  }
}

This would directly conflict with Danny's suggestion. Would like to get feedback from folks on what they think would be a more useful solution.

@dbanksdesign
Copy link
Member Author

Having "value" as optional is a lot more of a technical constraint. We need some way of knowing what is a token and the value of a token versus extra data/structure to the JSON object. Without it, we would not know what is a token.

@didoo
Copy link
Contributor

didoo commented Sep 28, 2018

Somehow I understand why people would like to be able to

reference color.font as well as color.font.secondary or $color-font

but personally I don't think is something we should try to fix in exchange for more complexity in the codebase and less clarity in the properties declarations.

As soon as you have a "secondary" font color, from the semantic perspective you have to come up with a name for the other available option, even if is the default one. I can imagine that it may look easier to just write color.font but the reason for using design tokens is not shortening declarations, but having a predictable, systematic and well-organised set of "design values".

@dbanksdesign
Copy link
Member Author

Should we close this as "won't fix"?

@nategreen
Copy link

@dbanksdesign suggested I throw a use case on the pile.

In the Design Systems slack I posed a question based on what I tried and couldn't accomplish: having tokens both for a color (color.gray.10, let's say) and that same color with transparency (color.gray.10.alpha.20). I attempted to do this in several ways but none of them ended up working…the first/best one was:

{
  color: {
    gray: {
      "10": {
        value: "#123456",
        alpha: {
          "20": {
            value: "#12345633"
          }
        }
      }
    }
  }
}

Danny confirmed this couldn't be done. (I'd missed this issue when searching for answers, so thanks for pointing me here. :) )

I can work around it with a naming convention e.g. color.gray.10-alpha.20 or color.gray.10@20…although neither of these seem quite as clear as color.gray.10.alpha.20, I'd rather do one of those than have to always use color.gray.10.base.

So this is not a show-stopper for me (not in the least), but it does seem to be a more valid use case than what you'd mentioned previously. 🤷‍♂️ Thanks.

@gavinmcfarland
Copy link

What would be the cons or disadvantages for allowing the following to work?

{
  "color": {
    "font": {
      "value": "#111" ,
      "secondary": { "value": "#333" },
    }
  }
}

I suppose if this wasn't supported an alternative would be for users to automatically link base or default as the value to the parent property, but it feels like an unnecessary complexity for the user.

@chazzmoney chazzmoney added Core Architecture This is an issue related to the core architecture of Style Dictionary discuss enhancement labels Aug 30, 2019
@chazzmoney
Copy link
Collaborator

I'd like to retract my previous statements about making value optional. We are putting lots of other things besides values in these files now, and having a way to distinguish a token from any other random data stored in these files is important.

@coffeedawg
Copy link

coffeedawg commented Jan 10, 2020

We've decided to put our optional modifiers at the end and being able to have children when there's a value would be very helpful. I suppose we could add a pseudo-child called 'base' or 'normal', but really that just adds clutter. Consider the ramifications for nested cases such as ours. We have a button which can be primary or secondary. Each of these can be regular or inverse (against a dark background) It can have states such as hover and active.

 “button-background-color”
 “button-background-color-hover”
 “button-background-color-focus”
 “button-background-color-inverse”
 “button-background-color-inverse-hover”
 “button-background-color-inverse-focus”
 “button-background-color-secondary”
 “button-background-color-secondary-hover”
 “button-background-color-secondary-focus”
 “button-background-color-secondary-inverse”
 “button-background-color-secondary-inverse-hover”
 “button-background-color-secondary-inverse-focus”

Should we really have to define a base version of each of these modifiers? What if we add a pressed of disabled state? I Personally find the above to be much more readable than:

"button-background-color-base-base-base"

Also, I think each optional attribute should use a different adjective for "normal" or "base". ("notinverse"? "verse"?):

"button-background-color-primary-normal-base"

I went through the exercise of redoing the button definition using only tokens named with the above "complete" requirement. I found the tokens to be nigh unreadable. It was nearly impossible to find any of the values I needed as I was combing through the less.

I would really like to see style dictionary support children for nodes with a value.

I'm currently exploring the use of a preprocessor to flatten out the hierarchy down to the values, which should allow me to use the json I have in mind.

That's my two cents.

@MrDevinB
Copy link

One approach to this that I've found to work is using a special character to define the base style. The only place this breaks down is aliasing.

{
  "color": {
    "global": {
      "background": {
        "@": { "value": "#FFFFFF" },
        "inverse": { "value": "#000000" }
      }
    }
  }
}

outputs

$color-global-background
$color-global-background-inverse

In order to alias the token example above, you need to include the @ like so {color.global.background.@.value}.

Alternatively, you could flip this on it's head and create a way to define sub-tokens in a similar way.

{
  "color": {
    "global": {
      "background": {
        "value": "#FFFFFF",
        "@": {
          "inverse": { "value": "#000000" }
        }
      }
    }
  }
}

@ryanfitzer
Copy link
Contributor

Alternatively, you could flip this on it's head and create a way to define sub-tokens in a similar way.

IMHO, the @ symbol is too semantically vague. What about variants?

{
  "color": {
    "global": {
      "background": {
        "value": "#FFFFFF",
        "variants": {
          "inverse": {
            "value": "#000000"
          }
        }
      }
    }
  }
}

@MrDevinB
Copy link

@ryanfitzer that sounds like a great idea. The only reason I was straying away from any particular word was to not add limitations to the name of a token. That being said, variants does seem more difficult to use for a token name, but people certainly are creative.

@nhoizey
Copy link
Contributor

nhoizey commented Mar 23, 2021

I like @ryanfitzer idea with variants.

@klarkc
Copy link

klarkc commented Apr 13, 2021

I have this issue, I need to replace a tailwind config with style generated output, but the original config was made with primary, primary-content, primary-focus, secondary...

@dbanksdesign
Copy link
Member Author

Check out @MrDevinB's comment above for a potential solution right now. It will work with any special character or separator character (@, _, -, or probably even just a space).

{
  "color": {
    "global": {
      "background": {
        "@": { "value": "#FFFFFF" },
        "inverse": { "value": "#000000" }
      }
    }
  }
}

@uptonking
Copy link

@dbanksdesign
since now we have to write value all the time.
maybe u can consider implement like this:

  • the tokens without value will be output;
  • the tokens with value won't be output.
  • just the opposite of the present status. but this will be a huge breaking change!

@dbanksdesign
Copy link
Member Author

@uptonking you can take a look at the discussion on #575 where we are talking about that. I 100% know how annoying and tedious it is writing value all the time. I don't have a good solution for it yet... The main reason for having value at all was to let Style Dictionary know what part of an arbitrarily organized object was a token and what wasn't. Some people add comments, documentation, metadata outside the token objects but within the overall dictionary object structure. I am open to ideas though!

@dbanksdesign dbanksdesign removed this from the 3.0 milestone Apr 16, 2021
@nhoizey
Copy link
Contributor

nhoizey commented May 26, 2021

@dbanksdesign may I suggest to rename this issue from "Having a default property in a namespace" to "Having tokens as siblings of a value" or something similar, more accurate with the direction of the discussion?

I struggled finding this issue when looking for informations about this: https://twitter.com/nhoizey/status/1397597969457852416

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Core Architecture This is an issue related to the core architecture of Style Dictionary discuss enhancement
Projects
None yet
Development

No branches or pull requests