62 lines
No EOL
2 KiB
TypeScript
62 lines
No EOL
2 KiB
TypeScript
import { Link } from "react-router";
|
|
import React from "react";
|
|
import classNames from "classnames";
|
|
|
|
interface ButtonProps {
|
|
appearance?: 'solid' | 'outline' | 'text';
|
|
children: React.ReactNode;
|
|
className?: string;
|
|
href?: string;
|
|
icon?: React.ReactNode;
|
|
onClick?: () => void;
|
|
disabled?: boolean;
|
|
size?: 'small' | 'medium' | 'large';
|
|
type?: 'button' | 'submit' | 'reset';
|
|
variant?: 'primary' | 'secondary' | 'accent';
|
|
}
|
|
|
|
const Button = ({ appearance, children, className, disabled, href, icon, onClick,
|
|
size = 'medium', type,
|
|
variant = 'primary'
|
|
}: ButtonProps) => {
|
|
const styles = classNames(
|
|
"flex items-center space-x-1",
|
|
"justify-center font-size-18 py-2 px-4 rounded flex",
|
|
{
|
|
'border-2 border-primary background-red text-white': variant === 'primary' && appearance === 'solid',
|
|
'border-2 border-primary text-primary': variant === 'primary' && appearance === 'outline',
|
|
'text-primary': variant === 'primary' && appearance === 'text',
|
|
'border-2 border-secondary text-secondary': variant === 'secondary' && appearance === 'outline',
|
|
'border-2 border-accent-blue text-accent-blue': variant === 'accent' && appearance === 'outline',
|
|
},
|
|
className
|
|
)
|
|
|
|
const iconClassNames = classNames({
|
|
"h-4 w-4 mr-1": size === "small",
|
|
"h-5 w-5 mr-1": size === "medium",
|
|
"h-7 w-7 mr-2": size === "large",
|
|
});
|
|
|
|
const iconElement =
|
|
React.isValidElement(icon) &&
|
|
React.cloneElement(icon as React.ReactElement<{ className?: string }>, {
|
|
className: iconClassNames,
|
|
});
|
|
|
|
if (href !== undefined) {
|
|
return (
|
|
<Link to={href} className={styles}>
|
|
{ icon && iconElement}
|
|
{ children}
|
|
</Link>
|
|
)
|
|
}
|
|
|
|
return <button onClick={onClick} className={styles} disabled={disabled} type={ type ?? 'button'}>
|
|
{ icon && iconElement}
|
|
{ children }
|
|
</button>
|
|
}
|
|
|
|
export default Button |