0

Trying to merge a custom theme options with the default one, so that my custom component will be using my theme without need of ThemeProvider wrapper.

New material-ui/styles/withStyles (mui v4-alpha) has additional option defaultTheme, that is overwritten by passed one, i'm trying to reset defaultTheme by myTheme, but no luck. Please help me to achieve that.

This is what i'm currently trying.

import React from 'react'
import Button from '@material-ui/core/Button'
import { createMuiTheme } from '@material-ui/core/styles'
import { withStyles } from '@material-ui/styles'

const styles = (theme) => {
  // here i'm getting myTheme with red palette.primary.main
  console.log(theme)
  return {}
}

export const MyButton = (props) => <Button {...props}/>

// reset primary color to red, so MyButton primary will be always red. 
// Here i mean much more complex extend with props and overrides keys (not only palette) 
const myTheme = createMuiTheme({
  palette: {
    primary: {
      main: '#ff0000',
    }
  }
})

export default withStyles(styles, {defaultTheme: myTheme})(MyButton)

But in the end, my MyButton is still using default blue mui color as primary one. What i'm doing wrong? Thanks in advance!

P.S. If i wrap <Button... into <ThemeProvider theme={myTheme}><Button..., all good, red button.

------------------edit #1------------------

Seems that my code is not working due to the following reason.

Default core Button component itself uses same withStyles wrapper function without defaultTheme option (only name option) export default withStyles(styles, { name: 'MuiButton' })(Button);. Means that Button itself gonna use default theme import defaultTheme from './defaultTheme'; (withStyle.js).

That means that i'm able to use withStyle defaultTheme option for my own components, but not for existing core once.

Then i have another question... Is it possible to apply myTheme (extension of defaultTheme) to default core mui component? (want to just import myButton somewhere else without need of ThemeProvider, similar how i'm importing core components)

zhulbert
  • 1
  • 3
  • I didn't understand why are you not wanting to use the theme provider wrapper. I thinks the API advises you using their own `MuiTheme` to restyle components theme wise. – Pedro Vieira Apr 22 '19 at 14:21
  • I want to have a library with set of components (some of them will use MUI some of them not). So when i import this components from my lib in another project, i don't want to have additional wrapper in this another project. Similar what MUI has... you import component and by default (if no ThemeProvider on top) it will be rendered with some default styling. – zhulbert Apr 22 '19 at 16:52

1 Answers1

0

I believe you can't do it without changing the API's core, it is implemented with a default theme and the way of changing this is as you already did, using a MuiThemeProvider. What you could do is using the theme provider inside your component and then export it, and when you use it in another code, you won't need to wrap it around anything. Like this:

import React from 'react'
import Button from '@material-ui/core/Button'
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import purple from '@material-ui/core/colors/purple';

const theme = createMuiTheme({
  palette: {
    primary: { main: purple[500] },
  },
});

function CustomButton() {
  return (
    <MuiThemeProvider theme={theme}>
      <Button color="primary">example</Button>
    </MuiThemeProvider>
  );
}

export default CustomButton;

And if it is a one-off change, you could use the inline styling with:

import React from 'react';
import Button from '@material-ui/core/Button';

const style = {
  minWidth: "200px",
  height:   "50px",
  padding:  "0 30px",
  fontSize: "1.125rem",
  lineHeight:   "50px",
  borderRadius: "3px",
  textAlign:    "center",
  textTransform:    "uppercase",
  transition:   "color 0.4s, background-color 0.4s, border-color 0.4s",
  letterSpacing: "0.05rem",
  textIndent: "0.1rem",
  textDecoration: "none",
  cursor: "pointer",
  overflow: "hidden",
  color: "#ffffff",
  backgroundColor: "#0096d6",
  border: "1px solid #0096d6",
};

function CustomButton() {
  return (
    <Button style={style}>example/Button>
  );
}

export default CustomButton;
Pedro Vieira
  • 2,266
  • 1
  • 20
  • 35
  • Note that you don't have to use `withStyles` – Pedro Vieira Apr 22 '19 at 17:16
  • You could even create a component with all the style theme options you want, and receive other components as props. So you could reuse your theme in more components. – Pedro Vieira Apr 22 '19 at 17:26
  • Thanks for your response! regarding inline: 1) i would like to have `theme` object in scope of css manipulations (withStyles). Although with inline, should be possible to make styles as a function and pass there theme (withTheme). 2) don't like having inlined css :). Regarding component wrapping. I've tried it, but appeared to be not a good idea. When you add 10 buttons on the page, css will be added to the DOM for all this 10 buttons. BaseButton_css *10 + MuiButton_css*10 + CustomButton_css*10 = 30 script tags with same content (css is the same, classNames differs by postfix) – zhulbert Apr 22 '19 at 18:50
  • I give up :) Looks like there is no easy way to achieve what i want. Guess the only clean and nice solution is to wrap all my apps with `ThemeProvider` on top of the app. – zhulbert Apr 22 '19 at 18:54
  • I think you could try using something I never did, the `props.children` property, so you can define a theme and inject all 10 buttons as props, loading the css files only once. Examples can be seen https://stackoverflow.com/questions/49706823/what-is-this-props-children-and-when-you-should-use-it – Pedro Vieira Apr 22 '19 at 18:57
  • It will add additional complexity to usage of my library components. Lib component should be maximum straightforward, and i should be able to just add this 10 buttons as is. Easier to add ThemeProvider on top :) – zhulbert Apr 22 '19 at 19:24