What is the best way to incorporate styled components and interpolations using emotion theming?

I've been building a React web application with a dynamic theme feature using the emotion-theming library. This allows users to switch between different environments, each with its own unique theme. To achieve this, I created my own CustomThemeProvider which dynamically changes the theme based on the selected environment. Here's the code snippet:

export interface CustomThemeContextValue {
    customTheme?: Theme;
    setCustomTheme: (theme: Theme) => void;
};

const CustomThemeContext = React.createContext<CustomThemeContextValue>({
    customTheme: undefined,
    setCustomTheme: (theme) => { }
});

interface CustomThemeProviderProps {

}

export const CustomThemeProvider: FC<CustomThemeProviderProps> = (props) => {
    const [customTheme, setCustomTheme] = useState<Theme>(theme);

    const context: CustomThemeContextValue = React.useMemo(() => ({
        customTheme,
        setCustomTheme
    }), [customTheme, setCustomTheme]);

    return (
        <CustomThemeContext.Provider value={context}>
            <ThemeProvider theme={customTheme} {...props} />
        </CustomThemeContext.Provider>
    );
};

export const useCustomTheme = () => {
    const context = React.useContext(CustomThemeContext);
    if (!context) {
        throw new Error('useCustomTheme must be used within a CustomThemeProvider');
    }

    return context;
};

The provider is implemented at the root level as shown below:

const Root = () => {
    return (
        <StrictMode>
            <CustomThemeProvider>
                <Normalize />
                <Global styles={globalStyle} />
                <App />
            </CustomThemeProvider>
        </StrictMode>
    );
};

This setup works well, and I can access the theme in function components using the emotion useTheme hook like this:

const theme: Theme = useTheme();

However, I'm now trying to figure out how to extract the theme from the emotion ThemeProvider and utilize it in specific scenarios. Can I use it in a context like this example below?

export const style: Interpolation = {
    cssProp: value
};

Or can I apply it in a context where styled.button comes into play, such as:

const Button: FC<HTMLProps<HTMLButtonElement> & ButtonProps> = styled.button([]);

Additionally, can I leverage it within the emotion/core method css() like demonstrated here?

const style = css({
    cssProp: value
});

Finding concrete answers to these queries through Google has proven challenging, so any assistance from fellow developers would be greatly appreciated.

Answer №1

After much searching, I have finally discovered a solution to my query and I am eager to share it with everyone since this information is not easily found. Here is the solution:

Instead of using Interpolation, you can utilize InterpolationWithTheme like so:

import { InterpolationWithTheme } from '@emotion/core';

export const style: InterpolationWithTheme<Theme> = (theme) => ({
    cssProp: theme.value
});

This method allows you to extract the theme from the ThemeProvider.

When incorporating styled components, you can implement it as follows:

const Button: FC<HTMLProps<HTMLButtonElement> & ButtonProps>
    = styled.button(({ theme }: any) => ([
    {
        cssProp: theme.value
    }
]);

Finally, if you wish to use the css() function with the themeProvider, you will need to substitute it with InterpolationWithTheme in order for it to function similarly to the first example provided in this answer.

These solutions were arrived at through a combination of referencing the emotionjs documentation and examining the emotionjs types/interfaces.

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

What is the best way to retrieve a string from a URL?

Is there a way to extract only a specific string from a URL provided by an API? For instance: I'm interested in extracting only: photo_xxx-xxx-xxx.png Any suggestions on how to split the URL starting at photo and ending at png? ...

Is it possible to enable CSS margins to collapse across a fieldset boundary in any way?

One interesting CSS behavior is that adjacent vertical margins typically collapse into one another. In other words, the space between elements will be equal to the larger margin instead of the sum of both margins. Interestingly, fieldset elements do not f ...

Receiving an issue while trying to launch a React application using npm start

Every time I try to create a new React folder using npx create-react-app test, I encounter an issue where npm start does not function properly and displays the following error message in the terminal: > <a href="/cdn-cgi/l/email-protection" class="_ ...

What is the reason for Typescript's compatibility with WScript?

Recently, I decided to install Typescript in order to get WScript intellisense in VScode. After setting it up, I was able to achieve the desired intellisense. However, I encountered an issue when compiling a Typescript file containing a WScript method usin ...

Tips for organizing multiple TextField components within a Grid container using Material-UI

I utilize Material-UI for my front-end design needs. I have a query related to the Grid layout feature. My goal is to include 7 TextField elements, but they are appearing overlapped. When I modify all 7 TextField elements from xs={1} to xs={2}, they become ...

Having trouble locating an element with Xpath using Selenium Web Driver? Any suggestions for a more efficient way to find this elusive element?

Selenium Web Driver- I'm having trouble locating an element using Xpath. Any suggestions on a better way to locate the element below? <div class="gwt-Label">Declined</div> I attempted to retrieve the text in the element using the followi ...

Effortless gliding towards the left

I am looking to incorporate buttons for smooth horizontal scrolling within my container. Currently, the functionality is in place but I would like to enhance its smoothness. How can I improve the scrolling experience? Should I consider using a different p ...

AngularJS causing issues with Materializecss dropdown menu operation

I'm currently working on a web application using Materializecss and AngularJS for the front-end. However, I've encountered an issue with the dropdown menu component of Materialize not functioning as expected. Here's an example of the dropdo ...

Issue with triggering (keyup.enter) in Angular 8 for readonly HTML input elements

My goal is to execute a function when the user presses Enter. By setting this input as readonly, my intention is to prevent the user from changing the value once it has been entered. The value will be populated from a popup triggered by the click attribut ...

Unable to display background image on Webpage due to blank page issue while uploading it with HTML and CSS

I've been attempting to build a webpage with an image as the background, but I seem to be facing some issues. Instead of seeing the desired image, all I get is a blank white page. The folder named "images" is located in the same directory as my HTML a ...

Leveraging both the spread operator and optional fields can improve the productivity and readability of your

Imagine you have an object with a mandatory field that cannot be null: interface MyTypeMandatory { value: number; } Now, you want to update this object using fields from another object, but this time with an optional field: interface MyTypeOptional ...

Exploring the power of React Leaflet and the exciting possibilities of React Leaflet

I'm currently in the process of implementing the draw functions on a leaflet map. I started off by creating a new app with just react-leaflet installed. I used npx create-react-app and installed the following packages: npm install react react-dom lea ...

Analyzing an array to identify specific elements provided as a parameter

Below are 2 react functions I have created: const hasPermission = (permission: string) => { if (user?.permissionsEnabled === false) { return true } return permissions.includes(permission) || false } The next ...

typescript max recursion depth restricted to 9 levels

After countless attempts, I finally managed to create a generic type that provides me with all possible combinations of JSON key lists and values. Additionally, I have developed a method to limit the recursion within this type. type EditAction<T,P exten ...

The React Nested Loop Query: Maximizing Efficiency in Data

Learning React has been a challenge for me, especially when comparing it to XML/XPath. In this scenario, I have two arrays simplified with basic string properties... customerList: Customer[] export class Customer { id: string = ""; firstnam ...

Navigate only within the tbody section of the Material UI Table by scrolling

Utilizing the material-ui Table component to build a table with a sticky header presents a challenge. The default behavior is for the scroll to encompass both the thead and tbody of the table. However, I specifically require the scroll functionality to be ...

Issue with Angular: Child component not receiving data after successful parent component call

I'm currently working with a parent and child component setup. Within the child component, I have a button configured like this: //child.component.html <button mat-raised-button [disabled]="!form.valid || submitButtonDisable" type = 'Submi ...

What is the best way to refresh a Component upon sending data to the server?

I'm in the process of developing a cross-platform application. I have a TabView Component that needs to update a tab after sending data to the server. During the initialization (ngOnInit) phase, I dynamically set the content of my tab. However, when I ...

RTK Query is unable to assign a tag ID

I'm currently setting up RTK Query and facing some challenges with defining a tag-id. Despite my efforts, I can't seem to get the "Timeseries" tag to function properly with an id. Below is the API configuration: export type GetTimeseriesProps = ...

Handling Click and Mouse Events with React [react-sortable-hoc, material-ui, react-virtualized]

I have come across an interesting example that I would like to share with you. Check out this live working example on Stackblitz When the delete button on the red bin icon is pressed, the onClick event handler does not get triggered (sorting happens inst ...