50 lines
1.3 KiB
TypeScript
50 lines
1.3 KiB
TypeScript
import type { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
|
|
export type ButtonVariant = 'primary' | 'neutral' | 'add' | 'danger';
|
|
export type ButtonSize = 'sm' | 'md' | 'lg';
|
|
|
|
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
variant?: ButtonVariant;
|
|
size?: ButtonSize;
|
|
loading?: boolean;
|
|
loadingLabel?: string;
|
|
leftIcon?: ReactNode;
|
|
rightIcon?: ReactNode;
|
|
}
|
|
|
|
export function Button({
|
|
variant = 'neutral',
|
|
size = 'md',
|
|
loading = false,
|
|
loadingLabel,
|
|
leftIcon,
|
|
rightIcon,
|
|
className,
|
|
children,
|
|
disabled,
|
|
...props
|
|
}: ButtonProps) {
|
|
const classes = [
|
|
'ui-button',
|
|
`ui-button--${variant}`,
|
|
`ui-button--${size}`,
|
|
loading ? 'is-loading' : '',
|
|
className ?? '',
|
|
].filter(Boolean).join(' ');
|
|
|
|
return (
|
|
<button
|
|
{...props}
|
|
className={classes}
|
|
disabled={disabled || loading}
|
|
>
|
|
{loading ? <span className="ui-button-spinner" aria-hidden="true" /> : leftIcon ? (
|
|
<span className="ui-button-icon" aria-hidden="true">{leftIcon}</span>
|
|
) : null}
|
|
<span className="ui-button-label">{loading && loadingLabel ? loadingLabel : children}</span>
|
|
{!loading && rightIcon ? <span className="ui-button-icon" aria-hidden="true">{rightIcon}</span> : null}
|
|
</button>
|
|
);
|
|
}
|
|
|