UNPKG

@shopify/polaris

Version:

Shopify’s product component library

199 lines (185 loc) • 7.57 kB
import React$1, { useRef, useState, useCallback } from 'react'; import { useFeatures } from '../../utilities/features/hooks.js'; import { useI18n } from '../../utilities/i18n/hooks.js'; import { classNames, variationName } from '../../utilities/css.js'; import { CaretDownMinor } from '@shopify/polaris-icons'; import { handleMouseUpByBlurring } from '../../utilities/focus.js'; import { Icon as Icon$1 } from '../Icon/Icon.js'; import { Spinner as Spinner$1 } from '../Spinner/Spinner.js'; import { Popover as Popover$1 } from '../Popover/Popover.js'; import { ActionList as ActionList$1 } from '../ActionList/ActionList.js'; import { UnstyledButton as UnstyledButton$1 } from '../UnstyledButton/UnstyledButton.js'; import styles from './Button.scss.js'; var DEFAULT_SIZE = 'medium'; var _ref = /*#__PURE__*/React$1.createElement(Icon$1, { source: CaretDownMinor }); function Button({ id, url, disabled, loading, children, accessibilityLabel, ariaControls, ariaExpanded, ariaPressed, onClick, onFocus, onBlur, onKeyDown, onKeyPress, onKeyUp, onMouseEnter, onTouchStart, external, download, icon, primary, outline, destructive, disclosure, plain, monochrome, submit, size = DEFAULT_SIZE, textAlign, fullWidth, pressed, connectedDisclosure }) { var { newDesignLanguage } = useFeatures(); var hasGivenDeprecationWarning = useRef(false); if (ariaPressed && !hasGivenDeprecationWarning.current) { // eslint-disable-next-line no-console console.warn('Deprecation: The ariaPressed prop has been replaced with pressed'); hasGivenDeprecationWarning.current = true; } var i18n = useI18n(); var isDisabled = disabled || loading; var className = classNames(styles.Button, newDesignLanguage && styles.newDesignLanguage, primary && styles.primary, outline && styles.outline, destructive && styles.destructive, isDisabled && styles.disabled, loading && styles.loading, plain && styles.plain, pressed && !disabled && !url && styles.pressed, monochrome && styles.monochrome, size && size !== DEFAULT_SIZE && styles[variationName('size', size)], textAlign && styles[variationName('textAlign', textAlign)], fullWidth && styles.fullWidth, icon && children == null && styles.iconOnly, connectedDisclosure && styles.connectedDisclosure); var disclosureIcon = /*#__PURE__*/React$1.createElement(Icon$1, { source: loading ? 'placeholder' : CaretDownMinor }); var disclosureIconMarkup = disclosure ? /*#__PURE__*/React$1.createElement("span", { className: styles.Icon }, /*#__PURE__*/React$1.createElement("div", { className: classNames(styles.DisclosureIcon, disclosure === 'up' && styles.DisclosureIconFacingUp, loading && styles.Hidden) }, disclosureIcon)) : null; var iconMarkup; if (icon) { var iconInner = isIconSource(icon) ? /*#__PURE__*/React$1.createElement(Icon$1, { source: loading ? 'placeholder' : icon }) : icon; iconMarkup = /*#__PURE__*/React$1.createElement("span", { className: classNames(styles.Icon, loading && styles.Hidden) }, iconInner); } var childMarkup = children ? /*#__PURE__*/React$1.createElement("span", { className: styles.Text }, children) : null; var spinnerColor = primary || destructive ? 'white' : 'inkLightest'; var spinnerSVGMarkup = loading ? /*#__PURE__*/React$1.createElement("span", { className: styles.Spinner }, /*#__PURE__*/React$1.createElement(Spinner$1, { size: "small", color: spinnerColor, accessibilityLabel: i18n.translate('Polaris.Button.spinnerAccessibilityLabel') })) : null; var content = iconMarkup || disclosureIconMarkup ? /*#__PURE__*/React$1.createElement("span", { className: styles.Content }, spinnerSVGMarkup, iconMarkup, childMarkup, disclosureIconMarkup) : /*#__PURE__*/React$1.createElement("span", { className: styles.Content }, spinnerSVGMarkup, childMarkup); var type = submit ? 'submit' : 'button'; var ariaPressedStatus = pressed !== undefined ? pressed : ariaPressed; var [disclosureActive, setDisclosureActive] = useState(false); var toggleDisclosureActive = useCallback(() => { setDisclosureActive(disclosureActive => !disclosureActive); }, []); var connectedDisclosureMarkup; if (connectedDisclosure) { var connectedDisclosureClassName = classNames(styles.Button, primary && styles.primary, outline && styles.outline, size && size !== DEFAULT_SIZE && styles[variationName('size', size)], textAlign && styles[variationName('textAlign', textAlign)], destructive && styles.destructive, connectedDisclosure.disabled && styles.disabled, styles.iconOnly, styles.ConnectedDisclosure, newDesignLanguage && styles.newDesignLanguage); var defaultLabel = i18n.translate('Polaris.Button.connectedDisclosureAccessibilityLabel'); var { disabled: _disabled, accessibilityLabel: disclosureLabel = defaultLabel } = connectedDisclosure; var connectedDisclosureActivator = /*#__PURE__*/React$1.createElement("button", { type: "button", className: connectedDisclosureClassName, disabled: _disabled, "aria-label": disclosureLabel, onClick: toggleDisclosureActive, onMouseUp: handleMouseUpByBlurring }, /*#__PURE__*/React$1.createElement("span", { className: styles.Icon }, _ref)); connectedDisclosureMarkup = /*#__PURE__*/React$1.createElement(Popover$1, { active: disclosureActive, onClose: toggleDisclosureActive, activator: connectedDisclosureActivator, preferredAlignment: "right" }, /*#__PURE__*/React$1.createElement(ActionList$1, { items: connectedDisclosure.actions, onActionAnyItem: toggleDisclosureActive })); } var buttonMarkup; if (url) { buttonMarkup = isDisabled ? /*#__PURE__*/ // Render an `<a>` so toggling disabled/enabled state changes only the // `href` attribute instead of replacing the whole element. // eslint-disable-next-line jsx-a11y/anchor-is-valid React$1.createElement("a", { id: id, className: className, "aria-label": accessibilityLabel }, content) : /*#__PURE__*/React$1.createElement(UnstyledButton$1, { id: id, url: url, external: external, download: download, onClick: onClick, onFocus: onFocus, onBlur: onBlur, onMouseUp: handleMouseUpByBlurring, onMouseEnter: onMouseEnter, onTouchStart: onTouchStart, className: className, "aria-label": accessibilityLabel }, content); } else { buttonMarkup = /*#__PURE__*/React$1.createElement(UnstyledButton$1, { id: id, type: type, onClick: onClick, onFocus: onFocus, onBlur: onBlur, onKeyDown: onKeyDown, onKeyUp: onKeyUp, onKeyPress: onKeyPress, onMouseUp: handleMouseUpByBlurring, onMouseEnter: onMouseEnter, onTouchStart: onTouchStart, className: className, disabled: isDisabled, "aria-label": accessibilityLabel, "aria-controls": ariaControls, "aria-expanded": ariaExpanded, "aria-pressed": ariaPressedStatus, role: loading ? 'alert' : undefined, "aria-busy": loading ? true : undefined }, content); } return connectedDisclosureMarkup ? /*#__PURE__*/React$1.createElement("div", { className: styles.ConnectedDisclosureWrapper }, buttonMarkup, connectedDisclosureMarkup) : buttonMarkup; } function isIconSource(x) { return typeof x === 'string' || typeof x === 'object' && x.body || typeof x === 'function'; } export { Button };