[Typescript]Material UIテーマのパレットで任意のキーワードを追加する

4 min読了の目安(約4300字TECH技術記事

Material UIのpaletteを拡張する

Material UIではcreateMuiThemeでpaletteが作成できます。
便利ではあるのですが、デフォルト設定以外のキーワードでも色指定したい場面は多いかと思います。
Material UIのテーマカラーを拡張してデフォルトのprimary|secondary|error|warning|info|success以外のキーワードをパレットオプションに追加する方法、ついでにグラデーションも扱うときのちょっとしたテクもお伝えします。

拡張用のd.tsファイルの追加

デフォルト以外のワードで登録するとエラーが出るので、PaletteOptionsを拡張します。

PaletteOptionsを拡張する

src/types/createPalette.d.ts

import * as createPalette from '@material-ui/core/styles/createPalette';
declare module '@material-ui/core/styles/createPalette' {
    interface PaletteOptions {    
        customColor1?: PaletteColorOptions;
        customColor2?: PaletteColorOptions;
    }
    interface Palette {    
        customColor1: PaletteColor;
        customColor2: PaletteColor;
    }
}

PaletteOptionsを追加するだけならこれだけでOKです。

src/components/theme.ts

const theme = createMuiTheme({
  palette: {
    primary: {
      main: '#556cd6',
    },
    secondary: {
      main: '#19857b',
    },
    success: {
      main: '#69A06F',
    },
    error: {
      main: red.A400,
    },
    customColor1:{
      main: '#69cc6F',
    },
    customColor2:{
      main: '#356cd6',
    }
  },
})

オリジナルのPaletteColorを追加してPaletteColorOptionsを拡張する

追加したパレットオプションでデフォルトのPaletteColorOptionsを利用するのであれば上記で終了です。しかし例えばmainlightでなくここも任意のワードを使いたいのであればさらに追加が必要です。

import * as createPalette from '@material-ui/core/styles/createPalette';
declare module '@material-ui/core/styles/createPalette' {
    interface PaletteOptions {    
      customColor1?: PaletteColorOptions;
      customColor2?: PaletteColorOptions;
      primaryGradation?: GradationPaletteColorOptions
    }
    interface Palette {    
      customColor1: PaletteColor;
      customColor2: PaletteColor;
    }
    interface GradationPaletteColorOptions {
      toRight?: string
      toBottom?: string
      toRightBottom?: string
    }
    interface GradationPaletteColor {
      toRight: string
      toBottom: string
      toRightBottom?: string
    }
  }

こうすればパレットオプション内に任意のワードを追加することができます

const theme = createMuiTheme({
 palette: {
   primary: {
     main: '#556cd6',
   },
   secondary: {
     main: '#19857b',
   },
   success: {
     main: '#69A06F',
   },
   error: {
     main: red.A400,
   },
   customColor1:{
     main: '#69cc6F',
   },
   customColor2:{
     main: '#356cd6',
   },
   primaryGradation: {
     toRight: 'linear-gradient(90deg, #FF0000, #FFBA00)',
     toBottom: 'linear-gradient(180deg, #FF0000, #FFBA00)',
     toRightBottom: 'linear-gradient(135deg, #FF0000, #FFBA00)',
   },
 },
})

[おまけ]透過なグラデーションを扱う時

上記のようにlinear-gradient(90deg, #FF0000, #FFBA00)を登録しておけば、UI側でtheme.pallete.primaryGradation.toRightという具合に使うことができます。Hex(#xxxxx) だと透過は使えないのでRGB(rgba(xxx,xxx,xxx,0.7) という具合に登録しておくと透過も可能です。

const theme = createMuiTheme({
 palette: {
   primary: {
     main: '#556cd6',
   },
   //省略
   primaryGradation: {
     toRight: 'linear-gradient(90deg, rgba(255,0,0,0.7), rgba(255,186,0,0.7))',//opacity:0.7で透過!!
     toBottom: 'linear-gradient(180deg, #FF0000, #FFBA00)',
     toRightBottom: 'linear-gradient(135deg, #FF0000, #FFBA00)',
   },
 },
})
const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: {
      background: theme.palette.primaryGradation.toRight,
    },
  })
)

ただ透過度が固定でなくcss側で数値を入れたいときもあります。

色だけパレットから拾ってきたい場合はパレットの色登録をRGBにしておくとグラデーションの時の使い勝手は上がります。

ただ可読性は低いので、使う頻度などによっては関数化してしまう方が良いかもしれません。

const theme = createMuiTheme({
 palette: {
   primary: {
     main: '#556cd6',
   },
   //省略
   primaryGradation: {
     red: '255,0,0',//RGBで設定
     orange: '255,186,0',//RGBで設定
     toRight: 'linear-gradient(90deg, rgba(255,0,0,0.7), rgba(255,186,0,0.7))',
     toBottom: 'linear-gradient(180deg, #FF0000, #FFBA00)',
     toRightBottom: 'linear-gradient(135deg, #FF0000, #FFBA00)',
   },
 },
})
const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: {
      background:
        'linear-gradient(0deg, rgba(' + theme.palette.primaryGradation.red + ',0.7), rgba(' + theme.palette.primaryGradation.orange + ',0.7))',
    },
  })
)

こちらからは以上です!なにか参考になれば幸いです!!


参考