@mapbox/mr-ui
Version:
UI components for Mapbox projects
223 lines (220 loc) • 7.09 kB
JavaScript
"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
};