Locked Video

Please log in or buy the course to watch

Buy Now

Migrating Emotion

Initial Emotion Styled Component:

StyledStatusLabel uses Emotion, which incorporates dynamic prop-based styling and accesses a theme object.

interface StyledStatusLabelProps {
  isPrompt?: boolean
  isMinimized?: boolean
}

const minimizedStyles = (theme: EmotionTheme): CSSObject => ({
  opacity: 0,
  padding: theme.spacing.none,
  margin: theme.spacing.none,
  maxWidth: 0,
  minWidth: 0,
  border: 0,
})

export const StyledStatusLabel = styled.label<StyledStatusLabelProps>(
  ({ isPrompt, isMinimized, theme }) => ({
    fontSize: theme.fontSizes.sm,
    color: isPrompt ? theme.colors.accentText : theme.colors.mutedText,
    textTransform: isPrompt ? 'none' : 'uppercase',
    margin: `0 0 0 ${theme.spacing.lg}`,
    whiteSpace: 'nowrap',
    maxWidth: '20rem',
    backgroundImage: `linear-gradient(90deg, ${theme.colors.accentBg}, #fffd80)`,
    borderRadius: isPrompt ? theme.radii.md : undefined,
    transition: `opacity 200ms ease-out 0s,
    clip 200ms ease-out 0s, min-width 200ms ease-out 0s,
    max-width 200ms ease-out 0s, padding 200ms ease-out 0s`,
    ...(isMinimized ? minimizedStyles(theme) : {}),
  }),
)

Identify Theme Tokens

Tokens such as spacing.none, fontSizes.sm, colors.accentText, colors.mutedText, colors.accentBg, spacing.lg, and radii.md are accessed from the theme object in Emotion.

Migrate to Panda CSS

Define a corresponding Panda theme in the panda.config file to include these token values under the tokens object.

 extend: {
      tokens: {
        colors: {
          accentText: { value: '#6644ff' },
          mutedText: { value: '#45445f' },
          accentBg: { value: '#FA44ff' }
        },
        fontSizes: {
          sm: { value: '12px' }
        },
        spacing: {
          none: { value: '0px' }
        },
        radii: {
          md: { value: '12px' }
        }
      }
    }

Create Panda CSS Recipe

Translate the Emotion styled component into a recipe starting with the base styles.

const statusLabelProps = cva({
  base: {
    marginLeft: 'lg',
    whiteSpace: 'nowrap',
    maxWidth: '20rem',
    fontSize: 'sm',
    transition: `opacity 200ms ease-out 0s,
    clip 200ms ease-out 0s, min-width 200ms ease-out 0s,
    max-width 200ms ease-out 0s, padding 200ms ease-out 0s`,
  },
})

Dynamic Variants

Implement dynamic variants (isMinimized, isPrompt) as boolean variants in eplacing theme access with token references.

const statusLabelProps = cva({
  base: {
    // base styles
  },
  variants: {
    isMinimized: {
      true: {
        opacity: 0,
        padding: 'none',
        margin: 'none',
        maxWidth: 0,
        minWidth: 0,
        border: 0,
      },
    },
    isPrompt: {
      true: {
        color: 'accentText',
        textTransform: 'none',
        borderRadius: 'md',
      },
      false: {
        color: 'mutedText',
        textTransform: 'uppercase',
      },
    },
  },
})

Handle Background Image

Convert dynamic background image styles by interpolating theme values into a CSS variable and defining the variable as a token.

base: {
  "--gradient-end": 'colors.accentBg',
  backgroundImage: `linear-gradient(90deg, var(--gradient-end), #fffd80)`
}