Skip to content

Instantly share code, notes, and snippets.

@tanvirraj
Created August 31, 2022 04:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tanvirraj/54ccf7ed27085057710df22bcc103690 to your computer and use it in GitHub Desktop.
Save tanvirraj/54ccf7ed27085057710df22bcc103690 to your computer and use it in GitHub Desktop.
// @flow
import React, { PureComponent } from "react";
import styles from "./Button.module.scss";
import cx from "classnames";
import { Link } from "react-router-dom";
import { Button as AntDesignButton } from "antd";
import { type Node } from "react";
/**
* Enum with all the button types.
* @readonly
* @enum {string}
*/
const ButtonType = Object.freeze({
PRIMARY: "primary",
SECONDARY: "secondary",
TERTIARY: "tertiary",
DEFAULT: "default"
});
/**
* Enum with all the button sizes.
* @readonly
* @enum {string}
*/
const ButtonSize = Object.freeze({
XSMALL: "xsmall",
SMALL: "small",
MEDIUM: "medium",
LARGE: "large",
DEFAULT: "default"
});
/**
* Enum with all the button shapes.
* @readonly
* @enum {string}
*/
const ButtonShape = Object.freeze({
CIRCLE: "circle",
ROUND: "round"
});
/**
* Enum with all the icon positions.
* @readonly
* @enum {string}
*/
const IconPosition = Object.freeze({
LEFT: "left",
RIGHT: "right"
});
type Props = {
/** Text shown as button title */
text?: string | Node,
/** Link associated with the button */
link?: string,
/** Icon shown before or after button text */
icon?: Node,
/** Used to set button status if its disabled or not */
disabled?: boolean,
/** Class name attached with the button component */
className?: any,
/** Type of the button ex- Primary or Secondary */
type: $Values<typeof ButtonType>,
/** Size of the button ex- small or large (default: large) */
size: $Values<typeof ButtonSize>,
/** Used to set icon position ex- left or right (default: left) */
iconPosition: $Values<typeof IconPosition>,
/** Set to true if the button should not have a border (default: has border) */
borderless?: boolean,
/** Set to true if the button should have a transparent background (default: has background color) */
transparent?: boolean,
/** Call the function when user clicks the button */
onClick?: Function,
loading?: boolean
};
/**
* Custom Ant Design button
*/
class Button extends PureComponent<Props> {
static defaultProps = {
type: ButtonType.DEFAULT,
size: ButtonSize.DEFAULT,
iconPosition: IconPosition.LEFT,
loading: false
};
render() {
const {
text,
link,
icon,
type,
size,
disabled,
iconPosition,
className,
borderless,
transparent,
onClick,
loading,
...rest
} = this.props;
const classNames = cx(
{
[styles.primaryButton]: type === ButtonType.PRIMARY,
[styles.secondaryButton]: type === ButtonType.SECONDARY,
[styles.tertiaryButton]: type === ButtonType.TERTIARY,
[styles.defaultButton]: type === ButtonType.DEFAULT,
[styles.xsmallButton]: size === ButtonSize.XSMALL,
[styles.smallButton]: size === ButtonSize.SMALL,
[styles.mediumButton]: size === ButtonSize.MEDIUM,
[styles.largeButton]: size === ButtonSize.LARGE,
[styles.borderless]: borderless,
[styles.transparentBg]: transparent
},
className
);
const button = (
<AntDesignButton
className={classNames}
disabled={disabled}
onClick={onClick}
loading={loading}
{...rest}
>
<span className={styles.buttonContent}>
{!loading && iconPosition === IconPosition.LEFT && icon}
{text && (
<span
className={cx({
[styles.iconLeft]: icon && iconPosition === IconPosition.LEFT,
[styles.iconRight]: icon && iconPosition === IconPosition.RIGHT
})}
>
{text}
</span>
)}
{!loading && iconPosition === IconPosition.RIGHT && icon}
</span>
</AntDesignButton>
);
return link ? <Link to={link}>{button}</Link> : button;
}
}
export default Button;
export { ButtonType, ButtonSize, ButtonShape, IconPosition };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment