bubble-icon
Skip to main content

Theming

The GraphCommerce magento-graphcms example and GraphCommerce components are built with MUI ↗. MUI provides a robust, customizable, and accessible library of foundational and advanced components, enabling you to build your design system and develop React applications faster.

This guide covers how to customize the global look and feel of your application, as well as some common theming needs.

Changing the color palette

The global styles or your GraphCommerce app are located in /components/theme.ts. To customize the app with your preferred colors, change the primary, secondary and text colors. Save the file to see your changes updated in real-time:

  primary: {
    main: '#FF4A55',
    contrastText: '#FFFFFF',
    dark: '#F33642',
  },
  secondary: {
    main: '#006BFF',
    light: '#D1E4FF',
    contrastText: '#ffffff',
  },
  ...
  text: {
    primary: '#000000',
    secondary: '#00000050',
    disabled: '#00000030',
  },

You can search through your codebase to discover which components will be affected by your changes. For example, search for occurrences of theme.palette.primary.main.

Best practices

  • Limit the number of global style overwrites in /components/theme.ts. to a minimum if possible. In most cases, styling within the context of a component is the better solution.

Styling component with props

Most components have props that define their look and feel. Most common are the color and variant props:

<Button
  ...
  color='primary'
  variant='pill'
  >
</Button>
  • Learn about a component's features in the MUI documentation: MUI Button documentation ↗
  • To learn which options are accepted by a prop, refer to the component's API: MUI Button API ↗. You can also use your IDE's suggestions functionality. For VS Code's IntelliSense feature, type Ctrl+Space.
  • It can be helpful to learn how a component is styled, for example, to explore how palette variables are used. Refer to the MUI Button source code ↗

Change a component's styling with the sx prop

A simple way to style a component is by using the sx prop ↗. To get started with the sx prop in your GraphCommerce storefront, refer to start building a GraphCommerce custom storefront.

Accessing the theme

To access the theme object, set an anonymous function as the value of the property:

sx={{
  borderRadius: 2,
  backgroundColor: (theme) => theme.palette.primary.main,
}}

To use the theme object for multiple property's:

sx={(theme) => ({
  borderRadius: `1px solid ${theme.palette.divider}`,
  backgroundColor: theme.palette.primary.main,
})}

Creating styled components with the styled() utility

A more advanced way is to use the MUI styled() ↗ utility for creating styled components:

import { styled } from '@mui/material'

const AnimatedButton = styled(Button, { name: 'animatedButton' })(
  ({ theme }) => ({
    '@keyframes pulse': {
      '0%': {
        boxShadow: `0 0 0 0 ${theme.palette.primary.main}`,
      },
      '100%': {
        boxShadow: `0 0 0 15px ${theme.palette.background.default}`,
      },
    },
    animation: 'pulse 1.5s infinite',
  }),
)
<AnimatedButton color='primary' variant='contained'>
  <Trans>About Us</Trans>
</AnimatedButton>

https://user-images.githubusercontent.com/1251986/155032870-ddecefe0-afb3-418c-af3d-91d8bc435dff.mp4

Example of a styled component

Overriding components state styling

To overwrite a component's hover state, add the sx prop:

<Button
  color='primary'
  variant='contained'
  sx={{ '&:hover': { background: 'green' } }}
>
  <Trans>Contact Us</Trans>
</Button>

Learn more about overriding styles with class names ↗ in the MUI documentation

Adding a background image

  • In /Layout/LayoutFull.tsx, add the sx prop to the <LayoutDefault> component:
<LayoutDefault sx={{ backgroundImage: `url(/images/stripes.svg)` }} />
  • Place your background image in the /public/images directory

Customizing default border-radius

All components that render content with a border-radius, except for pill buttons and circular buttons, are dependent on the value of shape. A simple way to remove this effect is to set its value to 0:

  shape: { borderRadius: 0 },
  typography: {

Adding an external CSS style sheet

  • In /pages/_document.tsx, add your CSS <link> element as a child of the <Head> component:
<Head>
  ...
  <link
    rel='stylesheet'
    type='text/css'
    media='all'
    href='https://www.graphcommerce.org/pagebuilder.min.css'
  />
</Head>
  • The external CSS file will affect the styling of all your app's pages

Styling a component with CSS from external style sheet

  • Add the fetch query to the getStaticProps function of a page
const stylesheet = await(
  await fetch('https://www.graphcommerce.org/pagebuilder.min.css'),
).text()
  • Pass the data as prop:
return { props: { ...stylesheet } }
  • Specify its type:
function CategoryPage(props: Props & { stylesheet: string }) {

  • Add it to the default function's props:

const { categories, products, ..., stylesheet } = props

  • Use the sx prop to apply the styles
<CategoryDescription
  description={category.description}
  sx={{ stylesheet, minWidth: '100vw' }}
/>

Lineair scaling with responsiveVal

The helper function responsiveVal offers lineair scaling based on the viewport width. For example: responsiveVal(16, 22) will render 16px at 320px window width, 22px at 1280px window width.

responsiveVal can be used to linear scale almost all CSS properties, including width, borderRadius and margin. Performance-wise, font-size and line-height should not be scaled with responsiveVal. To learn more, look into responsive font sizes.

Next steps