Zeyad Etman
Home

Thoughts about software development and Life

  • Home
  • About
  • Gallery
  • Twitter
  • Github
  • Books
  • Notes
  • Customize MUI theme with TypeScript

    0 Views

    4 min read

    material-uimuitypescriptnextjsstorybook

    Read more on design system from my notes

    Ok, this is a quick tutorial on how to customize the default theme in mui v5. we'll just customize the button component.

    Project Template here

    First thing, let's create our folder structure.

    Our folder structure is one of the basic setup we will do on our tutorial. it helps us to know where we will write our code in an organized way. Ok, so I prefer this structure while setup any theming whatever the ui framework I use.

    1.
    2└── theme/
    3 ├── foundations/
    4 │ ├── palette.ts
    5 │ ├── typography.ts
    6 │ ├── ...
    7 │ └── index.ts
    8 ├── components/
    9 │ ├── button.ts
    10 │ ├── ...
    11 │ └── index.ts
    12 └── index.ts
    13

    Now, we have two main folder, the first one will be foundations folder, and it used for basic theme variables, and the other one is components for components theming. In each folder we created index.ts file to export all from it.

    Next, let's build the theme from the end to beginning.

    open the theme/index.ts to import our foundations and components that structure our theme

    1import { components } from "theme/components";
    2import { foundations } from "./foundations";
    3import { createTheme, ThemeOptions } from "@mui/material";
    4
    5const themeOptions: Omit<ThemeOptions, "components"> = {
    6 ...foundations,
    7};
    8
    9export const theme: ThemeOptions = createTheme({
    10 ...themeOptions,
    11 components: {
    12 ...components,
    13 },
    14});
    15
    16

    No magic, ha? ThemeOptions will perfectly handles the types for the passed properties. We excluded the components from themeOptions vars and passed it inside the createTheme function, you can modify it to update it directly inside the variable.

    Based on mui, Here's the ThemeOptions interface, this will make our writing code is super easy and straightforward. How? We need to customize the theme colors for example, it called palette and its type is PaletteOptions

    So here's our theme/foundations/palette.ts

    1import { PaletteOptions } from "@mui/material";
    2
    3export const palette: PaletteOptions = {
    4 common: {
    5 white: "#fff",
    6 black: "#000",
    7 },
    8 primary: {
    9 main: "#33A3FF",
    10 light: "#53B1FD66",
    11 },
    12};
    13

    And because we've used the correct Interface so the editor will help us continue writing the remain properties

    The Question will be, What if I need to add a new color schema. The Answer is Simple as this

    1declare module "@mui/material/styles" {
    2 export interface PaletteOptions {
    3 blue?: PaletteColorOptions;
    4 }
    5}
    6

    How did I know about PaletteColorOptions ? it's not a magic, I clicked on PaletteOptions and checked the type for the already existing colors schema.

    Ok, until now everything is super easy right?

    What about customizing the components theme?

    Ok ok, the MUI Button component located here and they call it MuiButton. But let's create the components object that will be exported inside the createTheme.

    and it's simple as this theme/components/index.ts

    1import { Components } from "@mui/material";
    2
    3export const components: Components = {};
    4

    after that TS will help you writing your components.

    First thing, let's create our type for the MuiButton component theme, open the theme/components/button.ts

    1type muiButton = {
    2 defaultProps?: ComponentsProps["MuiButton"];
    3 styleOverrides?: ComponentsOverrides<Theme>["MuiButton"];
    4 variants?: ComponentsVariants["MuiButton"];
    5};
    6

    We got it from the .d.ts file located in the mui package files inside the node_modules folder. No magic!

    Note: Feel free to use interfaces or types for this.

    After that let's create our custom theme for MuiButton

    1declare module "@mui/material/Button" {
    2 export interface ButtonPropsVariantOverrides {
    3 isActive: true;
    4 }
    5}
    6
    7export const MuiButton: muiButton = {
    8 variants: [
    9 {
    10 props: { variant: "isActive" },
    11 style: ({
    12 theme,
    13 }: {
    14 theme: Theme;
    15 }) => {
    16
    17 return {
    18 color: theme.palette.common.white,
    19 };
    20 },
    21 },
    22 ],
    23};
    24
    1. I created a new variant for the Button you can use it inside your code.
    2. TS will be your guide while customizing the component.

    Note: I added export word before interface ButtonPropsVariantOverrides to avoid the eslint rule unused-imports/no-unused-vars

    Now, We need to wrap our app with this theme

    1import { theme } from "theme";
    2
    3<ThemeProvider theme={theme}>
    4 {children}
    5</ThemeProvider>
    6

    Tada! 🎉

    Project Template here

    Signature of the author