Search code examples
javascriptcssreactjsnext.jsemotion

I can't import emotion js style with dynamic variable


I have a webpage that looks like this:
enter image description here

This is my _app.tsx file:

import '../styles/globals.css'
import type { AppProps } from 'next/app'
import { createTheme } from '@arwes/design'
import { ThemeProvider, Global, css } from '@emotion/react'
import { globalStyles } from '../shared/styles.js'

function MyApp({ Component, pageProps }: AppProps) {
  const theme = createTheme();
  return (
    <ThemeProvider theme={theme}>
      {globalStyles}
      <div style={{
          marginBottom: theme.space(2),
          borderBottom: `${theme.outline(2)}px solid ${theme.palette['primary'].main}`,
          padding: theme.space(2),
          backgroundColor: theme.palette.neutral.elevate(2),
          textShadow: `0 0 ${theme.shadowBlur(1)}px ${theme.palette['primary'].main}`,
          color: theme.palette['primary'].main
      }}>
        Futuristic Sci-Fi UI Web Framework
      </div>

      <Component {...pageProps} />
    </ThemeProvider>
  )
}

export default MyApp

And this is shared/styles.js:

import { css, Global, keyframes } from '@emotion/react'
import styled from '@emotion/styled'

export const globalStyles = (
  <Global
    styles={css`
      html,
      body {
        margin: 0;
        background: papayawhip;
        min-height: 100%;
        font-size: 24px;
      }
    `}
  />
)

export const blueOnBlack = (theme) => css`
  marginBottom: ${theme.space(2)};
  borderBottom: ${theme.outline(2)}px solid ${theme.palette['primary'].main};
  padding: ${theme.space(2)};
  backgroundColor: ${theme.palette.neutral.elevate(2)};
  textShadow: 0 0 ${theme.shadowBlur(1)}px ${theme.palette['primary'].main};
  color: ${theme.palette['primary'].main};
`

Notice that blueOnBlack is an attempt to put the Futuristic Sci-Fi UI Web Framework style into its own importable variable.

The problem is that when I put blueOnBlack into the _app.tsx as the style for the Futuristic Sci-Fi UI Web Framework div tag, it fails.

This is _app.tsx with blueOnBlack imported:

import '../styles/globals.css'
import type { AppProps } from 'next/app'
import { createTheme } from '@arwes/design'
import { ThemeProvider, Global, css } from '@emotion/react'
import { globalStyles, blueOnBlack } from '../shared/styles.js'

function MyApp({ Component, pageProps }: AppProps) {
  const theme = createTheme();
  return (
    <ThemeProvider theme={theme}>
      {globalStyles}
      <div style={blueOnBlack(theme)}>
        Futuristic Sci-Fi UI Web Framework
      </div>

      <Component {...pageProps} />
    </ThemeProvider>
  )
}

export default MyApp

The resulting webpage looks like this,
enter image description here

It's almost right... but it dropped the background color. Why is it different?


Solution

  • I changed shared/styles.js from:

    import { css, Global, keyframes } from '@emotion/react'
    import styled from '@emotion/styled'
    
    export const globalStyles = (
      <Global
        styles={css`
          html,
          body {
            margin: 0;
            background: papayawhip;
            min-height: 100%;
            font-size: 24px;
          }
        `}
      />
    )
    
    export const blueOnBlack = (theme) => css`
      marginBottom: ${theme.space(2)};
      borderBottom: ${theme.outline(2)}px solid ${theme.palette['primary'].main};
      padding: ${theme.space(2)};
      backgroundColor: ${theme.palette.neutral.elevate(2)};
      textShadow: 0 0 ${theme.shadowBlur(1)}px ${theme.palette['primary'].main};
      color: ${theme.palette['primary'].main};
    `
    

    to this:

    import { css, Global, keyframes } from '@emotion/react'
    import styled from '@emotion/styled'
    
    export const globalStyles = (
      <Global
        styles={css`
          html,
          body {
            margin: 0;
            background: papayawhip;
            min-height: 100%;
            font-size: 24px;
          }
        `}
      />
    )
    
    export const blueOnBlack = (theme) => styled.div={
      marginBottom: theme.space(2),
      borderBottom: theme.outline(2) + 'px solid' + theme.palette['primary'].main,
      padding: theme.space(2),
      backgroundColor: theme.palette.neutral.elevate(2),
      textShadow: '0 0 ' + theme.shadowBlur(1) + 'px ' + theme.palette['primary'].main,
      color: theme.palette['primary'].main
    }
    

    And then it ran and gave me the correct styling including the black background on the text. Notice that I'm using styled.div instead of css