@shopify/polaris
Version:
Shopify’s product component library
199 lines (185 loc) • 7.57 kB
JavaScript
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 };