ScottSpence.com

Scott's Digital Garden.

Theming With Linaria

This is a followup on the post I did about Getting Started with Linaria

The starter I worked on last time I made into a template so it can be used as the base of this project.

I’ll use the Gatsby CLI to spin up a new project:

1gatsby new gatsby-linaria-starter-with-theme https://github.com/spences10/gatsby-starter-linaria

Defaults

In this example I’m using the defaults from Tailwind CSS for the theme.

With this as a base I can then add my own theme on top of that. An example of why I would want to do that would be with the Tailwind default there’s no primary colour.

If I want to add my own primary colour to the theme I can spread the defaults into my theme object, first up though, default theme.

To do that I’m going to create a theme-defaults.js file in the theme directory, then create a project-theme.js file where I’ll add in the theme properties I want in there.

1# create the files
2touch src/theme/{theme-defaults.js,project-theme.js}

Paste the Tailwind defaults into the theme-defaults.js file, I prefer to have a named export on files so I’m going to change the module.exports = { to export const defaults = {.

1export const defaults = {
2 prefix: '',
3 important: false,
4 separator: ':',
5 theme: {
6 screens: {
7 ...

The ... represents the reset of the items in the object, I’ve shortend it for brevity otherwise this would be a 400 line snippet. 😅

Really all I need from this is the theme object but rather than mess around with the object I’ll destructure the theme out of it in the project-theme.js file.

I can now use the Tailwind defaults in the project-theme.js file, this is also where I can add additional theme options, more on that shortly, for now I’m going to import the defaults, destructure the theme out of defaults and label it as themeDefaults I can then spread them into my theme object.

1import { defaults } from './theme-defaults'
2
3const { theme: themeDefaults } = defaults
4
5export const theme = {
6 ...themeDefaults,
7}

Theming with Linaria

If I wanted to I could create my own theme with Linaria using CSS custom properties but instead I’m going to be using the Callstack theme provider which has a hook I can use in useTheme.

1# install the theme provider
2yarn add @callstack/react-theme-provider

I’m going to create another file in the theme folder imaginatively named theme-provider.js in there I’ll import and pass in the theme object I created:

1import { createTheming } from '@callstack/react-theme-provider'
2import { theme } from './theme'
3
4export const { useTheme } = createTheming(theme)

Now I’ll be able to use the useTheme hook in my Linaria components using the styled tag.

Example

In the Header component I can now change the background property to use the theme.

I’ll need to import the useTheme hook and pass the theme object to the Linaria styled component theme prop.

1const Header = ({ siteTitle }) => {
2 const theme = useTheme()
3 return (
4 <StyledHeader theme={theme}>
5 <div>
6 <h1>
7 <Link to="/">{siteTitle}</Link>
8 </h1>
9 </div>
10 </StyledHeader>
11 )
12}

Now in the Linaria styled componet I can use any of the theme values. In the Header component I’ll change the background to blue:

1const StyledHeader = styled.header`
2 background: ${({ theme }) => theme.colors.blue[500]};
3 margin-bottom: 1.45rem;
4 div {
5 margin: 0 auto;
6 max-width: 960px;
7 padding: 1.45rem 1.0875rem;
8 h1 {
9 margin: 0;
10 a {
11 color: white;
12 text-decoration: none;
13 }
14 }
15 }
16`

Also a valid way to get the theme values would be:

1background: ${props => props.theme.colors.blue[500]};

I prefer to destructure the theme out of the props (({ theme })) however.

Moar theme options

So I have some nice defaults I can call on from the default config file I jacked from the Tailwind defaults. But what about that primary colour option?

Taking a look at the defaults there’s no option for rebeccapurple (hex #663399) so I’m going to add one.

In the project-theme.js I’ll define a new object for the primary colours, tip if you want to get shades of a particular colour take a look at 0to255.com.

With my shades of rebeccapurple I can add that to the theme object.

1import { defaults } from './theme-defaults'
2
3const { theme: themeDefaults } = defaults
4
5export const theme = {
6 ...themeDefaults,
7 colors: {
8 primary: {
9 100: '#aa7fd4',
10 200: '#9966cc',
11 300: '#884cc3',
12 400: '#773bb2',
13 500: '#663399',
14 600: '#552b80',
15 700: '#442266',
16 800: '#331a4d',
17 900: '#221133',
18 },
19 ...themeDefaults.colors,
20 },
21}

Take note that I’m spreading the colours back in after defining the new colour property. If I don’t do this then the object will be overwritten with the values provided here instead of both.

The new colour can now be used in the same way as before and I swap out the blue colour for the primary one.

Wrap up

So that’s how I add theming with Linaria, there was also the ThemeProvider and withTheme options that could be used from the react-theme-provider although I did find this way more suited to my needs.

Back to Top