/**
* Button — one recipe, four intents.
*
* The weight ladder is deliberately only three deep: exactly one `primary`
* per screen region, `secondary` for reversible actions, `ghost` for tertiary
* controls that sit inside another surface. `danger` is separate because it
* signals consequence, not rank.
*/
import { IconSpinner } from '../icons';
const VARIANTS = {
primary: 'c-btn-primary',
secondary: 'c-btn-secondary',
ghost: 'c-btn-ghost',
danger: 'c-btn-danger',
};
const SIZES = {
xs: 'c-btn-xs',
sm: 'c-btn-sm',
md: '',
};
/**
* @param {Object} props
* @param {string} [props.variant] primary | secondary | ghost | danger.
* @param {string} [props.size] xs | sm | md.
* @param {boolean} [props.busy] Swap the leading icon for a spinner and
* block interaction. The label stays, so the
* button never changes width mid-action.
* @param {Function} [props.icon] Leading icon component.
* @param {string} [props.href] Render an anchor instead of a button.
* @return {Element} Button or link.
*/
export default function Button( {
variant = 'secondary',
size = 'md',
busy = false,
icon: Icon,
href,
className = '',
children,
disabled,
...props
} ) {
const classes = [
'c-btn',
VARIANTS[ variant ] || VARIANTS.secondary,
SIZES[ size ] || '',
className,
]
.filter( Boolean )
.join( ' ' );
const content = (
<>
{ busy && }
{ ! busy && Icon && }
{ children }
>
);
if ( href ) {
return (
{ content }
);
}
return (
);
}