DataSwede
DataSwede

Reputation: 5591

Reference to theme's primary color instead of a specific color in Material UI

Using ReactJS and Material UI, I have a project in which I have changed the theme colors.

const newTheme = getMuiTheme({
    fontFamily: 'Roboto, sans-serif',
    palette: {
        primary1Color: cyan500,
        primary2Color: cyan700,
        primary3Color: grey400,
        accent1Color: amberA400,
        accent2Color: grey100,
        accent3Color: grey500,
        textColor: darkBlack,
        alternateTextColor: white,
        canvasColor: white,
        borderColor: grey300,
        disabledColor: fade(darkBlack, 0.3),
        pickerHeaderColor: cyan500,
        clockCircleColor: fade(darkBlack, 0.07),
        shadowColor: fullBlack,
    },
});

  // App class
  render() {
    return(
        <ThemeProvider theme={newTheme}>
            <Project />
        </ThemeProvider>
    )
  }

Everything works as expected. Certain components, like buttons have the ability to set the color based on the primary prop. However, I have a component that uses an icon that needs the primary color. I can import the color and set it directly:

import React from 'react';
import ActionLock from 'material-ui/svg-icons/action/lock';
import {cyan500} from 'material-ui/styles/colors';

export default class LockIcon extends React.Component {
    render() {
        return(
            <ActionLock color={cyan500} />
        )
    }
}

Is there some way to reference the theme's primary color, rather than setting the color in each component individually? Something like:

import React from 'react';
import ActionLock from 'material-ui/svg-icons/action/lock';
import {primary1Color} from 'somewhere';

export default class LockIcon extends React.Component {
    render() {
        return(
            <ActionLock color={primary1Color} />
        )
    }
}

Upvotes: 38

Views: 64933

Answers (9)

E Purwanto
E Purwanto

Reputation: 363

With MUI 5 and the createTheme() function, you can reference the palette inside your ThemeOptions by passing a function as the typography value. This function accepts the palette as it's first argument.

This lets you easily map the various hX and bodyX typography variants.

const theme = createTheme({
  palette: {
    primary: {
      main: "#2D3178",
    },
  },
  typography: (palette) => ({
    h1: {
      fontSize: "2rem",
      fontWeight: 700,
      color: palette.primary.main,
    },
  }),
});

You can also reference the theme in the sx prop by passing a function

<Box sx={(theme) => ({
    backgroundColor: theme.palette.secondary.main,
})}/>

Upvotes: 1

viniciusalvess
viniciusalvess

Reputation: 814

You can use the useTheme() hook and access the colors like the example below. There are also some other color variants as well.

enter image description here

Mui 5:

import * as React from 'react';
import PropTypes from 'prop-types';
import { NavLink } from "react-router-dom";
import { useTheme } from "@mui/material/styles";

function VinNavLink(props) {
  const theme = useTheme();

  return (
    <NavLink {...props} style={({ isActive }) => isActive ? { textDecoration: "underline", color: theme.palette.primary.main} : undefined}>{props.children}</NavLink>
  );
}

export default VinNavLink;

Upvotes: 6

Normal
Normal

Reputation: 3596

MUI V5

For the users of MUI v5, you can specify a function inside the sx css style directly, ex:

<Box sx={{ color: (theme) => theme.palette.primary1Color }} />

Upvotes: 4

NearHuscarl
NearHuscarl

Reputation: 81280

If you're using system properties, you can define a string path of the Palette object to the color value like below:

<Box sx={{ color: "primary.main" }}>primary.main</Box>
<Box sx={{ color: "secondary.main" }}>secondary.main</Box>
<Box sx={{ color: "error.main" }}>error.main</Box>
<Box sx={{ color: "warning.main" }}>warning.main</Box>
<Box sx={{ color: "info.main" }}>info.main</Box>
<Box sx={{ color: "success.main" }}>success.main</Box>
<Box sx={{ color: "text.primary" }}>text.primary</Box>
<Box sx={{ color: "text.secondary" }}>text.secondary</Box>
<Box sx={{ color: "text.disabled" }}>text.disabled</Box>

The above is the same as:

<Box sx={{ color: theme => theme.palette.primary.main }}>primary.main</Box>
<Box sx={{ color: theme => theme.palette.secondary.main }}>secondary.main</Box>
<Box sx={{ color: theme => theme.palette.error.main }}>error.main</Box>
<Box sx={{ color: theme => theme.palette.warning.main }}>warning.main</Box>
<Box sx={{ color: theme => theme.palette.info.main }}>info.main</Box>
<Box sx={{ color: theme => theme.palette.success.main }}>success.main</Box>
<Box sx={{ color: theme => theme.palette.text.primary }}>text.primary</Box>
<Box sx={{ color: theme => theme.palette.text.secondary }}>text.secondary</Box>
<Box sx={{ color: theme => theme.palette.text.disabled }}>text.disabled</Box>

The example using the callback is more verbose but is type-safe, the shorter one with only string is quicker and good when prototyping, but you may want to store the string in a constant to prevent any typo errors and help the IDE refactor your code better.

Live Demo

Edit 43281020/reference-to-themes-primary-color-instead-of-a-specific-color-in-material-ui

Upvotes: 18

ykorach
ykorach

Reputation: 618

Yes you have! using muiThemeable..

import muiThemeable from 'material-ui/styles/muiThemeable';
class LockIcon extends React.Component {
    render() {
        return(
            <ActionLock color={this.props.muiTheme.palette.primary1Color} />
        )
    }
}
        export default muiThemeable()(LockIcon)

from material-ui docs

Upvotes: 18

Hamza Khursheed
Hamza Khursheed

Reputation: 2909

With react hooks, now you don't need to warp component in withTheme, just use useTheme:

import { useTheme } from '@material-ui/core/styles';

export default function MyComponent() {
    const theme = useTheme();
    
    return <span>{`spacing ${theme.spacing}`}</span>;
}

Upvotes: 5

jdoroy
jdoroy

Reputation: 954

If you're using React v16.8.0 and Material-UI v3.5.0 or greater, you can utilize the useTheme() hook:

import { useTheme } from '@material-ui/core/styles';

function LockIcon = () => {
  const theme = useTheme();

  return (
    <ActionLock color={theme.palette.primary1Color} />
}

Upvotes: 49

shashi verma
shashi verma

Reputation: 973

Ok if you are using material-ui version greater than 4, then the above solution might not work for you. Follow the below's code

import { withTheme } from '@material-ui/core/styles';

function DeepChildRaw(props) {
  return <span>{`spacing ${props.theme.spacing}`}</span>;
}

const DeepChild = withTheme(DeepChildRaw);

Reference: https://material-ui.com/styles/advanced/

Upvotes: 4

chenop
chenop

Reputation: 5143

Adding how to access theme colors in material-ui v1.0.0 (currently beta) Using withTheme component.
Also check the following Example.

import React, {Component} from 'react';
import { withTheme } from 'material-ui/styles';

class WithThemeExample extends Component {
    render() {
        const { theme } = props;
        const {primary, secondary} = theme.palette.text;

        return (
            <div>
                <div style={{color: primary}}>Hi in Primary color</div>
                <div style={{color: secondary}}>Bye in Secondary color</div>
            </div>
        );
    }
}

export default withTheme()(WithThemeExample);

Upvotes: 15

Related Questions