segmentio / evergreen

🌲 Evergreen React UI Framework by Segment
https://evergreen.segment.com
MIT License
12.39k stars 832 forks source link

Generic Theme types, strongly typed DefaultTheme + theme utilities #1382

Closed brandongregoryscott closed 2 years ago

brandongregoryscott commented 2 years ago

Overview

Adds generic interfaces & type aliases that allow users to build their own theme objects or easily reference the values set in defaultTheme. I added tsd as a way to sanity check the type definitions while we're still on JS as well as serve as a playground for quickly inspecting types in VS Code.

Essentially, Theme is the base generic theme which is constrained to a set of Components ('Button', 'Input', 'Text', etc).

The DefaultTheme extends Theme and overrides some of the generic object types that accept string keys, such as colors:

// generic Theme 
colors: { [color: string]: Color<string | { [group: string]: Color }> }
// DefaultTheme
colors: { [color in DefaultThemeColors]: Color } & {
    border: Color<{ default: string; muted: string }>
    icon: Color<{
      default: string
      muted: string
      disabled: string
      selected: string
    }>
    text: Color<{ danger: string; success: string; info: string }>
  }

which is now strongly typed to: image

A similar strategy is used to expose the various appearances and sizes for each component.

While we would like to export a utility for generating interfaces for any generic theme object, we aren't quite there yet. This should act as a holdover for the time being.

Additionally, I added some other types/utilities:

Screenshots (if applicable) mergeTheme util which returns a union of the destinationTheme and sourceTheme types: image

primary is being overridden, while warning is a new appearance: image image

useTheme with default type set to DefaultTheme: image

Explicit typing: image

Factory function for returning a typed context: image

Since this is such a big change, I'd welcome others to pull down my fork and test out the types locally (assuming you have gh and yalc installed)

cd ~/your/clone/or/fork/of/evergreen
gh pr checkout 1382
yarn install
yalc publish

cd ~/your/project/using/evergreen
yalc add evergreen-ui

Documentation

netlify[bot] commented 2 years ago

βœ”οΈ Deploy Preview for evergreen-storybook ready!

πŸ”¨ Explore the source changes: 771703915ce1beccfe587539631fd0d1078e1924

πŸ” Inspect the deploy log: https://app.netlify.com/sites/evergreen-storybook/deploys/61dca962abb05800088d85e1

😎 Browse the preview: https://deploy-preview-1382--evergreen-storybook.netlify.app

anuejn commented 2 years ago

Hey, whats the state of this? This would be very nice to have :).

brandongregoryscott commented 2 years ago

Hey, whats the state of this? This would be very nice to have :).

Hey @anuejn! I was hoping to get through this hard-coded version as a holdover, but we wanted to take the time to get the TypeScript types correct to more generically represent the shape of a theme (both the default theme and how it can be extended). I'm working on that in another branch but I don't have an ETA for when it'll be ready. Since evergreen is not natively written in TS, writing the definitions and making sure they are accurate (especially with such a complex object with dynamic props) is clunky and time consuming.

In the meantime, the hard-coded version of DefaultTheme can be copied into your local project for reference/overrides. You'll probably have to do some casting, but it was generated from running JSON.stringify(defaultTheme); so it should be reasonably accurate.

anuejn commented 2 years ago

Okay, thanks for the the quick response. For now I will vendor the code from this branch into said project but I am thrilled to integrate the proper version when it is ready :)

brandongregoryscott commented 2 years ago

@anuejn This is available in v6.7.0. Try it out and let me know if you run into any issues!

anuejn commented 2 years ago

works for me :) (see https://github.com/audapolis/audapolis/pull/227 if you are interested)

anuejn commented 2 years ago

Actually one thing would be quite nice for our use case: The ability to put arrays of strings into the colors section of the theme. This is however nothing that is too important as we can work-around it by creating an object with integer keys for now (for an example use-case, see https://github.com/audapolis/audapolis/pull/227/files#diff-5dd9dde26bd45ecf6de8d7ee6a6a78ba430629ed9c57466fecf746b8d04a2f95R23).

However this already helps a lot and is a very nice solution to the typing problem :)

brandongregoryscott commented 2 years ago

Ooh, interesting! We haven't had a use case for a set of color values without specifically named keys yet, but as long as it doesn't muddle with the typing of the string or nested object typing, I think we can probably widen that field's type πŸ‘