import * as React from 'react';
import cx from 'classnames';
import Text from '../text/Text';
import Spinner from '../spinner/Spinner';
import {__DEV__, invariant} from '../utils';
export const BUTTON_LITE_SIZE = {
XS: 'xs',
S: 's',
} as const;
type ButtonLiteSizeType = 'xs' | 's';
export const BUTTON_LITE_VARIANT = {
TRANSPARENT: 'transparent',
TRANSPARENT_INVERTED: 'transparent-inverted',
TRANSPARENT_LIGHT: 'transparent-light',
TRANSPARENT_INDIGO: 'transparent-indigo',
SOLID_LIGHT: 'solid-light',
SOLID_INDIGO_LIGHT: 'solid-indigo-light',
} as const;
type ButtonLiteVariantType =
| 'transparent'
| 'transparent-inverted'
| 'transparent-light'
| 'transparent-indigo'
| 'solid-light'
| 'solid-indigo-light';
type TargetType = '_self' | '_blank' | '_parent' | '_top';
export type AriaLiveType = 'off' | 'polite' | 'assertive';
export type ButtonLiteTypeType = 'button' | 'submit' | 'reset';
const anchorRelatedProps = [
'download',
'hreflang',
'ping',
'referrerpolicy',
'rel',
];
export type ButtonLitePropsType = {
/**
* Children to be rendered inside Button
* @example }
* variant="solid"
* >
* button
*
*/
children?: React.ReactNode;
/**
* Specify variant of the button that you want to use
* @example
* button
*
*
*/
variant?: ButtonLiteVariantType;
/**
* Specify href for button, optional string
* @example
*/
href?: string;
/**
* Specifies where to display the linked URL.
*/
target?: TargetType;
/**
* Accessible information that indicates opening in new tab.
*/
newTabLabel?: string;
/**
* Accessible name for Button.
*/
'aria-label'?: string;
onClick?: (
arg0: React.MouseEvent
) => unknown;
/**
* The default behavior of the button.
*/
type?: ButtonLiteTypeType;
/**
* There are two sizes options for buttons, not need to be specify, default is s
* @example
* button
*
*/
size?: ButtonLiteSizeType;
/**
* Show loading state. By default loading state make button disabled while
* showing spinner inside and keep button's width unchanged.
*/
loading?: boolean;
/**
* `aria-live` for loading state. Defaults to "off".
*/
loadingAriaLive?: AriaLiveType;
/**
* Accessible information about loading state. Defaults to "loading".
*/
loadingAriaLabel?: string;
/**
* Optional boolean for disabled button
* @example
*/
disabled?: boolean;
/**
* You can render icon inside each variant of button on the left side
* @example }
* variant="facebook"
* >
* Login with Facebook
*
*/
icon?: React.ReactNode;
/**
* Reverses order of icon and text. Effective only when icon is set.
*/
reversedOrder?: boolean;
className?: string;
} & Omit<
React.AllHTMLAttributes,
| 'variant'
| 'icon'
| 'reversedOrder'
| 'children'
| 'size'
| 'href'
| 'disabled'
| 'loading'
| 'loadingAriaLive'
| 'loadingAriaLabel'
| 'fullWidth'
| 'className'
| 'target'
| 'newTabLabel'
| 'aria-label'
| 'type'
| 'onClick'
>;
const ButtonLite = ({
className,
variant = BUTTON_LITE_VARIANT.TRANSPARENT,
children,
size = BUTTON_LITE_SIZE.S,
loading,
loadingAriaLabel,
loadingAriaLive,
disabled,
icon,
reversedOrder,
href,
target,
newTabLabel = '(opens in a new tab)',
type,
onClick,
'aria-label': ariaLabel,
...rest
}: ButtonLitePropsType) => {
const buttonClass = cx(
'sg-button-lite',
`sg-button-lite--${variant}`,
`sg-button-lite--${size}`,
{
'sg-button-lite--loading': loading,
'sg-button-lite--reversed-order': reversedOrder,
},
className
);
const isDisabled = disabled || loading;
const isLink = !!href;
const hasIcon = icon !== undefined && icon !== null;
if (__DEV__) {
invariant(
!(reversedOrder && !icon),
`Using 'reversedOrder' property has no effect when 'icon' property is not set.`
);
invariant(
!(
!isLink &&
(target || Object.keys(rest).some(p => anchorRelatedProps.includes(p)))
),
`An anchor-related prop is not working when "href" is not provided: ${Object.keys(
rest
)}`
);
invariant(
!(isLink && type),
'`type` prop is not working when href is provided'
);
}
// @ts-ignore TS7006
const onButtonClick = e => {
if (isLink && isDisabled) {
return;
}
return onClick && onClick(e);
};
const TagToRender = isLink ? (isDisabled ? 'span' : 'a') : 'button';
return (
null}
>
{loading && (
)}
{hasIcon && {icon}}
{children}
{target === '_blank' && (
{newTabLabel}
)}
);
};
export default ButtonLite;