简体   繁体   中英

How to extend or merge Styled Components theme

I have a Styled Components-based component library with its own set of theme settings that for the most part will never need to be overridden. I'm in the process of pulling this component library into another project that also uses Style Components and has its own theme. How can I import components from the component library and this project and ensure that each of them are only provided with theme values from their corresponding repo? I don't want to override my component library theme, I'd like to manage 2 separate themes so that my component library has access to a default theme and this other project can define a separate theme object for it's own components

Example: Separate Project

const theme = {
  colors: {
    error: '#f23f3f',
  }
}

import { SeparateProjectThemeProvider } from 'separate-proj';

class App extends React.Component {
 render () {
  return (
   <SeparateProjectThemeProvider theme={theme}>
     <h1>Hello</h1>
   </SeparateProjectThemeProvider>
  )
 }
}

Component Library

const theme = {
  colors: {
    brand: '#3bbdca',
  }
}

import { ThemeProvider } from "styled-components";

import defaultTheme from "./theme-settings";

const mergeThemes = (theme1, theme2) => {
  const mergedTheme = { ...theme1, ...theme2 };
  return mergedTheme;
};

const CustomThemeProvider = props => {
  const customTheme = {
    custom: Object.assign({}, defaultTheme)
  };

  return (
    <ThemeProvider theme={mergeThemes(customTheme, props.theme)}>
        {props.children}
    </ThemeProvider>
  );
};

export default CustomThemeProvider;

The code below will demonstrate a couple options -- either pre-wrapping each of your component-lib components with the appropriate theme provider (WrappedTitle) or wrapping as you use them ("Hello Component World!" portion).

// Sample component-lib/index.js
import React from 'react';
import styled from "styled-components";
import {ThemeProvider} from "styled-components";

const theme = {
  titleColor: "green"
};
export const CompLibThemeProvider = props => {
  const customTheme = Object.assign({}, theme, props.theme);
  return (
    <ThemeProvider theme={customTheme}>
        {props.children}
    </ThemeProvider>
  );
};

export const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: ${props => props.theme.titleColor};
`;
export const WrappedTitle = (props) => {
  return (<CompLibThemeProvider><Title {...props}/></CompLibThemeProvider>);
};

And here is some sample project code:

// App.js
import React from 'react';
import styled from 'styled-components';
import {Title, CompLibThemeProvider, WrappedTitle} from 'component-lib';
import {ThemeProvider} from "styled-components";

const theme = {
  titleColor: "red"
};

export const BigTitle = styled.h1`
  font-size: 5em;
  text-align: center;
  color: ${props => props.theme.titleColor};
`;

const ProjectThemeProvider = props => {

  return (
    <ThemeProvider theme={Object.assign({}, theme, props.theme)}>
        {props.children}
    </ThemeProvider>
  );
};
const App = () => {
  return (
    <>
    <ProjectThemeProvider>
      <>
        <BigTitle>Hello Big World!</BigTitle>
        <WrappedTitle>Hello Pre-wrapped World!</WrappedTitle>
      </>
    </ProjectThemeProvider>
    <CompLibThemeProvider><Title>Hello Component World!</Title></CompLibThemeProvider>
    </>
  );
}

export default App;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM