Reusable Button with ReactJS + Typescript + Styled-components
Tags: react, typescript, styledcomponents
Published: 2021-08-02 15:29:41

Welcome, here's a guide teaching you how to create a simple and powerful reusable button component using ReactJS, Typescript and Styled-components.

![Example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/12wp1xl7aera3q2to31f.png)

*Observation: I created this post considering that you know the basics of ReactJS, typescript and styled-components. If you see anything wrong, please tell me!*

Let's start creating two files, `index.tsx` and `styles.ts`.

Inside `index.tsx` let's create a functional component called `Button` and pass the styled-component `<Container>` inside it:

```react
import React from "react";
import { Container } from "./styles";

export const Button = () => {
  return (
    <Container>
    </Container>
  )
};
```

In order to make this component reusable in different situations, we have to create some properties for it. In this case, let's create a `type` called `ButtonProps`, and pass these props:

```react
export type ButtonProps = {
  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void; // to handle onClick functions
  children?: React.ReactNode; // make the component able to receive children elements
  color?: 'primary' | 'secondary'; // two styling options (you can create as many as you want)
  disabled?: boolean; // make the button disabled or not
};
``` 

Then, let's call these props in our `Button` component, using props destructuring and see what we've done so far:

```react
import React from "react";
import { Container } from "./styles";

export type ButtonProps = {
  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void; // to handle onClick functions
  children?: React.ReactNode; // make the component able to receive children elements
  color?: "primary" | "secondary"; // two styling options
  disabled?: boolean; // make the button disabled or not
};

export const Button = ({
  onClick,
  children,
  color = "primary",
  disabled,
}: ButtonProps) => {
  return (
    <Container onClick={onClick} color={color} disabled={disabled}>
      {children}
    </Container>
  );
};
```
Now, it's time to set the styles properties, let's go to our file `styles.ts`, import styled and { css } from styled-components and { ButtonProps } from `index.tsx`:

```react
import styled, { css } from "styled-components";
import { ButtonProps } from ".";
```

To set different styles to our Button component, let's create a const called `COLOR` and pass some styles with the `css` we imported to encapsulate it, using the same name we put on the color property in `ButtonProps`:

```react
const COLOR = {
  primary: css`
    color: #fff;
    background: linear-gradient(#3f3cfe, #e943d5);
  `,
  secondary: css`
    color: #000;
    background: linear-gradient(#c7c7d2, #bcbaba);
  `,
};
```

And a const called `DISABLED`, to style the Button when it's disabled:

```react
const DISABLED = css`
  cursor: not-allowed;
  background: #d4d4d4;
  color: #f5f5f5;
`;
```

Now, let's pass some default styles to the `Button` Container and call the `ButtonProps` type, in order to use the properties:

```react
export const Container = styled.button<ButtonProps>`
  padding: 10px 15px;
  cursor: pointer;
  border: none;
  border-radius: 50px;
  font-weight: 500;
  outline: none;
  transition: all 0.2s;

  ${(props) => props.color && COLOR[props.color]}
  ${(props) => props.disabled && DISABLED}
`;
```

As you can see above, we have to pass some arrow functions to call the properties and match it with our encapsulated css (`const COLOR and const DISABLED`).

Now, we have a powerful **reusable button component!**

You can see the results at the beginning of the article!

Thanks for reading this content, I hope it helps you in some way and, if you notice something wrong, feel free to help me leaving a comment bellow or find me on [twitter](https://twitter.com/thehuferr) !

You can also find me at:

[Github](https://github.com/huferr)
[Linkedin](https://www.linkedin.com/in/hugo-ferreira-it/)