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

Initial definition #1

Open
jxnblk opened this issue Mar 23, 2019 · 15 comments

Comments

Projects
None yet
8 participants
@jxnblk
Copy link
Member

commented Mar 23, 2019

This issue is meant to be the canonical place for discussion about the initial scope and details of the theme specification.

@jxnblk jxnblk pinned this issue Mar 23, 2019

@zethussuen

This comment has been minimized.

Copy link

commented Mar 25, 2019

Hi Brent!

As a designer, I'm a huge fan of styled-system and all of the work you've done in this space. As an engineer, I constantly advocate for styled-system + typescript. Personally, I want to see some sort of type recommendation in theme-specification. I would love to be able to swap theme specs in and out and not worry whether widths have been defined as a number (10) vs string (10px, 10em, etc). I can also see how this may be restrictive. Would love to hear your thoughts on the topic.

@souporserious

This comment has been minimized.

Copy link

commented Mar 29, 2019

Super excited to see this getting started!

I've been thinking about this spec the last couple of days and wondering if you have any thoughts on how multiple sets of fontSizes could be handled? Similar to how Github uses two sets of font sizes across viewports. Do you think it would be best handled in each respective application? I'm thinking it would be nice to have that relationship accessible in the spec for things like documentation, tooling, etc.

@jxnblk

This comment has been minimized.

Copy link
Member Author

commented Mar 29, 2019

@souporserious I'm hoping that the idea of scales being objects means that you would have one master fontSizes array or object, then use that as the basis for subsets like what you're describing. It could be additional custom fields like theme.mobileFontSizes and theme.desktopFontSizes or a nested object within the root scale, like theme.fontSizes.mobile. Just like colors, I think trying to make a one-size-fits all abstraction at the scale definition level will be very difficult, and this is more meant to start more from a where do I find values for font sizes perspective, if that makes sense

@jxnblk

This comment has been minimized.

Copy link
Member Author

commented Mar 29, 2019

@zethussuen thanks! I think this initial spec is meant to be fairly loosely defined when it comes to what you put in the scales. That said, an extension of this spec could absolutely layer a type system on top – I think the PR here sort of leans that direction: styled-system/styled-system#432

@souporserious

This comment has been minimized.

Copy link

commented Mar 29, 2019

Totally! That makes sense. I like settling on a key-value structure that everyone can adhere to, which right now seems great to me 👍.

@jxnblk

This comment has been minimized.

Copy link
Member Author

commented Mar 31, 2019

Just opened a PR for discussion about width and height properties here: #2

@Grsmto

This comment has been minimized.

Copy link

commented Apr 4, 2019

Related to @zethussuen comment, we are using TypeScript with styled-system and the way you define aliases for a scale does not work in a strictly typed context because you are applying a value to an array, which is considered an error in TS.
I don't know if you want to consider TS for the spec but that's how we had to do to avoid the typing error:

const fontSizes = {
  0: '0.75rem', // 12px
  1: '0.875rem', // 14px
  2: '1rem', // 16px
  3: '1.125rem', // 18px
  4: '1.25rem', // 20px
  5: '1.5rem', // 24px
  6: '1.75rem', // 28px
  7: '2rem', // 32px
  8: '2.25rem', // 36px
  9: '2.625rem', // 42px
};

fontSizes.baseText = fontSizes[1];

This way the fontSizes is an object and not an array but still can be accessed just like an array.

@jxnblk

This comment has been minimized.

Copy link
Member Author

commented Apr 4, 2019

@Grsmto Yeah, this spec should "work" for any language really. If you have to slightly alter what an object looks like for TS, I think that's totally valid. The aliasing example uses JS as a lingua franca to describe one possible approach to scale definition

@nniesen

This comment has been minimized.

Copy link

commented Apr 5, 2019

It's awkward that space is the only one that is collection and is not plural.

@timhudson

This comment has been minimized.

Copy link

commented Apr 5, 2019

I'm so glad to see this discussion and repo! After reading through the spec and everyones feedback, I wrote down my thoughts. This will be a bit of a dump, apologies in advance.

1. Static definitions JSON/YML

This has been discussed in styled-system/styled-system#432 (comment) and touched on above.

To increase the specs reach and potential adoption, it's certainly worth considering embracing a baseline of everything being statically defined. While any language could be used to generate a spec-compliant static theme, it's this common output that could be consumed predictably by tooling of any language or platform. I agree with the earlier sentiment that JSON would be a good choice.

However, we'd have to create or adopt a standard for referencing values. Style Dictionary solves this with a template-tag-esque approach.

2. Functions as values

This flies in the face of static definitions, but some scales could better be described through a function, especially when unbounded. A decent example is the space scale. This could reasonably be described as n => n * 1.5. Color scales could use a more complex function that understands color. Several systems use functions and omitting them here may limit this specs reach.

I'm on the fence as I would favor static definitions. Could they reasonably co-exist? It's a little convoluted but I could see this solved using function names which map to externally defined implementations.

"space": "fn:space" // gross prefix
export const space = n => n * 1.5

3. Abstracting away platform specific language/concepts

Considering how a design language can be applied across many platforms and technologies, how can we abstract away platform specific language without losing the specs simplicity and familiarity? While I don't think it's practical to have a completely generic spec, that sounds unnecessarily plain, I do wonder if we can take things a little further than where they are currently.

These stand out to me as potentially CSS specific:

  • mediaQueries
  • maxWidths, minWidths, maxHeights and minHeights?
    • I can't definitively say these are CSS specific but I'm skeptical
  • zIndices
  • Any mention of CSS outside the context of the Key Reference
  • Excluded Values could be reframed to discuss generally what is out of scope for this spec, using CSS as an example.

As for Key Reference mappings, we could make room for adding more key mappings beyond CSS. However, this has me questioning whether mappings should even be part of the spec. I'm tempted to consider that a tooling concern. I'm not sure.

4. Prior art

What makes this unique or more capable than existing solutions? Answering this can help folks see the value. For me personally, I see a potential ecosystem enabled by this spec. Knowing I could access tooling by adhering to spec can be compelling.

I'm sure there's more but here's the prior art I'm aware of:

  • Theo
    • Predictable Spec, easy to build tooling for
    • Doesn't support arrays or nesting
  • Style Dictionary
    • Supports nesting, not arrays
    • Supports aliasing

OK, I'll stop now 😝. I hope some of that is helpful in continuing this discussion.

@jxnblk

This comment has been minimized.

Copy link
Member Author

commented Apr 7, 2019

Thanks @timhudson! This is super helpful!

  1. Static definitions JSON/YML

I agree that having a statically defined theme for this spec makes a lot of sense. Personally, I'd rather avoid inventing anything like the templating in Style Dictionary – I think that can be handled by whatever generates the theme object if needed.

  1. Functions as values

I think similarly, functions could be used to generate the object, but I don't think this spec has to deal with templates or functions at all. How the scales are defined should be outside of the scope here, IMO

  1. Abstracting away platform specific language/concepts

This point I probably disagree with. While other specs may try to "bridge-the-gap" across platforms, I don't think that should be a goal here. CSS is a fine spec, and I'd rather this theme specification build on top of that base (because I think it's good). For a lot of this, it's not too difficult to translate from web terms into proprietary platform terms or ignore parts like media queries where it isn't applicable.

  1. Prior art

Yes, prior art absolutely should be documented in this project somewhere. Until I proposed this, I'd never heard of Style Dictionary, and I do mention Design Tokens (which is what the Theo implementation is based on IIRC)in my blog post. If there are any others, please feel free to open a PR to include them.

@timhudson

This comment has been minimized.

Copy link

commented Apr 8, 2019

functions could be used to generate the object, but I don't think this spec has to deal with templates or functions at all

I've been thinking a lot about dynamic theme modification lately, such as mobile sizes or high-contrast colors, but I've mostly thought of this as something acting on static tokens. I really like your suggestion above. It's a good mental model and maybe worth documenting for anyone else attempting to find where dynamic theming can fit in with static theme definitions.

CSS is a fine spec, and I'd rather this theme specification build on top of that base (because I think it's good)

I agree. I'm not concerned with using, or even favoring, CSS terminology. It's familiar, stable and in-line with typical design tokens.

I'm more thinking about the concepts that don't port well to other platforms. Rather than single out any one example, it may be better to map out my thought process as I evaluate some of these keys:

Is the key…

  1. a commonly used term (colors) or visual concept (shadows)?
  2. broadly useful (space) or fundamental to visual systems (fontSize)?
  3. well, thats all I got. Ha!

it's not too difficult to translate from web terms into proprietary platform terms or ignore parts like media queries where it isn't applicable

I'm particularly interested in translation and portability. This is mostly where I'm coming from.

Regarding ignoring parts of the spec, the question I'm inclined to consider is how often or in how many contexts would folks ignore this key? If this number felt low, I would begin to ponder that keys value and the specs increased surface area.

My feedback above isn't really actionable right now as it's focused more on thinking than actual output. But hopefully that is within the nature of this issue.

@dakebl

This comment has been minimized.

Copy link

commented Apr 17, 2019

What do people think of merging all of font tokens into a single object?
I've been toying with it a little in experimentation:

// Create your initial tokens
const tokens = {
  font: {
    families: {
      body: 'sans-serif',
      heading: 'Helvetica, sans-serif',
      subHeading: 'serif',
      monospace: 'monospace',
    }, 
    sizes: [
      12, 14, 16, 20, 24, 32
    ],
    weights: [
      200, 300, 400, 600, 700, 900
    ]
  }
}

// Add any aliases you feel are useful
tokens.font.sizes.body = tokens.font.sizes[2]
tokens.font.sizes.h1 = tokens.font.sizes[5]
tokens.font.sizes.h2 = tokens.font.sizes[4]
tokens.font.sizes.h3 = tokens.font.sizes[3]
tokens.font.sizes.h4 = tokens.font.sizes[2]
tokens.font.sizes.h5 = tokens.font.sizes[1]
tokens.font.sizes.h6 = tokens.font.sizes[0]

tokens.font.weights.normal = tokens.font.weights[2]
tokens.font.weights.bold = tokens.font.weights[4]
tokens.font.weights.extraBold = tokens.font.weights[5]

I've also been playing with a typographically based root object that includes things like letterSpacings:

// Create your initial tokens
const tokens = {
  typography: {
    fonts: {
      body: 'sans-serif',
      heading: 'Helvetica, sans-serif',
      subHeading: 'serif',
      monospace: 'monospace',
    }, 
    fontSizes: [
      12, 14, 16, 20, 24, 32
    ],
    fontWeights: [
      200, 300, 400, 600, 700, 900
    ],
    letterSpacings: [
      1, 1.25, 1.5, 1.75, 2
    ]
  }
}

// Add any aliases you feel are useful
tokens.typography.fontSizes.body = tokens.typography.fontSizes[2]
tokens.typography.fontSizes.h1 = tokens.typography.fontSizes[5]
tokens.typography.fontSizes.h2 = tokens.typography.fontSizes[4]
tokens.typography.fontSizes.h3 = tokens.typography.fontSizes[3]
tokens.typography.fontSizes.h4 = tokens.typography.fontSizes[2]
tokens.typography.fontSizes.h5 = tokens.typography.fontSizes[1]
tokens.typography.fontSizes.h6 = tokens.typography.fontSizes[0]

tokens.typography.fontWeights.normal = tokens.typography.fontWeights[2]
tokens.typography.fontWeights.bold = tokens.typography.fontWeights[4]
tokens.typography.fontWeights.extraBold = tokens.typography.fontWeights[5]

I'd be interested to hear what others think?

@russpitre

This comment has been minimized.

Copy link

commented May 1, 2019

It's awkward that space is the only one that is collection and is not plural.

I like spacings

@zethussuen

This comment has been minimized.

Copy link

commented May 1, 2019

@dakebl I do like the idea of anything font-related being grouped together. I would go a step further and think about line-height pairings as well.

tokens.typography.fontSizes.body = tokens.typography.fontSizes[2]
tokens.typography.lineHeights.body = tokens.typography.lineHeights[2]

In terms of implementation, this feels quite verbose to type out all the time:

const Foo = styled.div`
  font-size: ${theme.tokens.typography.body}
  line-height: ${theme.tokens.typography.body}
`

I would love an interface that abstracts common pairings away and allows for something like:

const Foo = styled.div`
  ${theme.???.body}; // "font-size: 14px; line-height: 20px;"
`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.