Enhancing MUI Theming with TypeScript: Custom Variants and Styles
TypeScript provides a powerful type system that can greatly enhance the MUI customization process, enabling developers to enforce type safety and utilize auto-completion features within their editors. This article will walk you through how to use TypeScript to customize MUI components and themes effectively.
Step 1: TypeScript with Component Customization
Customizing with Styled
When using styled
, TypeScript can infer types from the component. But to ensure that you are passing the correct props, you can define an interface for them:
1import Button from '@mui/material/Button'; 2import { styled } from '@mui/material/styles'; 3 4interface CustomButtonProps { 5 colorVariant?: 'dashed' | 'default'; 6} 7 8const CustomButton = styled(Button)<CustomButtonProps>(({ theme, colorVariant }) => ({ 9 ...(colorVariant === 'dashed' && { 10 border: `2px dashed ${theme.palette.primary.main}`, 11 }), 12 // more styles here 13})); 14 15// Usage 16<CustomButton colorVariant="dashed"> 17 Custom Styled Button 18</CustomButton>;
Extending Theme with Custom Variants
When adding new variants, you'll need to extend MUI's theme module to include the custom variant:
1import { createTheme, ThemeProvider, Button } from '@mui/material'; 2 3declare module '@mui/material/Button' { 4 interface ButtonPropsVariantOverrides { 5 dashed: true; 6 } 7} 8 9const theme = createTheme({ 10 components: { 11 MuiButton: { 12 variants: [ 13 { 14 props: { variant: 'dashed' }, 15 style: { 16 textTransform: 'none', 17 border: `2px dashed #3f51b5`, 18 }, 19 }, 20 ], 21 }, 22 }, 23}); 24 25// Usage 26<ThemeProvider theme={theme}> 27 <Button variant="dashed"> 28 Dashed Variant Button 29 </Button> 30</ThemeProvider>;
Step 2: Defining Themes with TypeScript
Creating a Typed Custom Theme
Defining a theme requires specifying the structure of the custom theme, adhering to MUI's ThemeOptions
interface:
1import { createTheme, ThemeProvider } from '@mui/material'; 2 3declare module '@mui/material/styles' { 4 interface Theme { 5 customShadows: { 6 card: string; 7 }; 8 } 9 // allow configuration using `createTheme` 10 interface ThemeOptions { 11 customShadows?: { 12 card?: string; 13 }; 14 } 15} 16 17const customTheme = createTheme({ 18 customShadows: { 19 card: '0 2px 10px 0 rgba(0,0,0,0.12)', 20 }, 21 // other theme settings 22}); 23 24// Usage 25<ThemeProvider theme={customTheme}> 26 {/* Your component tree */} 27</ThemeProvider>;
Implementing Predefined Component Styles
To ensure type safety when overriding component styles, you should extend the Theme
interface:
1declare module '@mui/material/styles' { 2 interface Theme { 3 components?: { 4 MuiButton?: { 5 styleOverrides?: { 6 root?: React.CSSProperties; 7 }; 8 }; 9 }; 10 } 11} 12 13const customTheme = createTheme({ 14 components: { 15 MuiButton: { 16 styleOverrides: { 17 root: (theme) => ({ 18 borderRadius: theme.shape.borderRadius, 19 }), 20 }, 21 }, 22 }, 23}); 24 25// Now, TypeScript is aware of the custom styleOverrides
TypeScript's integration with MUI's theming system ensures that your theme customizations are not only visually consistent but also type-safe, preventing a class of errors and improving developer experience.
Remember, by leveraging TypeScript with MUI, you gain access to a richer development environment, making the customization process more efficient and enjoyable. Now that you have the tools to type-check your themes, you can confidently apply these practices to craft stunning and consistent UIs.