Skip to content

Approaches

Learn which approach is recommended, depending on the situation, to customize Joy UI components.

  • For customizing only a specific instance of a given component, use the sx prop.
  • To ensure every instance of a given component looks the same across you app, use theming.
  • To create something that Joy UI doesn't support out of the box but still has design consistency, create a reusable component that uses Joy UI's theme design tokens.

sx prop

The sx prop provides a superset of CSS (contains all CSS properties/selectors, in addition to custom ones) that maps values directly from the theme, depending on the CSS property used.

Every Joy UI component supports it and it's a tool that allows you to quickly customize components on the spot. Visit the sx prop documentation to learn more about it.

Theming

The theme is an object where you define both your design language with foundational tokens such as color schemes, typography and spacing scales, and how each component, and their different variants and states, uses them.

Here are some examples that reproduce popular designs (only the light mode, though):

import { CssVarsProvider, extendTheme } from '@mui/joy/styles';
import Button from '@mui/joy/Button';

const githubTheme = extendTheme({
  colorSchemes: {
    light: {
      palette: {
        success: {
          solidBg: '#2DA44E',
          solidHoverBg: '#2C974B',
          solidActiveBg: '#298E46',
        },
        neutral: {
          outlinedBg: '#F6F8FA',
          outlinedHoverBg: '#F3F4F6',
          outlinedActiveBg: 'rgba(238, 239, 242, 1)',
          outlinedBorder: 'rgba(27, 31, 36, 0.15)',
        },
        focusVisible: 'rgba(3, 102, 214, 0.3)',
      },
    },
  },
  focus: {
    default: {
      outlineWidth: '3px',
    },
  },
  fontFamily: {
    body: 'SF Pro Text, var(--gh-fontFamily-fallback)',
  },
  components: {
    JoyButton: {
      styleOverrides: {
        root: ({ ownerState }) => ({
          borderRadius: '6px',
          boxShadow: '0 1px 0 0 rgba(27, 31, 35, 0.04)',
          transition: '80ms cubic-bezier(0.33, 1, 0.68, 1)',
          transitionProperty: 'color,background-color,box-shadow,border-color',
          ...(ownerState.size === 'md' && {
            fontWeight: 600,
            minHeight: '32px',
            fontSize: '14px',
            '--Button-paddingInline': '1rem',
          }),
          ...(ownerState.color === 'success' &&
            ownerState.variant === 'solid' && {
              '--gh-palette-focusVisible': 'rgba(46, 164, 79, 0.4)',
              border: '1px solid rgba(27, 31, 36, 0.15)',
              '&:active': {
                boxShadow: 'inset 0px 1px 0px rgba(20, 70, 32, 0.2)',
              },
            }),
          ...(ownerState.color === 'neutral' &&
            ownerState.variant === 'outlined' && {
              '&:active': {
                boxShadow: 'none',
              },
            }),
        }),
      },
    },
  },
});

function App() {
  return (
    <CssVarsProvider theme={githubTheme}>
      <Button>Solid</Button>
      ...other buttons
    </CssVarsProvider>
  );
};

Customizing theme tokens

Theme tokens refer to both low-level and global variant design tokens.

For example, instead of assigning the same hex code every time you want to change a given component's background color, you assign a theme token instead. If, at any point, you want to change that, you'd change in one place only, ensuring you consistency across all the components that use that theme token.

To print your own design language into Joy UI components, start by customizing these tokens first, as every component uses them.

To do that, always use the extendTheme function as the customized tokens will be deeply merged into the default theme. Under the hood, Joy UI will convert the tokens to CSS variables, enabling you to get them through theme.vars.*, which is very convenient as you can use any styling solution to read those CSS vars.

<span class="token keyword">import</span> <span class="token punctuation">{</span> CssVarsProvider<span class="token punctuation">,</span> extendTheme <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@mui/joy/styles'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> theme <span class="token operator">=</span> <span class="token function">extendTheme</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">colorSchemes</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">light</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">palette</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token comment">// affects all Joy components that has `color="primary"` prop.</span>
        <span class="token literal-property property">primary</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          <span class="token number">50</span><span class="token operator">:</span> <span class="token string">'#fffbeb'</span><span class="token punctuation">,</span>
          <span class="token number">100</span><span class="token operator">:</span> <span class="token string">'#fef3c7'</span><span class="token punctuation">,</span>
          <span class="token number">200</span><span class="token operator">:</span> <span class="token string">'#fde68a'</span><span class="token punctuation">,</span>
          <span class="token comment">// 300, 400, ..., 800,</span>
          <span class="token number">900</span><span class="token operator">:</span> <span class="token string">'#78350f'</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token literal-property property">fontFamily</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">display</span><span class="token operator">:</span> <span class="token string">'Inter, var(--joy-fontFamily-fallback)'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">body</span><span class="token operator">:</span> <span class="token string">'Inter, var(--joy-fontFamily-fallback)'</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">App</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">CssVarsProvider</span></span> <span class="token attr-name">theme</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>theme<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token operator">...</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">CssVarsProvider</span></span><span class="token punctuation">></span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

Customizing components

Each Joy UI component uses a pre-defined set of theme tokens. For example, the default small Button comes with fontSize: sm by default. To change that while ensuring that every instance of it has the same styles, do it targeting the component directly from the theme.

Here's a preview of how you'd change the button's font size to large:

<span class="token keyword">import</span> <span class="token punctuation">{</span> CssVarsProvider<span class="token punctuation">,</span> extendTheme <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@mui/joy/styles'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> Button <span class="token keyword">from</span> <span class="token string">'@mui/joy/Button'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> theme <span class="token operator">=</span> <span class="token function">extendTheme</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">components</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token comment">// The component identifier always start with `Joy${ComponentName}`.</span>
    <span class="token literal-property property">JoyButton</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">styleOverrides</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token function-variable function">root</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> theme <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
          <span class="token comment">// theme.vars.* return the CSS variables.</span>
          <span class="token literal-property property">fontSize</span><span class="token operator">:</span> theme<span class="token punctuation">.</span>vars<span class="token punctuation">.</span>fontSize<span class="token punctuation">.</span>lg<span class="token punctuation">,</span> <span class="token comment">// 'var(--joy-fontSize-lg)'</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">MyApp</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">(</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">CssVarsProvider</span></span> <span class="token attr-name">theme</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>theme<span class="token punctuation">}</span></span><span class="token punctuation">></span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Button</span></span><span class="token punctuation">></span></span>Text<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">Button</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">CssVarsProvider</span></span><span class="token punctuation">></span></span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

Reusable component

Creating new and custom components is always an option when you don't find exactly what you're looking for. You can, however, ensure design consistency with other Joy UI components by pulling styles from the theme through the styled function.

You also gain the ability to use the sx prop, which also accepts theme tokens, to customize this newly created component.