Stretching the limits: Combining and expanding your Styled Components theme

I am facing a situation where I have a component library built using Styled Components that has its own theme settings which are not meant to be overridden. Now, I need to incorporate this component library into another project that also uses Style Components and has its own theme. How can I import components from both the component library and the project while ensuring that each of them only receives theme values from their respective repositories? I want to maintain two separate themes - one for the component library and another for the project's components.

For 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;

Answer №1

In the following code snippet, you will find two different options to style your component-lib components using a theme provider. You can either pre-wrap each component with the appropriate theme provider (WrappedTitle) or wrap them as you use them within the code ("Hello Component World!" section).

// Example 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>);
};

Here is an example of how the project code could look:

// 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;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Placing a button at the bottom of a bootstrap well

Hey there, I'm facing an issue with the button positioning. I really need the button to be placed at the bottom of the well, but for some reason, it keeps showing up next to the image instead. This is what's happening: the button is ending up be ...

What are the advantages of using history.push or another method from react-router-dom compared to simply assigning the path to window.location.pathname?

When I need to navigate within my code, I find it more convenient to simply assign the desired path to window.location.pathname. Can this approach have any drawbacks? ...

Difficulty aligning floated buttons in HTML and CSS

I am struggling with aligning the accept/decline buttons on my website. The cancel button is being pushed too far to the right because of the float: right; command I used, and I can't figure out how to properly align it. <?php echo' <html ...

Tips for Passing the correct ID to the modal component in reactJs

Looking for some assistance. The issue I'm encountering is that the modal isn't displaying the correct ID of the data I wish to delete Here is my DataTable.jsx code: import React, { useState, useEffect } from "react"; import axios from ...

Update elements dynamically using JSX

I have an array called data.info that gets updated over time, and my goal is to replace placeholder rendered elements with another set of elements. The default state of app.js is as follows: return ( <Fragment> {data.info.map((index) =&g ...

Disable toolbar focus in TinyMCE

Is there a method to prevent the appearance of the white square known as "Focus to toolbar" in TinyMCE? Clarification: Upon pressing Alt+F10 in TinyMCE, a white square is outlined around a button on the toolbar. This allows navigation among toolbar butto ...

Different methods to avoid using $scope.$watch in a directive when dealing with an undefined variable

As I work on my angularjs application, I find myself utilizing directives for reusable UI elements across different pages. However, I encounter a challenge when a directive depends on a value from a promise. In such cases, I have to employ $scope.$watch al ...

Using NextJS router to navigate and scroll to a specific component on a different page

Imagine I find myself on Page1 and there is a button that triggers a router.push to Page2. However, my dilemma arises when I need Page2 to automatically scroll to a specific component upon loading. Is this even possible? Does anyone have any insights or ...

Design your own custom up and down arrow icons or buttons using CSS styling techniques

Is there a way to create "up and down" control buttons using only CSS and no background image? I attempted to add CSS for arrows in "li.className:after or li.className:before", but it caused the main boxes to move. Check out the Fiddle link to see the is ...

There seems to be a glitch in the functionality of annotations when using annotator.js

Currently, I am utilizing annotator.js to store the range in mysql. The following code fragment is being used for highlighting text within my file: <script src="/js/pdfjs/annotator.js"></script> <script> $(function(){ var annotation ...

Creating a see-through effect for dijit.Dialog as it appears

Utilizing the dijit.Dialog library, I have implemented a Dojo Dialog box that appears on a Rowclick event of a Dojo grid. I am looking to make the Dialog box transparent or reduce its opacity so that the background is visible and it looks visually appealin ...

Choosing the right framework for a web application

Currently, I am at a crossroads when it comes to deciding on the architecture of the web application I will be developing. As part of a small team, I am tasked with working on this project solo while my colleagues focus on other tasks. The front-end of th ...

Establishing a pair of separate static directories within Nest

I am looking to utilize Nest in order to host two static applications. Essentially, I have a folder structure like this: /public /admin /main Within my Nest application, I currently have the following setup: app.useStaticAssets(join(__dirn ...

Issue encountered: Unable to properly increment the value in Ajax/PHP more than once

I am currently in the process of creating a basic voting system, and as a test run I have set up a div with a PHP variable that should increase by 1 each time a button is clicked. The current setup works fine for one click, but fails to continue incrementi ...

How can you implement a switchable theme feature similar to Twitter on your website?

As a beginner programmer and college student with limited design knowledge, I am working on creating a microblogging website similar to Twitter. I noticed that some websites use pre-loaded styles or themes without separate CSS files. I am unsure of how t ...

Icon-enhanced Bootstrap dropdown selection

I have a unique select dropdown using Bootstrap where I want to display icons like the example below: https://i.sstatic.net/dZmTS.png <!DOCTYPE html> <html> <head> <script src="/scripts/snippet-javascript-console.min.js?v=1"& ...

Selecting a dropdown value dynamically after a form submission in ColdFusion using jQuery

I created a basic form with the use of an onload function to populate market values by default. However, I encountered an issue where after selecting a market value from the drop-down list and submitting the form, the selected value does not stay selected ...

What is the best way to remove an element from an array and add a new one?

Here is the array that I am working with: [ { "id": "z12", "val": "lu", "val2": "1", }, { "id": "z13", "val": "la", "val2" ...

Verify the presence of a JSON object within the session storage using JavaScript

I'm currently developing a website where some data is stored within the session. In the initial page, I need to verify if the JSON object already exists in the session. Below is the code snippet that's causing issues: var passedTotal = JSON.par ...

Making a single variable object as opposed to using multiple variables

In order to improve the code structure, I am looking to consolidate all properties into a JavaScript object instead of using multiple variables: // Method 1 // This method gives an error as _inp cannot be accessed by input_value // Uncaught TypeError: Can ...