@carbon/react
Version:
React components for the Carbon Design System
158 lines (156 loc) • 4.6 kB
JavaScript
/**
* Copyright IBM Corp. 2016, 2026
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
import ButtonBase from "./ButtonBase.js";
import { IconButton, IconButtonKinds } from "../IconButton/index.js";
import React from "react";
import PropTypes from "prop-types";
import { jsx } from "react/jsx-runtime";
//#region src/components/Button/Button.tsx
/**
* Copyright IBM Corp. 2016, 2026
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
const ButtonKinds = [
"primary",
"secondary",
"danger",
"ghost",
"danger--primary",
"danger--ghost",
"danger--tertiary",
"tertiary"
];
const ButtonSizes = [
"xs",
"sm",
"md",
"lg",
"xl",
"2xl"
];
const ButtonTooltipAlignments = [
"start",
"center",
"end"
];
const ButtonTooltipPositions = [
"top",
"right",
"bottom",
"left"
];
function isIconOnlyButton(hasIconOnly, _kind) {
if (hasIconOnly === true) return true;
return false;
}
const Button = React.forwardRef((props, ref) => {
const { as, autoAlign = false, children, hasIconOnly = false, tooltipHighContrast = true, tooltipDropShadow = false, iconDescription, kind = "primary", onBlur, onClick, onFocus, onMouseEnter, onMouseLeave, renderIcon: ButtonImageElement, size, tooltipAlignment = "center", tooltipPosition = "top", ...rest } = props;
if (ButtonImageElement && !children && !iconDescription) console.error("Button: renderIcon property specified without also providing an iconDescription property. This may impact accessibility for screen reader users.");
const iconOnlyImage = !ButtonImageElement ? null : /* @__PURE__ */ jsx(ButtonImageElement, {});
if (!isIconOnlyButton(hasIconOnly, kind)) {
const { tooltipAlignment, ...propsWithoutTooltipAlignment } = props;
return /* @__PURE__ */ jsx(ButtonBase, {
ref,
...propsWithoutTooltipAlignment
});
} else {
let align = void 0;
if (tooltipPosition === "top" || tooltipPosition === "bottom") {
if (tooltipAlignment === "center") align = tooltipPosition;
if (tooltipAlignment === "end") align = `${tooltipPosition}-end`;
if (tooltipAlignment === "start") align = `${tooltipPosition}-start`;
}
if (tooltipPosition === "right" || tooltipPosition === "left") align = tooltipPosition;
return /* @__PURE__ */ jsx(IconButton, {
...rest,
ref,
as,
align,
label: iconDescription,
kind,
size,
highContrast: tooltipHighContrast,
dropShadow: tooltipDropShadow,
onMouseEnter,
onMouseLeave,
onFocus,
onBlur,
autoAlign,
onClick,
renderIcon: iconOnlyImage ? null : ButtonImageElement,
children: iconOnlyImage ?? children
});
}
});
Button.displayName = "Button";
Button.propTypes = {
as: PropTypes.oneOfType([
PropTypes.func,
PropTypes.string,
PropTypes.elementType
]),
autoAlign: PropTypes.bool,
children: PropTypes.node,
className: PropTypes.string,
dangerDescription: PropTypes.string,
disabled: PropTypes.bool,
hasIconOnly: PropTypes.bool,
href: PropTypes.string,
iconDescription: (props) => {
if (props.renderIcon && !props.children && !props.iconDescription) return /* @__PURE__ */ new Error("renderIcon property specified without also providing an iconDescription property.");
return null;
},
isExpressive: PropTypes.bool,
isSelected: PropTypes.bool,
kind: (props, propName, componentName) => {
const { hasIconOnly } = props;
const validKinds = hasIconOnly ? IconButtonKinds : ButtonKinds;
if (props[propName] === void 0) return null;
if (!validKinds.includes(props[propName])) return /* @__PURE__ */ new Error(`Invalid prop \`${propName}\` supplied to \`${componentName}\`. Expected one of ${validKinds.join(", ")}.`);
return null;
},
onBlur: PropTypes.func,
onClick: PropTypes.func,
onFocus: PropTypes.func,
onMouseEnter: PropTypes.func,
onMouseLeave: PropTypes.func,
rel: PropTypes.string,
renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
role: PropTypes.string,
size: PropTypes.oneOf([
"xs",
"sm",
"md",
"lg",
"xl",
"2xl"
]),
tabIndex: PropTypes.number,
target: PropTypes.string,
tooltipAlignment: PropTypes.oneOf([
"start",
"center",
"end"
]),
tooltipDropShadow: PropTypes.bool,
tooltipHighContrast: PropTypes.bool,
tooltipPosition: PropTypes.oneOf([
"top",
"right",
"bottom",
"left"
]),
type: PropTypes.oneOf([
"button",
"reset",
"submit"
])
};
//#endregion
export { ButtonKinds, ButtonSizes, ButtonTooltipAlignments, ButtonTooltipPositions, Button as default };