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 */ 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;