将mixins传递给样式组件

时间:2018-11-28 23:02:41

标签: css material-ui styled-components

我正在尝试将Mixin从Material UI传递给样式化组件。问题是我无法找到一种将mixin值传递给样式化组件而不将其分配给css属性的方法。例如,这是不可能的:

const Example = styled.div`
  ${p => p.theme.mixins.toolbar};
`;

编辑:问题最终是结束符'}'旁边的分号。我相信添加分号会使样式化组件认为您是在添加普通属性,而不是mixin。

3 个答案:

答案 0 :(得分:0)

// App/WithTheme.js

import React from 'react';
import {
  MuiThemeProvider,
  createMuiTheme,
  withTheme as muiWithTheme,
} from '@material-ui/core/styles';
import { ThemeProvider } from 'styled-components';
import PropTypes from 'prop-types';

const muiTheme = createMuiTheme({
  typography: {
    useNextVariants: true,
  },
});

function MaterialUiTheme(props) {
  return <MuiThemeProvider theme={muiTheme}>{props.children}</MuiThemeProvider>;
}

MaterialUiTheme.propTypes = {
  children: PropTypes.any,
};

const appTheme = { mode: 'light' };

function StyledComponentsTheme(props) {
  return (
    <ThemeProvider theme={{ app: appTheme, mui: props.theme }}>
      {props.children}
    </ThemeProvider>
  );
}

StyledComponentsTheme.propTypes = {
  children: PropTypes.any,
  theme: PropTypes.object,
};

const StyledComponentsThemeWithMui = muiWithTheme()(StyledComponentsTheme);

function WithTheme(props) {
  return (
    <MaterialUiTheme>
      <StyledComponentsThemeWithMui>
        {props.children}
      </StyledComponentsThemeWithMui>
    </MaterialUiTheme>
  );
}

WithTheme.propTypes = {
  children: PropTypes.any,
};

export default WithTheme;



// App/index.js

import WithTheme from './WithTheme';
import AppStuff from './AppStuff';

export default function App() {
  return (
    <AppWrapper>
      <WithTheme>
        <AppStuff />
      </WithTheme>
    </AppWrapper>
  );
}


// App/AppStuff.js
import styled from 'styled-components';
// import whatever else

// define AppStuff

export default const AppStuffStyled = styled(AppStuff)`
  margin-top: ${props => {
    console.log('styledProps', props); // manual check to see that we have theme w/ mui and app
    return props.theme.mui.spacing.unit;
  }};
`;

答案 1 :(得分:0)

您需要传播未调用它的mixins,如下所示:

const Example = styled.div`
  ${props => ({ ...props.theme.mixins.toolbar })}
`;

然而,这将返回样式对象,您可能希望将结果对象转换为css兼容的语法,如下所示:

const Example = styled.div`
  ${props => (Object.entries({ ...props.theme.mixins.toolbar }).reduce((styleString, [propName, propValue]) => {
      if (propName.indexOf('@') !== -1) {
        // iterate over media queries
        return `${styleString}${propName} { ${Object.entries(propValue).reduce((ss, [pn, pv]) => {
          pn = pn.replace(/([A-Z])/g, m => `-${m[0].toLowerCase()}`);
          return `${ss}${pn}:${pv+(Number.isInteger(pv) ? 'px' : '')};`;
        }, '')}; }`;
      }
      propName = propName.replace(/([A-Z])/g, matches => `-${matches[0].toLowerCase()}`); // convert camel-case properties into dash-splitted attributes
      return `${styleString}${propName}:${propValue+(Number.isInteger(propValue) ? 'px' : '')};`; // append css pixel unit to integer values
    }, ''))}
`;

答案 2 :(得分:0)

我阅读了您的修改,但删除分号对我不起作用。这可行:

import React from "react";
import { createMuiTheme } from "@material-ui/core/styles";
import styled, { ThemeProvider } from "styled-components";

const Content = styled.div`
  toolbar: ${props => props.theme.mixins.toolbar};
`;

const theme = createMuiTheme();

const Wrapper = props => {
  return (
    <ThemeProvider theme={theme}>
      <Content children={props.children} />
    </ThemeProvider>
  );
};

export default Wrapper;