In this section, we’ll be going through the most common theming options for our most common components. This list is not exhaustive, so if you don’t see what you need, you might need to dig yourself. See “How to theme a component” to learn how to do that.
Global
The most important variables to set are:
- global.initialMainColors.fg: Usually font color, but could also be used for icons or borders
- global.initialMainColors.bg: Background Color
Make sure these have good contrast!
- global.initialMainColors.primary: This is the main brand color for your site
Advanced
Derrived colors:
These colors are calculated if you don’t set them, but you’re free to tweak them.
- global.generatedMainColors.primaryContrast (defaults to white, but depending on your primary color, it may not work)
- global.generatedMainColors.secondary: Used for hover states on primary colors, by default a darker version of your primary color
- global.generatedMainColors.secondaryContrast (defaults to white, but again, depending on your secondary color, it may not work)
- global.links.colors.default : default link color
- global.body.backgroundImage: background image (optional)
- global.body.color: background color, overlays over top the bg set on global.mainColors.bg
How to theme a component
Getting familiar with the way we write styles will help a lot. See “Creating and Styling Components” section first.
So knowing that process, we can back trace from our browser to the variables.
For this example, I’ll use the the article reaction, (aka. The “Was this article helpful?” component).
If we inspect the component, we’ll see that the root div has a class called “articleReactions_f1tf4wb”. That means we can expect to find: “ArticleReactions.tsx”, “ArticleReactions.story.tsx” and “articleReactionsStyles.ts”. How unimaginative, right?
Let’s say we want to edit the title size. We inspect our component and find that the title has a class “articleReactions-title_f1rwc7t7”. Ok, so that means, we’ll need to look for “title” and we do find it. So, it gets its font size from a global variable: globalVariables().fonts.size.large,
That means, currently, to increase the font size, you would need to change the global large font size. Now, if you needed to do this, you could create a “reactionVariables” function, create a variable for the title that defaults to the global, assign it and then you’ll be able to change it just for the one component.
Yes, that is a lot of work for just one size, but once you do it, all future clients will have access to this new variable. So it’s short term pain for long term gain, instead of just throwing in a hacky bit of CSS.
Creating and Styling Components
When it comes to choosing names, it’s important to leave any sense of creativity out the door. The goal is to be very unimaginative, so it’s easy for people to guess where to find things.
Let’s go over an example:
Example: We want to make a component called “example”.
- This component’s file name will be: `Example.tsx`
- This components story (for storybook) will be `Example.story.tsx`
- This components styles will come from `exampleStyles.ts`
If this seems very unimaginative, then you’re doing an amazing job.
Let’s keep going:
Inside the exampleStyles.ts, we will likely have 2 functions:
`exampleVariables()`
You must call include in this file `const makeThemeVars = variableFactory("example");` This will create a namespace for your variables to live and not conflict with other parts of the app. You then create as many variables as you want.
const sizing = makeThemeVars("sizing", {
height: 48,
spacer: 12,
mobile: {
height: 44,
width: formElementVars.sizing.height,
},
});
Note that all variables declared with makeThemeVars will be namespaced in “example” since we created that function with the variableFactory.
This will return, unimaginatively, the variables for styling this component. This function may call on other global variables, like `globalVariables()` or `formElementsVariables()`. It’s good to be using these variables, because we can inherit variables from the globals, making it easier to propagate changes across the whole theme. Avoid depending on variables from one component to the other. It’s better to create a global variable and have them called separately call.
When creating your variables, do not simply copy over the list of classes you’ll need and create variables from them. Think as if you were a themer, wanting to modify this component. What options would you want to have control over? That’s what should be guiding your variables.
We commonly have components inherit from globals and then redeclare their own variable. Example, your example component might have a color variable and this color variable defaults to the global. This is a good pattern. It allows us to easily propagate changes throughout the theme by only setting a global variable. It also allows us to overwrite just that one component if we want it to be different from the global.
exampleClasses() => This will return, unimaginatively, the classes to style the component
In this function, you will be writing your actual CSS. You will need to call the styleFactory:
const style = styleFactory("inputBlock");
The style function here will prefix all the created classes with the string it was given, in this case ”inputBlock”.
The element “root” does not need a name, and so you can create it like so:
const root = style({
display: "block",
}
The generated class here will be something like “inputBlock_f3lw35i”. The random characters at the end are generated.The important part is the name you give it for debugging.
Any other elements, do need a sub element name though:
const errors = style("errors", {
display: "block",
fontSize: unit(globalVars.fonts.size.small),
});
The generated class here will be something like: inputBlock-errors_f3l245i
Note that the “style” function we use here is a wrapped and enhanced version of the style function from https://typestyle.github.io/#/core/-style-
These classes are now ready to be applied to your component and are themable.
Do NOT try and style on these generated classes directly. The hash at the end may change and it also goes against the philosophy of our system. If there’s something you’d like to customize, then let’s enhance the component to support it for all!