Search code examples
reactjstypescriptstyled-componentscss-in-js

Extend a Styled Component from a different file


What I'm trying to achieve is to be able to add extra styling to my Button.tsx(essentially extending the styles) when using this component in different files. As you can see in my Button.tsx I have defined some default styles I would like the button to have, but as I use more buttons across my app, I might want to change the background or color, etc.

One thing I could do is this:

Example of not what I want to do:

import React from 'react'
import styled from 'styled-components'

interface IButton = {
  children: string
}

export default function Button({ children }: IButton) {
  const Button = styled.button`
    padding: 1em;
    background: #ccc;
    border-radius: 5px;
  `
  const RedButton = styled(Button)`
    // Inherits all of the styles from Button.
    background: red;
  `

  return (
    <Button>{children}</Button
  )
}

This example will inherit my Button styles and then allows me to extend. The problem with this solution is, if I decide to add more buttons, I will always have to come back to this file and then add the different variants, which could start to make this file get pretty chunky and messy.

Ideally I would like to extend my <Button> from the App.tsx file, or which ever file I'm using my <Button> in.


How could I adjust the code below to achieve this?

Button.tsx

import React from 'react'
import styled from 'styled-components'

interface IButton = {
  children: string
}

export default function Button({ children }: IButton) {
  const Button = styled.button`
    padding: 1em;
    background: #ccc;
    border-radius: 5px;
  `

  return (
    <Button>{children}</Button
  )
}

App.tsx

import React from 'react'
import styled from 'styled-components'

export default function App() {
  return (
    {/* This button would render with the default styles from Button.tsx */}
    <Button>Button One</Button>
    {/* This button would render with extended styles, a blue background for example */}
    <Button>Button Two</Button>
  )
}

Solution

  • In your App.tsx you can do the same:

      const BlueButton = styled(Button)`
        background: blue;
      `
    

    what styled-components does is it creates a class with background blue and pass it to your Button. so in your Button.tsx you need to accept the css class

    export default function Button({ className, children }: IButton) {
      const Button = styled.button`
        padding: 1em;
        background: #ccc;
        border-radius: 5px;
      `
    
      return (
        <Button className={className}>{children}</Button
      )
    }
    

    Edit another way to do is to export the style like this

    const BaseStyles = css`
        padding: 1em;
        background: #ccc;
        border-radius: 5px;
    `
    
    const BaseButton = styled.button`
        ${BaseStyles}
    `
    

    Then later override the styles

     const BlueButton = styled.button`
        ${BaseStyles}
        background: blue;
      `