0
votes

Often when I use styled-components I define a set of standard components in a globals.js file and export them from there e. g. a standard paragraph style like this:

export const P = styled.p`
    font-size: 1.4rem;
`

Every standard style may come with variations e. g. a standard bold paragraph. I wonder what is the best way to achieve this. I can see several approaches:

Way 1 (pass a bold prop):

const P = styled.p`
    font-weight: ${({fontWeight}) => fontWeight ? fontWeight : 'normal'}
`

Way 2 (create a component with a bold prop but export a separate component that already has the prop):

export const BoldP = props => <P fontWeight="bold">

Way 3 (Define and export all variations individually):

export const P = styled.p`
    font-weight: ${({fontWeight}) => fontWeight ? fontWeight : 'normal'}
`

export const BoldP = styled(P)`
    font-weight: bold
`

This question may seem a little profane, but since this is a very standard interface for a lot of apps, I wonder if there is a "right" way to do this.

1

1 Answers

-1
votes

If you need some standart shared values, like main site color, then you need global styled-components theme.

First create global theme context:

import React, { useEffect, useState } from 'react'
import { deepClone } from '@shared'
import { defaultGeneralTheme } from '../data/defaultGeneralTheme'
import { ThemeProvider, createGlobalStyle } from 'styled-components'

export const ThemeContext = React.createContext(null)

export const ThemeContextProvider = props => {
  const [generalTheme, setGeneralTheme] = useStateRo(deepClone(defaultGeneralTheme))

  return (
    <ThemeContext.Provider value={{ generalTheme, setGeneralTheme }}>
      <ThemeProvider theme={theme}>
        <>
          <GlobalStyle />
          {props.children}
        </>
      </ThemeProvider>
    </ThemeContext.Provider>
  )
}

const GlobalStyle = createGlobalStyle`
  body {  
    line-height: 1.2rem;
    background-color:  ${({ theme }) => theme.secondaryColor};
  } 
`

Then you can create reusable components:

import styled from 'styled-components'
import React, { forwardRef } from 'react'

export const Input = forwardRef(({ ...rest }, ref) => {
  return <StyledInput {...rest} ref={ref} />
})

const StyledInput = styled.input`
  color: ${({ theme }) => theme.textColor};
  width: 100%;
  text-align: center;
`

defaultGeneralTheme example:

export const defaultGeneralTheme = {
    secondaryColor: '#ffffff',
    textColor: '#000000',
}

Don't forget to wrap your top level component with provider:

<ThemeContextProvider><App /></ThemeContextProvider>