design-tokens / community-group

This is the official DTCG repository for the design tokens specification.
https://tr.designtokens.org
Other
1.56k stars 63 forks source link

Toughts on the Use of "$" Prefix in the DTCG Token Standard #240

Closed DarioSoller closed 1 week ago

DarioSoller commented 3 months ago

First, I want to express my appreciation for the tremendous effort and dedication that has gone into developing the new DTCG token standard. The work being done here is invaluable to the design and development community, and I am grateful for the opportunity to contribute my thoughts.

As a lead frontend engineer and member of a bigger design system team, I have a deep appreciation for clean code craftsmanship, the importance of maintainable and speakable code and system design. With this in mind, I have some concerns regarding the decision to prefix relevant properties of the design token data object with the "$" character:

I apologize if my feedback comes at a late stage in the process, but I felt it was important to share my perspective. I am eager to hear the thoughts of others on this matter and to engage in a constructive discussion about potential alternatives.

Thank you once again for your hard work and for considering my input.

ddamato commented 3 months ago

I'm reasonably sure the $ convention used here is based on the variable naming convention originating in Sass. The jQuery usage is less relevant, as the entire library was meant to exist under that one namespace. Design tokens are more closely related to styling variables than DOM manipulation. I'm not familiar with RxJS observables, but there will be plenty of $ among other languages, just like there is plenty of usage of different characters for other reasons. I don't know how the RxJS ecosystem clashes with what is expected to be used in this specification.

Regardless of the history, what I find beneficial in the $ prefix here has to do with JSON's restrictions. While yes it would be great to have all of these enhancements to help the developer experience, the core of the specification is expected to align with JSON's limitations, AFAICT. We have used _ to denote private because the language used doesn't support the concept of private (until it does). This isn't necessarily meant for someone to edit in an IDE but for systems to ingest and transform into styles.

Further, I find that the $ provides more clarity as a "special" field than if special keys were to exist without needing to dive into documentation. It should raise the question, "Why do these keys have this prefix?" as opposed to if keys look like any other keys. However, given that you've raised the idea, I'd like to know what you suggest as alternatives, knowing the limitations.

nesquarx commented 3 months ago

Seconding @ddamato, specialness in human review is a big sell for the $ - and I don't see the $ translating to tokens in CSS or in places where it'll clash with a JQuery or equivalent.

On Tue, 13 Aug 2024 at 19:28, ddamato @.***> wrote:

I'm reasonably sure the $ convention used here is based on the variable naming convention originating in Sass https://sass-lang.com/documentation/variables/. The jQuery usage is less relevant, as the entire library was meant to exist under that one namespace. Design tokens are more closely related to styling variables than DOM manipulation. I'm not familiar with RxJS observables, but there will be plenty of $ among other languages, just like there is plenty of usage of different characters for other reasons. I don't know how the RxJS ecosystem clashes with what is expected to be used in this specification.

Regardless of the history, what I find beneficial in the $ prefix here has to do with JSON's restrictions. While yes it would be great to have all of these enhancements to help the developer experience, the core of the specification is expected to align with JSON's limitations, AFAICT. We have used _ to denote private because the language used doesn't support the concept of private (until it does). This isn't necessarily meant for someone to edit in an IDE but for systems to ingest and transform into styles.

Further, I find that the $ provides more clarity as a "special" field than if special keys were to exist without needing to dive into documentation. It should raise the question, "Why do these keys have this prefix?" as opposed to if keys look like any other keys. However, given that you've raised the idea, I'd like to know what you suggest as alternatives, knowing the limitations.

— Reply to this email directly, view it on GitHub https://github.com/design-tokens/community-group/issues/240#issuecomment-2286325605, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEKS36BFPO55XINO65KHPA3ZRIGGPAVCNFSM6AAAAABMN2DP72VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEOBWGMZDKNRQGU . You are receiving this because you are subscribed to this thread.Message ID: @.***>

DarioSoller commented 3 months ago

Thanks for going into a discussion so quickly and sharing your thoughts on that, @ddamato. Let me try to reply in detail and also trying to challenge a little bit on what you said:

I'm reasonably sure the $ convention used here is based on the variable naming convention originating in Sass. The jQuery usage is less relevant, as the entire library was meant to exist under that one namespace. Design tokens are more closely related to styling variables than DOM manipulation. I'm not familiar with RxJS observables, but there will be plenty of $ among other languages, just like there is plenty of usage of different characters for other reasons. I don't know how the RxJS ecosystem clashes with what is expected to be used in this specification.

Regardless of the history, what I find beneficial in the $ prefix here has to do with JSON's restrictions. While yes it would be great to have all of these enhancements to help the developer experience, the core of the specification is expected to align with JSON's limitations, AFAICT. We have used _ to denote private because the language used doesn't support the concept of private (until it does). This isn't necessarily meant for someone to edit in an IDE but for systems to ingest and transform into styles.

Further, I find that the $ provides more clarity as a "special" field than if special keys were to exist without needing to dive into documentation. It should raise the question, "Why do these keys have this prefix?" as opposed to if keys look like any other keys. However, given that you've raised the idea, I'd like to know what you suggest as alternatives, knowing the limitations.

specialness in human review is a big sell for the $ - and I don't see the $ translating to tokens in CSS or in places where it'll clash with a JQuery or equivalent.

So here is my innocent take on this

Referring to your example from https://design-tokens.github.io/community-group/format/#description-0

{
  "brand": {
    "$description": "Design tokens from our brand guidelines",
    "color": {
      "$description": "Our brand's primary color palette",
      "acid green": {
        "$value": "#00ff66"
      },
      "hot pink": {
        "$value": "#dd22cc"
      }
    }
  }
}

$description but also $type can be used on a group level. If one concern is to prevent conflicts between the property names of the design token standard and possible design token names, then it would also help if there are no conflicts of properties that are on different levels in the object hierarchy of the design token definitions. While the description on the group level also is a description just like a description for a single design token, there is still the difference for what these descriptions stand for. One for a group of tokens and one for a single token. Therefore I suggest that we actually name these descriptions for what they actually stand for: tokenGroupDescription and tokenDescription

I would suggest the following:

{
  "brand": {
    "tokenGroupDescription": "Design tokens from our brand guidelines",
    "color": {
      "tokenGroupDescription": "Our brand's primary color palette",
      "acid green": {
        "tokenValue": "#00ff66",
        "tokenType": "color",
        "tokenDescription": "Really ugly green",
      },
      "hot pink": {
        "tokenValue": "#dd22cc",
        "tokenType": "color",
        "tokenDescription": "Really hot pink",
      }
    }
  }
}

with the following exemplary JSON naming schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "patternProperties": {
    ".*": {
      "type": "object",
      "properties": {
        "tokenGroupDescription": {
          "type": "string"
        },
        ".*": {
          "type": "object",
          "properties": {
            "tokenGroupDescription": {
              "type": "string"
            },
            ".*": {
              "type": "object",
              "properties": {
                "tokenValue": {
                  "type": "string",
                  "pattern": "^#[0-9a-fA-F]{6}$"
                },
                "tokenType": {
                  "type": "string",
                  "enum": ["color"]
                },
                "tokenDescription": {
                  "type": "string"
                }
              },
              "required": ["tokenValue", "tokenType"]
            }
          }
        }
      }
    }
  }
}

I am on vacation for the next time, but I sure will pick up any discussion for when I am back in September.

ddamato commented 3 months ago

I don't know what's odd about using Sass as the archetype, considering these are design tokens, meaning they have roots in design. This makes them closer to the ecosystem of style as opposed to behavior as Javascript does. This was my comment regarding DOM manipulation; it has nothing to do with examples. The JSON is merely the transportation layer between systems, as this isn't limited to a JS ecosystem. Systems could ingest tokens in Python, Rust, or whatever. It's either JSON or XML as options in this case, and I have great confidence that no one wants to parse XML again. So, it's inaccurate to say JSON is strictly in the realm of Javascript.

I don't have any details about folks disliking jQuery because of the namespace convention it used. However, I'm not going to discuss jQuery any further because it's really a tangent in this conversation. If you are really afraid of clashing, use the jQuery namespace instead of the $; problem solved.

My comment about the quality of specialness certainly involves educating oneself about the schema, most likely through documentation. Without the prefix, I can imagine someone could accidentally remove expected keys because the file would look like unstructured data, as none of the keys look all that special. Personally, I'd use more caution if I saw keys with $ prefix.

mryechkin commented 3 months ago

@ddamato agreed with all of the above 💯

drwpow commented 3 months ago

Historical Context: The use of the "$" prefix can be reminiscent of older practices, such as those seen in jQuery, which may not align with modern coding standards and practices. Additionally, this prefix has been used in other contexts, such as RxJS observables, which has led to some confusion and mixed opinions within the developer community.

I'm reasonably sure the $ convention used here is based on the variable naming convention originating in Sass.

I don’t believe any of these are correct or relevant to the original decision. As I see you reached the conclusion, the primary need for this character is to mark reserved object keys. Reserving common words like description or group is too limiting on what tokens can be named (people may want a token named typography.description or card.group.bg-color).

The $ character specifically was inspired by JSONSchema that uses this pattern to reserve words. JSONSchema is a very relevant pattern to the DTCG spec because it allows arbitrary nesting, something that’s forbidden in other schema formats (e.g. OpenAPI). In the case of arbitrary nesting, you must reserve certain words and forbid them from usage. Using a prefix is the best of both words, being able to reserve many words, and make their reservation clear, without requiring verbosity and without reasonable conflicts with arbitrary user-provided names.

Additional technical explanation The DTCG format is basically an Abstract Syntax Tree (AST) format. It can be parsed, and traversed, and every level (“node”) must be classified as either a **group** or **token.** As-defined, a node is a **token** if it contains `$value` (_not_ `$type`), otherwise it is a **group**. Classification must happen using type discrimination. In traditional ASTs, you literally have a `type: "[type]"` key (or `kind`) at every level, which then determines the other properties you may have. However, manually typing this out is very user-hostile. It’s a _ton_ of boilerplate and overhead, but done in the service of making parsing and traversal trivially easy. So how do we keep all the benefits of an AST, without making it impossible to write by hand? Again, borrowing from JSONSchema’s innovations in this area, the `$` prefix is a brilliant solution to this hard problem of allowing an AST to be expressed in an incredibly human-readable & writable format. But while still being easy to parse. DTCG was wise to stand on the shoulders of giants here and solve the same problem in the same way.

Remember—this is a schema format. JSONSchema is a very close parallel. RxJS, jQuery, Sass, or what have you are all irrelevant. Draw what conclusions you want to personally, but none of those comparisons apply.

Could there be alternative approaches that might achieve the same goals without the drawbacks associated with the "$" prefix?

$description but also $type can be used on a group level. If one concern is to prevent conflicts between the property names of the design token standard and possible design token names, then it would also help if there are no conflicts of properties that are on different levels in the object hierarchy of the design token definitions. … Therefore I suggest that we actually name these descriptions for what they actually stand for: tokenGroupDescription and tokenDescription

Through discussion you arrived at a proposal to consider, changing $typetokenType, $grouptokenGroup, etc. You’ve come to the same exact design pattern—requiring a prefix—but you’ve just chosen verbosity because you don’t like the $ character. You mention “drawbacks” to using $ but I didn’t see a specific technical downside other than the opinion of “I see it in jQuery and jQuery is old and I think it’s bad therefore we should change it.”

This is a stylistic change that doesn’t solve any real problems with the schema as-currently-defined. And it’s one proposed without acknowledging relevant prior art like JSONSchema. So I’m personally not in favor of just changing an existing, working schema just because you personally don’t like its aesthetics. But if you feel strongly, I’d recommend making a new issue with a formal syntax proposal change to be reviewed.

danosek commented 3 months ago

tokenGroupDescription is less readable than $description. You know, as a designer I see unnecessary words and clutter.

To be clear - $ (or any prefix) was selected to eliminate conflicts of new standard properties with somebody's custom properties down the road? Because otherwise I don't see any added value.

drwpow commented 3 months ago

To be clear - $ (or any prefix) was selected to eliminate conflicts of new standard properties with somebody's custom properties down the road? Because otherwise I don't see any added value.

I just answered this in my comment before yours. JSONSchema. Arbitrary nesting in ASTs.

DarioSoller commented 1 month ago

Thanks, @drwpow, for mentioning that the primary need for the "$" prefix derived from the necessity to mark reserved object keys. Also, thanks for adding the respective source from the JSON Schema spec, which I hadn’t considered. This brings the discussion in the right direction.

Maybe you can help me better understand a few parts of this specification. For example, at the bottom of section 8, it states:

"While the "$" prefix is not formally reserved for the Core vocabulary, it is RECOMMENDED that extension keywords (in vocabularies or otherwise) begin with a character other than "$" to avoid possible future collisions."

If I understand this correctly, we have the following situation:

  1. "$" Prefix Not Formally Reserved: The "$" prefix is not exclusively reserved for the core vocabulary, meaning that technically, you could use it for other purposes.
  2. Recommendation for Extension Keywords: Despite the lack of formal reservation, it is recommended that any extension keywords (whether they are part of a custom vocabulary or otherwise) should not begin with the "$" character.
  3. Reason for the Recommendation: The primary reason for this recommendation is to avoid possible future collisions. As the JSON Schema specification evolves, new core keywords prefixed with "$" might be introduced. If your custom keywords also use the "$" prefix, they could conflict with these future additions.

Am I understanding it wrong? Could anyone maybe provide even more technical clarification here?

And regarding one of the other comments:

tokenGroupDescription is less readable than $description. You know, as a designer I see unnecessary words and clutter.

I still stick to my suggestion because, for me, it is less friction reading a longer variable name rather than having to resolve the abstraction for what the "$" prefix stands for. Also, keeping in mind how people read words, the order of characters doesn’t really matter as long as the first and last character are correct. This implies that reading speed is not significantly affected by the length of a word.

kaelig commented 1 week ago

I confirm what @drwpow said, there is no connection to Sass's usage of $.

@DarioSoller thank you for the great question and proposing alternatives. I do like your suggestions. I'm not saying $description is better than tokenGroupDescription, in fact I'd argue tokenGroupDescription is better in the sense it fully disambiguates the purpose of this key/value pair.

We instead chose to go the $-prefix route, and ran it past the author of JSON Schema himself, @Relequestual, who confirmed we weren't doing anything silly that would come back to haunt us later.

Sometimes, multiple appropriate avenues are open to us, and our job is to make a choice so the spec can move forward!