Not able to access theme in styled component using @emotion/styled
Asked Answered
A

3

8

enter image description here

I'm using @emotion/react to theming and injected theme into it, I'm able to access theme using useTheme into component but not able to access theme into styles using @emotion/styled. Any help please?

//libs
import React from 'react';
import styled from '@emotion/styled';

import StylesProvider from '@mui/styles/StylesProvider';
import { ThemeProvider } from '@emotion/react';


const THEME = {
  primary: 'red'
}

const StyledText = styled('p')`
  color: ${({ theme }) => theme.primary};
`;

function App() {
  return (
    <StylesProvider injectFirst>
      <ThemeProvider theme={THEME}>
        <StyledText>test</StyledText>
      </ThemeProvider>
    </StylesProvider>
  );
}

export default App;



here is sample code
Amby answered 26/10, 2021 at 6:38 Comment(1)
Added sample code in my question.Amby
C
4
  1. Create "emotion.d.ts" and declare your Theme:
import "@emotion/react";

declare module "@emotion/react" {
  export interface Theme {
    color: {
      primary: string;
    }
  }
}
  1. Import Definitely Type file "emotion.d.ts" into "tsconfig.ts":
"typeRoots": ["emotion.d.ts"]
  1. Reload Window and use it like this:
const StyledText = styled('p')`
  color: ${({ theme }) => theme.color.primary};
`;
  1. If you use Mui, let's extends your Theme:
export interface Theme extends ThemeOfMui{}
Chrysa answered 31/12, 2021 at 2:48 Comment(1)
why do you advise to use typeRoot? If typeRoots is specified, only packages under typeRoots will be included. typescriptlang.org/tsconfig#typeRootsDearden
W
2

You need to call it like this. See this section for more detail.

const StyledTextField = styled('div')(({ theme }) => `
  margin: ${theme.spacing(1)};
  background-color: ${theme.palette.primary.main};
  /* ... */
`);

Or you can also use the JS object like in the docs:

const StyledTextField = styled('div')(({ theme }) => ({
  margin: theme.spacing(1),
  backgroundColor: theme.palette.primary.main,
  // ...
}));

Codesandbox Demo

Willetta answered 26/10, 2021 at 6:40 Comment(8)
Its not working, error seems like "Property 'spacing' does not exist on type 'Theme'."Amby
@RupinderpalThind see my updated answer. You can explore the theme object here. It's theme.palette.primary.main, not theme.primary if you want to access the primary colorWilletta
Still not able to access theme here, I'm using typescript, might be that causing any issue?Amby
@RupinderpalThind I don't see where you import the styled function, but you need to import it from @mui/material/styles to be able to use with MUI theme object.Willetta
I'm using it from "@emotion/styled"Amby
@RupinderpalThind that's the problem, when using with MUI, you need to import it from @mui/material/styels instead, or it won't work with MUI theme. You can see from my codesandbox import path.Willetta
you are also setting up theme with material, but I'm using "@emotion/react" to setup theme, this is another method for theming, earlier it was working fine but now I just upgrade everything and its stops working.Amby
@RupinderpalThind this works in my codesandbox. But anyway, if you're using MUI v5, you should use emotion provided by MUI instead, it has more features and is integrated better with existing MUI components. Using both ThemeProviders from emotion and MUI may lead to strange side effect since it's not supported that way.Willetta
B
0

You need to tell Typescript the type of your theme, like so


import '@emotion/react'

declare module '@emotion/react' {
  export interface Theme {
    color: {
      primary: string
      positive: string
      negative: string
    }
  }
}

Otherwise there is no way, that Typescript could be aware of your individual theme properties. It can not infer this from the Context.Provider because the theme property on the context provider is populated at runtime and Typescript types are static (compile time) types.

You can find more information here: emotion with typescript

Boscage answered 27/11, 2022 at 19:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.