DEV Community

Eduardo Henrique Gris
Eduardo Henrique Gris

Posted on

Styled-components in React with Typescript

Introduction

Styled-components is a styling library for React applications that provides flexibility in defining styles based on received props. The goal of this article is to introduce how the library works, how to define types for the passed props, and how to extend styles.

Setup

Adding the lib to the app:

yarn add styled-components --dev
Enter fullscreen mode Exit fullscreen mode

React structure

The definition of styling using styled-components follows the following format:

import styled from "styled-components";

const StyledComponent = styled.htmlElement`
  // css properties
`;

const Component = () => (
  <StyledComponent />
);

export default Component;
Enter fullscreen mode Exit fullscreen mode

The above contains the following elements:

  • import styled: necessary import for styling using the lib
  • StyledComponent: where the css properties of the Component are defined, using the imported styled
  • htmlElement: where the type of html element is defined, such as div, button...

React example

Below, I'll provide a simple example for a text component (with fewer props to keep the example concise). The idea is to apply the structure mentioned above and demonstrate how prop passing works:

import styled from "styled-components";

const StyledText = styled.span`
  color: ${(props) => (props.$color ? props.$color : "#000")};
  font-size: ${(props) => (props.$fontSize ? props.$fontSize : "16px")};
`;

const Text = ({
  children,
  color,
  fontSize,
}) => (
  <StyledText
    $color={color}
    $fontSize={fontSize}
  >
    {children}
  </StyledText>
);

export default Text;
Enter fullscreen mode Exit fullscreen mode

For the Text component, three types of props can be passed: children, color, and fontSize. The first defines the text to be displayed, while the second and third relate to styling. Since only the last two are related to styling, only they are passed as props to StyledText. In this case, the props are prefixed with a $ to avoid console errors caused by passing props for a DOM element that doesn't recognize them. The html element corresponding to the component is defined as styled.span.
Inside the const StyledText, the properties are defined based on the passed props. If $color is provided, it sets the color; otherwise, it defaults to #000. If $fontSize is provided, it sets the font size; otherwise, it defaults to 16px.
Thus, the component is defined using the lib. In the example, the name StyledText is used, but the name is customizable.

React structure with Typescript

Starting from the structure defined above in React structure, here is the format with the type definitions:

import styled from "styled-components";

interface StyledComponentType {
  // types definition
}

const StyledComponent = styled.htmlElement<StyledComponentType>`
  // css properties
`;

const Component = () => (
  <StyledComponent />
);

export default Component;
Enter fullscreen mode Exit fullscreen mode

Above, the interface is defined right after styled.htmlElement, with the name StyledComponentType. Inside the interface StyledComponentType, the types are defined.

React with Typescript example

Now, I'll add the types definiton to the example present in React example:

import styled from "styled-components";

interface StyledTextProps {
  $color?: string;
  $fontSize?: string;
}

interface TextProps {
  children: React.ReactNode;
  color?: string;
  fontSize?: string;
}

const StyledText = styled.span<StyledTextProps>`
  color: ${(props) => (props.$color ? props.$color : "#000")};
  font-size: ${(props) => (props.$fontSize ? props.$fontSize : "16px")};
`;

const Text = ({
  children,
  color,
  fontSize,
}: TextProps) => (
  <StyledText
    $color={color}
    $fontSize={fontSize}
  >
    {children}
  </StyledText>
);

export default Text;
Enter fullscreen mode Exit fullscreen mode

In the example above, the types for the component is defined in TextProps, and those from styled-components in <StyledTextProps>, based on the props passed in each place.

Extending styles

Another feature that the lib allows is creating a component that inherits the styling from another component. This is useful when you want similar components that differ slightly from each other but don't want to give too much flexibility for the property that differs by passing props.

import styled from "styled-components";

const StyledComponentA = styled.htmlElement`
  // A css properties
`;

const StyledComponentB = styled(StyledComponentA)`
  // B css properties
`;

const Component = () => (
  <>
    <StyledComponentA />
    <StyledComponentB />
  </>
);

export default Component;
Enter fullscreen mode Exit fullscreen mode

Above, styledComponentB inherits the properties defined for styledComponentA, and any properties written inside StyledComponentB will add more properties. If there is a property of the same type that styledComponentA already defines, it will overwrite it.

Extending styles example

Now, I will present an example of style extension with two buttons, which differ in terms of their padding, but this property is not flexible, each one has it pre-defined.

import styled from "styled-components";

const StyledButtonA = styled.button`
  border: 2px solid #000;
  cursor: pointer;
  padding: 10px 12px;
`;

const StyledButtonB = styled(StyledButtonA)`
  padding: 15px 20px;
`;

const Buttons = () => (
  <>
    <StyledButtonA>ButtonA</StyledButtonA>
    <StyledButtonB>ButtonB</StyledButtonB>
  </>
);

export default Buttons;
Enter fullscreen mode Exit fullscreen mode

In the example above, StyledButtonA has three properties defined: border, cursor and padding. StyledButtonB is using the same properties because it is extending the styles from StyledButtonA via styled(StyledButtonA), except for the padding, as a different one is defined inside StyledButtonB.

Conclusion

The idea of this article was to explain how the styled-components lib works in React apps with TypeScript, covering its usage, the definition of types related to it and the part about style extension.
For those who want to learn more about the library, here is the link to the documentation.

Top comments (0)