DEV Community

Cover image for 🤩 Build Custom Button Component With React JS
Satish Naikawadi
Satish Naikawadi

Posted on • Originally published at satishnaikawadi.me

🤩 Build Custom Button Component With React JS

This is the first part of many 🛎️ from the series Custom UI Components With React. In this post we will see how we can create custom Button component with different props and styles in React JS.

Below is the demo of what we are going to build in this tutorial.

btn-demo.jpg

✔️ Button Component Props

We are going to have several props for this component so that we can have control on it from outside to how we can customize or modify it.The props will be as follows -

  • btnColor - This props will decide the color of the button.
  • labelColor - This props will decide the color of text inside the button. By default it will be white, but depending on your btnColor you can change it to have right contrast.
  • onClick - This will be a onClick handler present on button.
  • type - This prop will decide the styling of the button. It will have the value either one of outline | block | rounded. If this prop is not passed button will have default styling.
  • style - This prop will have any custom styling you want to give Button component from outside.
  • disabled - This prop will decide if the button is in active state or not.

🃏Basic Styling Of Button

We will give button some basic styling. Here we will create button.module.css file and then we will add btn class to it for giving some basic styles to our button as follows.


/* button.module.css */

.btn {
    font-family: 'Ubuntu', sans-serif;
    position: relative;
    font-weight: 400;
    font-size: 1.3rem;
    line-height: 2;
    height: 50px;
    transition: all 200ms linear;
    border-radius: 4px;
    width: 240px;
    letter-spacing: 1px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    align-self: center;
    border: none;
    cursor: pointer;
    box-shadow: 0 12px 35px 0 rgba(16, 39, 112, .25);
    outline: 0;
    text-transform: capitalize;
}
Enter fullscreen mode Exit fullscreen mode

💠 Creating Button Functional Component

Now we will create a Button.js files in which we will create out custom Button Component. In this file we will import styles from our button.module.css file . Here we will return a basic HTML button element and we will add btn class to it from styles.We will destructure the all props.

//Button.js

import React from 'react';
import styles from './button.module.css';

const Button = ({ children, onClick, btnColor = 'teal', labelColor, disabled, type, style, ...props }) => {
    return (
        <button
            className={styles.btn}
        >
            {children || 'label'}
        </button>
    );
};

export default Button;

Enter fullscreen mode Exit fullscreen mode

Now in this Button.js file we will create some styles objects for different types of buttons.


//Button.js

    const commonStyles = {
        backgroundColor : btnColor,
        color           : labelColor || 'white'
    };
    const outlineStyles = {
        border          : `1px solid ${btnColor}`,
        color           : btnColor,
        backgroundColor : 'white'
    };
    const outlineHoverStyle = {
        color           : labelColor || 'white',
        backgroundColor : btnColor
    };

    const roundedStyle = {
        backgroundColor : btnColor,
        color           : labelColor || 'white',
        borderRadius    : '25px'
    };
    const disabledStyle = {
        cursor          : 'default',
        backgroundColor : btnColor,
        color           : labelColor || 'white',
        opacity         : 0.4
    };
    const blockStyles = {
        width  : '95%',
        margin : '0 auto'
    };
Enter fullscreen mode Exit fullscreen mode

Here we have common styles depending on btnColor which will be added to every type of button . On the other hand all the other styles will be added conditionally depending on the type of button. Here note that for outline type we have two cases - first is default outlineStyles which will be added when type of button is outline and the other case is when we hover over the button.

So to track the hover state we will create state hover with useState() react hook with which we will add hover style conditionally. With Javascript Event Handlers onMouseEnter and onMouseLeave we will toggle our hover state.

Now we will add a simple switch statement in javascript to conditionally render the styles depending on the type of button.


//Button.js
    let btnStyle;
    switch (type) {
        case 'rounded':
            btnStyle = roundedStyle;
            break;
        case 'block':
            btnStyle = blockStyles;
            break;
        case 'outline':
            if (hover) {
                btnStyle = outlineHoverStyle;
            }
            else {
                btnStyle = outlineStyles;
            }
            break;
        default:
            btnStyle = {
                backgroundColor : btnColor,
                color           : labelColor || 'white'
            };
            break;
    }


Enter fullscreen mode Exit fullscreen mode

And that's it , Now we will just add this btnStyle along with any style passed from props onto button and we will also add disabled style if button has disabled prop. So our final code will look like follows -


//Button.js

import React, { useState } from 'react';
import styles from './button.module.css';

const Button = ({ children, onClick, btnColor = 'teal', labelColor, disabled, type, style, ...props }) => {
    const [
        hover,
        setHover
    ] = useState(false);
    const toggleHover = () => {
        setHover(!hover);
    };
    const commonStyles = {
        backgroundColor : btnColor,
        color           : labelColor || 'white'
    };
    const outlineStyles = {
        border          : `1px solid ${btnColor}`,
        color           : btnColor,
        backgroundColor : 'white'
    };
    const outlineHoverStyle = {
        color           : labelColor || 'white',
        backgroundColor : btnColor
    };

    const roundedStyle = {
        backgroundColor : btnColor,
        color           : labelColor || 'white',
        borderRadius    : '25px'
    };
    const disabledStyle = {
        cursor          : 'default',
        backgroundColor : btnColor,
        color           : labelColor || 'white',
        opacity         : 0.4
    };
    const blockStyles = {
        width  : '95%',
        margin : '0 auto'
    };
    let btnStyle;
    switch (type) {
        case 'rounded':
            btnStyle = roundedStyle;
            break;
        case 'block':
            btnStyle = blockStyles;
            break;
        case 'outline':
            if (hover) {
                btnStyle = outlineHoverStyle;
            }
            else {
                btnStyle = outlineStyles;
            }
            break;
        default:
            btnStyle = {
                backgroundColor : btnColor,
                color           : labelColor || 'white'
            };
            break;
    }
    return (
        <button
            style={

                    disabled ? { ...commonStyles, ...btnStyle, ...disabledStyle, ...style } :
                    { ...commonStyles, ...btnStyle, ...style }
            }
            onMouseEnter={toggleHover}
            onMouseLeave={toggleHover}
            {...props}
            type="button"
            onClick={

                    !disabled ? onClick :
                    () => {}
            }
            className={styles.btn}
        >
            {children || 'button'}
        </button>
    );
};

export default Button;

Enter fullscreen mode Exit fullscreen mode

Here you can see live demo and interact with this component.
Hope you inderstand this tutorial. For more tutorials like these plz visit my personal blog satishnaikawadi.me Thank You for reading 😇.

Top comments (1)

Collapse
 
jaloplo profile image
Jaime López

Why not creating an specific button for each style or type instead of having so many linea of code making difficult to read? I think, applying Single Responsibility principle here would make this component to be several of them and another as the manager. What do you think???