UNPKG

@mapbox/mr-ui

Version:

UI components for Mapbox projects

223 lines (220 loc) 7.09 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Button; var _react = _interopRequireDefault(require("react")); var _classnames = _interopRequireDefault(require("classnames")); var _propTypes = _interopRequireDefault(require("prop-types")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function getSize(variant) { switch (variant) { case 'appPrimary': case 'appSecondary': return 'small'; default: return 'large'; } } function getWidth(variant) { switch (variant) { case 'appPrimary': case 'appSecondary': return 'small'; default: return 'medium'; } } function getCorners(variant) { switch (variant) { case 'appPrimary': case 'appSecondary': return true; default: return false; } } function getOutline(variant) { switch (variant) { case 'secondary': case 'appSecondary': return true; default: return false; } } function getColor(variant) { switch (variant) { case 'secondary': case 'appPrimary': case 'appSecondary': return 'gray'; case 'tertiary': return 'transparent'; case 'destructive': return 'red'; default: return 'blue'; } } /** * A good-looking button! * * The rendered element will be a `<button>` or an `<a>`, depending on whether * you provide an `href` prop or not. * * If you'd like to put an icon before or after the text of your button, * use [IconText](#icontext) for the content. */ function Button(_ref) { let { variant = 'primary', ariaLabel, size = getSize(variant), width = getWidth(variant), color = getColor(variant), outline = getOutline(variant), corners = getCorners(variant), block = false, disabled = false, onClick, passthroughProps, href, children } = _ref; const isSmall = size === 'small'; const isMedium = size === 'medium'; const isLarge = size === 'large'; const widthSmall = width === 'small'; const widthMedium = width === 'medium'; const widthLarge = width === 'large'; const classes = (0, _classnames.default)('btn', { [`btn--${color}`]: color, 'btn--stroke': outline, 'link link--gray transition': variant === 'tertiary', round: corners, 'round-full': !corners, h24: isSmall, py12: isLarge, py6: isMedium, px6: widthSmall && isSmall, px12: widthMedium && isSmall || widthSmall && !isSmall, px24: widthLarge && isSmall || widthMedium && !isSmall, px36: !isSmall && widthLarge, 'w-full block': width === 'full', block, 'txt-s': !isSmall, 'py3 txt-xs': isSmall }); const universalProps = { className: classes, 'aria-label': ariaLabel ? ariaLabel : variant, onClick, ...passthroughProps }; if (href) { return /*#__PURE__*/_react.default.createElement("a", _extends({ href: href }, universalProps), children); } // "disabled" is not a valid attributes for anchors. const buttonProps = { ...universalProps, children, disabled }; return /*#__PURE__*/_react.default.createElement("button", _extends({ type: "button" }, buttonProps)); } Button.propTypes = { /** * The button's content. A string is recommended, but you can put an element * in here if you think that's right. If you do, it should be inline-level, * using `<span>`s instead of `<div>`s. ([IconText](#icontext) is * inline-level.) */ children: _propTypes.default.node.isRequired, /** * A keyword identifying the standard button styling variant to use. * * *The variant is a starting point*: all of the other styling props can be * used to override details. * * The following variants are available: * * - `"primary"`: For primary actions. * - `"secondary"`: For secondary actions. * - `"tertiary"`: For downplayed actions, the ones people shouldn't * usually want to perform, like cancelling instead of confirming. * - `"destructive"`: For destructive actions, like deleting something. * - `"appPrimary"`: For primary actions in dense apps. * - `"appSecondary"`: For secondary actions in dense apps. */ variant: _propTypes.default.oneOf(['primary', 'secondary', 'tertiary', 'destructive', 'appPrimary', 'appSecondary']), /** * A callback that receives the click event. * * You definitely need this if you don't use `href`; but you can also provide * both `onClick` and `href`, and `onClick` will be called when the `<a>` is * clicked. */ onClick: _propTypes.default.func, /** * A URL. If `href` is provided, the button will be an `<a>`. */ href: _propTypes.default.string, /** * The size of the button: `"small"`, `"medium"`, or `"large"`. * * This accounts for height, outline thickness, text size, and other details. * * This will override whichever defaults are set by your `variant` of choice. */ size: _propTypes.default.oneOf(['small', 'medium', 'large']), /** * The width of the button: `"small"`, `"medium"`, `"large"`, or `"full"`. * For every option but `"full"` this prop determines horizontal padding. * `"full"` sets the button to fill the width of its container. * * This is distinguished from `size` because buttons of the same general size * can vary by width. * * This will override whichever defaults are set by your `variant` of choice. */ width: _propTypes.default.oneOf(['small', 'medium', 'large', 'full']), /** * If `true`, the button will be outlined instead of filled with color. */ outline: _propTypes.default.bool, /** * The Assembly color of the button. */ color: _propTypes.default.string, /** * If `true`, the button will have (slightly rounded) corners instead of * the full curve they have by default. */ corners: _propTypes.default.bool, /** * If `true`, the element will be `block` displayed instead of `inline-block`. * * This is sometimes necessary to get your pixel-perfect layout, if you don't * want the extra line-height that wraps inline elements. Typically, you * should only set `block` to `true` if the parent element is controlling * width (in a layout that uses flexbox, absolute positioning, or floats). */ block: _propTypes.default.bool, /** * Is it disabled? */ disabled: _propTypes.default.bool, /** * An object of props that you want to pass through to the element that * Button renders. This can be useful if you want to disable * the button, assign an ID for testing, add an ARIA attribute, toss in some * custom style properties, etc. */ passthroughProps: _propTypes.default.object };