Migrating to Linaria theme
The way theming works has changed slightly in Flight 5.0 in order to be compatible with Linaria, to make switching between themes easier, and to make it possible to autocomplete theme values in your editor.
Step one
First, create a theme-variables.js
in your src
directory. Copy the default values in to it:
module.exports = {
default: {
colors: {
white: "#FFFFFF",
black: "#000000",
main: "#000000",
grey: "#878787",
lightgrey: "#E8E8E8",
tablegrey: "#F3F3F3",
beige: "#f5f5dc",
loadingBar: "#2f80ed",
blue: "#2f80ed",
red: "#FF0000",
background: "#f7f7f7",
darkgrey: "#333",
mediumgrey: "#9a9a9a",
highlight: "#2f80ed",
},
fontWeights: {
light: 300,
regular: 400,
semibold: 700,
},
breakpoints: {
xs: "20rem",
sm: "40rem",
md: "50rem",
lg: "64rem",
xl: "80rem",
},
fontSizes: [
"12px",
"14px",
"16px",
"20px",
"24px",
"32px",
"48px",
"64px",
"72px",
],
space: [
"0px",
"8px",
"16px",
"24px",
"32px",
"40px",
"48px",
"56px",
"64px",
],
fonts: {
primary: "Source Sans Pro",
},
},
};
Go ahead and update those values to match your previous Theme.js
.
Step two
Injecting global styles is handled differently in Linaria. If you have any global styles in Theme.js
, move them to a separate globalStyles.js
file:
import { css } from "linaria";
css`
:global() {
${globals};
}
`;
const globals = `
html,
body {
height: 100%;
font-family: '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto',
'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans',
'Helvetica Neue', 'Arial', 'sans-serif';
}
`;
And import it to the Shop.js
file:
import "../path/to/globalStyles";
Fonts
Another common use case for injectGlobal
in previous versions was for loading custom fonts in loadFontCss.js
. Similarly with globalStyles.js
, you wrap the styles in css
:
import { css } from "linaria";
export default function loadCss() {
return css`
:global(html) {
@font-face {
font-family: "Font Name";
src: local("Font Name");
font-weight: 400;
font-style: normal;
font-display: swap;
}
}
`;
}
You don't have to make any changes for the fonts in shop.js
if it is imported and passed to the <CustomFont />
component.
Step three
Now that your theme-variables.js
is ready, replace Theme.js
with the following:
import themeVariables from "../theme-variables.js";
import { createTheme } from "@jetshop/ui/Theme/createTheme";
// Edit your theme values at `src/theme-variables.js`
const theme = createTheme(themeVariables);
export { theme };
Whenever you create a styled
component with Linaria, it does not have the theme
object anymore. Therefore the following code would not work
const Container = styled("div")`
color: ${({ theme }) => theme.colors.red};
`;
You have to import the theme
object from the Theme.js
file to make it work
Whenever you want to use theme values in your CSS, import the theme from Theme.js
like this:
import { theme } from "../path/to/Theme";
const Container = styled("div")`
color: ${theme.colors.red};
`;
Step four
Add your theme to shop.config.js
. This is necessary so that we can use values from your theme in ui and core components.
In src/shop.config.js
:
import { theme } from "./components/Theme";
export default {
theme,
//... the rest of your config
};
Step five
If you are using sanitizeCss
to reset your CSS, you should simply import it in your Shop.js
:
import "@jetshop/ui/Theme/sanitizeCss";
Step six
You have to update both the client.js
and the server.js
files, so <Shop />
is no longer wrapped in <Theme />
. Example for client.js
file:
import React from "react";
import boot from "@jetshop/core/boot/client";
import Shop from "./components/Shop";
import config from "./shop.config";
boot(<Shop />, config);
Step seven
As Linaria styled
component no longer has the theme
object, you can't use theme
function from @jetshop/ui/utils/theme
anymore. Update your code to import the theme
object from your local Theme.js
file and use it as an object (and not as a function).
Common issues when upgrading
Invalid theme references
Previously, if you referenced an invalid theme value in your CSS, the React app would still happily render, although the generated css would include undefined
in place of the invalid value. For example:
const styles = css`
color: ${theme.this.doesnt.exist}
`
// the above would yield
.dfgkjdfhg { color: undefined }
Linaria is more strict about this, and will throw errors in the build if you try to access a theme value that does not exist. This is a common issue when upgrading stores.
In that case, you may see an error in the console referencing this:
Malformed CSS
If the CSS has syntax errors in it, Linaria will throw a less-obvious error.
In this case, it can be a little harder to track down. You may need to search your project for the CSS that is referenced by the error, and scan it to make sure it is valid.
For example, the above error was created by the following syntax in a styled component:
const Component = styled("div")`
#{$theme.above.md} {
color: red;
}
`;
Note the #{$theme.above.md}
is not valid syntax.
Multiple themes
Sometimes you may want the user to be able to switch themes through the shop’s UI. For example, this might be useful for a dark and light theme.
You may have noticed the default
key in theme-variables.js
. It’s now possible to add multiple themes to your theme-variables.js
just by adding keys for them.
For example, to add a theme named alt
:
{
"default": {
"colors": {
"primary": "blue",
"secondary": "#000"
}
},
"alt": {
"colors": {
"primary": "pink"
}
}
}
Any properties in the alt
theme will override those in the default
theme. So in the example above, the primary
colour in the alt
theme will be pink, and the secondary
colour will be black.
Using different theme variables per— shop ID
Some stores are based off the same repository, but with different shop IDs. In this case, you may want to load different theme variables depending on which shop ID the app is built with.
To do this, you can dynamically import your theme variables like so:
In Theme.js
:
const theme = createTheme(
process.env.REACT_APP_SHOP_ID === "demostore"
? require("../theme-variables.js")
: require("../theme-variables-alt.js")
);
Note that one of your theme variable files must be named theme-variables.js
.
Using multiple deploys with different themes within one repo
Some stores will have channels within the same shop that use different themes. In this case, you may want to change the gitlab-ci to deploy two different deploys for each channel.
Instructions for this can be found here.