63 lines
2.0 KiB
TypeScript
63 lines
2.0 KiB
TypeScript
import React from 'react'
|
|
|
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
isLoading?: boolean
|
|
}
|
|
|
|
const Button: React.FC<ButtonProps> = ({
|
|
children,
|
|
className,
|
|
isLoading = false,
|
|
disabled,
|
|
...props
|
|
}) => {
|
|
const baseClasses =
|
|
'w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white focus:outline-none focus:ring-2 focus:ring-offset-2'
|
|
const activeClasses = 'bg-sky-600 hover:bg-sky-700 focus:ring-sky-500'
|
|
const loadingClasses = 'bg-sky-400 cursor-not-allowed'
|
|
const disabledClasses = 'bg-gray-400 cursor-not-allowed'
|
|
|
|
const getButtonClasses = () => {
|
|
if (isLoading)
|
|
return `${baseClasses} ${loadingClasses} ${className || ''}`
|
|
if (disabled)
|
|
return `${baseClasses} ${disabledClasses} ${className || ''}`
|
|
return `${baseClasses} ${activeClasses} ${className || ''}`
|
|
}
|
|
|
|
return (
|
|
<button
|
|
className={getButtonClasses()}
|
|
disabled={disabled || isLoading}
|
|
{...props}
|
|
>
|
|
{isLoading ? (
|
|
<svg
|
|
className="animate-spin -ml-1 mr-3 h-5 w-5 text-white"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<circle
|
|
className="opacity-25"
|
|
cx="12"
|
|
cy="12"
|
|
r="10"
|
|
stroke="currentColor"
|
|
strokeWidth="4"
|
|
></circle>
|
|
<path
|
|
className="opacity-75"
|
|
fill="currentColor"
|
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
></path>
|
|
</svg>
|
|
) : (
|
|
children
|
|
)}
|
|
</button>
|
|
)
|
|
}
|
|
|
|
export default Button
|