Rootstrap Get Started →

Insights

How to Set Up Material-UI (MUI)

How to Set Up Material-UI (MUI)

ReactJS (React) is a widely used JavaScript library and one of the most popular at the moment. React is used for building small pieces of user interfaces in what we know as components, you might think of it as LEGO blocks. React allows developers to use any kind of library for routing, state management, CSS and cache, making it a flexible technology. The main purpose of this tutorial is to teach you what MUI is and how to set up this powerful CSS library.

MUI

Material UI is one of the most famous collections of CSS libraries for React, and you can find the documentation in its official website MUI: The React component library you always wanted. As of the time of this tutorial, MUI is structured into three major sections:

  • MUI Core
  • MUI X
  • MUI Toolpad

MUI Core

In this section you can find four MUI libraries for building your app (and it is not required to use all of them in a project). Here you will find most of the components that you need when building a React application.

  • Material UI: contains a collection of React UI components which implement Google’s Material Design. Material UI
  • JOY UI: It is a library that contains a collection of JOY UI components which are an alternative to Material Design and is maintained by MUI. Joy UI
  • Base UI: is a library of React components unstyled and low-level hooks. Base UI
  • MUI System: is a collection of CSS utilities for laying out React UI componentsMUI System

MUI X (Paid version)

It is a collection of advanced MUI components such as Data Grid, Date and Time Pickers, Charts and TreeView. MUI X

MUI Toolpad

Toolpad is a tool powered by MUI’s components. It is designed to create applications faster. You build apps by dragging and dropping components and connecting external data.

SETTING UP MUI

For this tutorial we’ll be using the Material UI library as it is one of the most used and known libraries from MUI and now that we already know what MUI is in the ecosystem of React, let's set up the library in a brand new React project.

Create a new React application

Let’s create a react project by using vite.

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Naming the project

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Select React

Select typescript as the programming language in which we will be writing our app.

Now run the app

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Install Material UI

Once we have verified that our project is working as expected, let's install Material UI in it. To do so, let’s head to the official page of MUI, MUI Core and ultimately to Material UI and search for the command line instruction to install it with the default installation which comes with Emotion as its default styling engine. https://mui.com/material-ui/getting-started/installation/

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Install fonts (optional)

Now let’s install the Roboto font which is the default font used by Material UI.

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Install Icons (optional)

To have the chance to use Material Icons we need to install an specific package

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Render a button

Let’s open our favorite code editor in the root of our project. You should see something similar to this.

Now, go to the App.ts file and remove all the content. Then import the Button component from Material UI.

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Now, Add a component called App and return the button we just imported

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

and finally export the App component as default for our file

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

The final result should look like this

As you can see it is really easy to get a react application up and running with Material UI, so let’s keep going.

THEMING

Having an application that stands out is crucial, necessitating customization and having a set of custom components, colors, typography and other elements that work well together and can be used in our entire application. MUI provides a good tooling to do this as we see in the next sections.

Note: if you want to explore the default theme you will find this information here Default theme viewer.

Create a custom palette color

Let’s create a new file called customTheme.ts under the src folder. Now, create a variable called theme and assign to it the result of calling createTheme. For this case we’ll use the example provided by the official documentation. Color - Material UI

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Now export the theme variable

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Applying the Custom Theme

Go to the main.tsx file and let’s use the theme we just created. To do this we need to import the Material UI ThemeProvider and our theme.

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Now, wrap up the app around this provider.

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

You should see now that the button’s color has changed

Using a base theme to create another one with more tweaks

Now that we have taken a first look at how to create a custom theme, let’s add more changes to our theme. Go back to the customTheme.ts file (something you need to know is that you have the chance to create a theme out of another one). It is a good idea to create a base theme with the palette color that we are going to use across our app to avoid hardcoding color values everywhere. Let’s change the theme variable name to baseTheme and create a new theme called theme out of it. The process is very similar to what we did the first time when we created the baseTheme but now, we need to include this theme as an argument to the createTheme function.

You should see something like this

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Styling Components

If you want to change the styles to a specific component, that needs to be done whether when creating a theme, creating a custom component, applying the styles directly to the component or overriding the global styles.

Let’s set a 45 border radius to the default MUI’s Button implementing it with the different ways to achieve this. The button should look as follows:

One-off customization

This approach is used to customize a single component or a single instance of this component, this approach can be achieved with two basic ways:

- By using the sx property which is a property available in every MUI component:

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

- By overriding the styles with class names

Create a CSS file with the needed styles

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Import the file and use it in the App.tsx folder

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

- Reusable components

This approach is highly recommended as it allows for reusability and scalability by keeping a set of standard components used across the application. For this approach there are some main ways to achieve this.

  • By using the createTheme function: createTheme has a property components, inside this property you will pass in all the MUI components that you want to tweak, the properties set here will be merged in with the properties from the original theme.
/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 
  • By using the styled function which receives as an argument the MUI component to be customized and returns a new component.
/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

This new component could be exported as a stand-alone component from its own file;create a new file called StyledButton.tsx and paste the following code:

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Now import it in the App component

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Variants

Variants are a way of customizing the appearance and behavior of Material UI components, MUI has a set of built-in variants. Let’s take as an example the button component and the variants that come by default.

Creating a new variant

If you want to create a new variant to be used across our app, the way to do so is overriding the default set of variants and including the new ones by using module augmentation. Let’s do it for a Button component.

In the customTheme.ts file at the fop of the file below the imports paste

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

With this code, it is now possible to customize and use this new variant,

Now with the createTheme function let’s pass in the component property along with the new variant:

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

Now use the new variant in the App.tsx file

/* applying-custom-theme.tsx */
import { ThemeProvider } from '@emotion/react'; 
import { theme } from './customTheme'; 


/* css-files.scss */
.button { 
  border-radius: 45px; 
} 
 


/* custom-palette.tsx */
import { createTheme } from '@mui/material/styles'; 
 
const theme = createTheme({ 
  palette: { 
    primary: { 
      light: '#757ce8', 
      main: '#3f50b5', 
      dark: '#002884', 
      contrastText: '#fff', 
    }, 
    secondary: { 
      light: '#ff7961', 
      main: '#f44336', 
      dark: '#ba000d', 
      contrastText: '#000', 
      }, 
    }, 
}); 


/* export-app.tsx */
export default App; 

/* export-component.tsx */
import { Button, styled } from "@mui/material"; 
 
export const StyledButton=styled(Button)({ 
  borderRadius: 45,
}) 


/* export-theme.tsx */
export {theme} 

/* give-name.bash */
project name: … mui-project

/* import-button.tsx */
import Button from '@mui/material/Button'; 

/* import-new-components.tsx */
import { StyledButton } from './StyledButton'; 
 
function App() {
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>
  </>);
}
 
export default App 


/* import-scss.tsx */

import Button from '@mui/material/Button';  
import styles from './App.module.css' 
 
function App() {  
  return (  
    <Button variant='contained' className={styles.button} >Press me!</Button>  
  );  
}  
 
export default App 

/* install-fonts.bash */
npm install @fontsource/roboto 

/* install-icons.bash */
npm install @mui/icons-material 

/* install-mui.bash */
npm install @mui/material @emotion/react @emotion/styled 


/* new-project.bash */
npm create vite

/* new-theme.tsx */
const theme = createTheme(baseTheme,{ 
}) 


/* render-button.tsx */
function App() { 
  return ( 
  <Button variant='contained'>Press me!</Button> 
  ); 
}


/* reusable-components.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
      MuiButton: { 
        styleOverrides: { 
          root: { 
           borderRadius: 45, 
         }, 
        }, 
     }, 
  }, 
}); 


/* run-app.bash */
cd mui-project 
npm install 
npm run dev 


/* styled.tsx */
import Button from '@mui/material/Button';  
import { styled } from '@mui/material'; 
 
function App() {  
  return ( <> 
    <StyledButton variant='contained' >Press me!</StyledButton>  
    <StyledButton variant='contained' >Press me 2!</StyledButton>  
  </>);  
}  
 
const StyledButton =styled(Button)({ 
  borderRadius: 45,  
}) 
 
export default App 


/* sx.tsx */
function App() {  
  return (  
   <Button variant='contained' sx={{borderRadius:45}}>Press me!</Button> 
  );  
} 


/* use-variant.tsx */
function App() {
  return ( <> 
    <Button variant='dashed' >Press me!</Button> 
    <Button variant="dashed" color="secondary" sx={{ ml: 1 }}> 
  </>) 
} 
 


/* use-variants-with-theme.tsx */
const theme = createTheme(baseTheme, { 
  components: { 
    MuiButton: { 
      variants: [ 
        { 
          props: { variant: "dashed" }, 
          style: { 
            textTransform: "none", 
            color: blue[500], 
            border: `2px dashed ${blue[500]}`, 
        }, 
        }, 
        { 
          props: { variant: "dashed", color: "secondary" }, 
          style: { 
            color: red[500], 
            border: `4px dashed ${red[500]}`, 
          }, 
        }, 
      ], 
    }, 
  }, 
}); 
 


/* variant.bash */
? Select a variant: › - Use arrow-keys. Return to submit. 
❯   TypeScript 
	TypeScript + SWC 
	JavaScript 
	JavaScript + SWC 

/* variants.tsx */
declare module '@mui/material/Button' { 
  interface ButtonPropsVariantOverrides { 
    dashed: true; 
  } 
} 


/* wrap-app-with-provider.tsx */
ReactDOM.createRoot(document.getElementById('root')!).render( 
  <ThemeProvider theme={theme}> 
    <React.StrictMode> 
     <App /> 
    </React.StrictMode> 
  </ThemeProvider>, 
) 

You should see something like this:

This is it for now! And I hope this tutorial helped you understand the way MUI works and how you can set it up.

For further information

How to customize - Material UI (mui.com)

Themed components - Material UI (mui.com)

← All insights