import type { FunctionComponent, MouseEventHandler, ReactElement } from "react";
import BaseProps from "../types";
/**
* @interface
* @implements BaseProps
* @property text {string} The text to display on the button.
* @property [icon] {ReactElement} The icon to display on the button.
* @property [type] {"success" | "info" | "warning" | "error"} The type (in terms of style) of button.
* @property [outlined=false] {boolean} Whether the button is outlined or filled in. Filled in by default.
* @property [disabled=false] {boolean} Whether to disable the button.
* @property [loading=false] {boolean} Whether to show a loading state for the button.
*
* @author Giancarlo Pernudi Segura <gino@neuralberta.tech>
*/
interface BaseButtonProps extends BaseProps {
text: string;
icon?: ReactElement;
type?: "success" | "info" | "warning" | "error";
outlined?: boolean;
disabled?: boolean;
loading?: boolean;
}
/**
* @interface
* @implements BaseButtonProps
* @property onClick {MouseEventHandler<HTMLButtonElement>} The handler function gets called when the user clicks on the button.
* @property href {never}
* @see {@link <https://www.npmjs.com/package/@types/react>|@types/react}
*
* @author Giancarlo Pernudi Segura <gino@neuroalberta.tech>
*/
interface ButtonFunctionProps extends BaseButtonProps {
onClick: MouseEventHandler<HTMLButtonElement>;
href?: never;
}
/**
* @interface
* @implements BaseButtonProps
* @property href {string} Link that the button will redirect to when clicked.
* @property onClick {never}
*
* @author Giancarlo Pernudi Segura <gino@neuroalberta.tech>
*/
interface ButtonLinkProps extends BaseButtonProps {
href: string;
onClick?: never;
}
/** @ignore */
export type ButtonProps = ButtonFunctionProps | ButtonLinkProps;
/**
* @hide
* Get the css class name for a given button style type.
* @param type {"success" | "info" | "warning" | "error" | undefined} notification type
* @returns {"is-success" | "is-info" | "is-warning" | "is-danger" | "is-primary"} type of string
*
* @author Giancarlo Pernudi Segura <gino@neuralberta.tech>
*/
const typeToClassName = (type: ButtonProps["type"]) => {
switch (type) {
case "success":
return "is-success";
case "info":
return "is-info";
case "warning":
return "is-warning";
case "error":
return "is-danger";
default:
return "is-primary";
}
};
export type ButtonComponent = FunctionComponent<ButtonProps>
/**
* Button Component
* @component
* @param text {string} The text to display on the button.
* @param onClick {MouseEventHandler<HTMLButtonElement>} The handler function gets called when the user clicks on the button. Cannot be used if href is defined.
* @param href {string} Link that the button will redirect to when clicked. Cannot be used if onClick is defined.
* @param [icon] {ReactElement} The icon to display on the button.
* @param [type] {"success" | "info" | "warning" | "error"} The type (in terms of style) of button.
* @param [outlined=false] {boolean} Whether the button is outlined or filled in. Filled in by default.
* @param [disabled=false] {boolean} Whether to disable the button.
* @param [loading=false] {boolean} Whether to show a loading state for the button.
*
* @author Giancarlo Pernudi Segura <gino@neuralberta.tech>
*/
const Button: ButtonComponent = ({ text, onClick, href, icon, type, outlined = false, disabled = false, loading = false, style}) => {
const commonProps = {
style,
className: `button
${typeToClassName(type)}
${outlined ? "is-outlined" : ""}
${loading ? "is-loading" : ""}`,
disabled: disabled,
};
const innerDOM = (<>
{icon && <span className="icon">{icon}</span>}
<span>{text}</span>
</>);
return (onClick) ?
(
<button {...commonProps} onClick={onClick}>
{innerDOM}
</button>
) :
(
<a {...commonProps} href={href}>
{innerDOM}
</a>
);
};
export default Button;
Source