@metamask/design-system-react
Version:
Design system react ui components
84 lines • 5.07 kB
JavaScript
function $importDefault(module) {
if (module?.__esModule) {
return module.default;
}
return module;
}
import { Slot, Slottable } from "@radix-ui/react-slot";
import $React, { forwardRef } from "react";
const React = $importDefault($React);
import { ButtonBaseSize } from "../../types/index.mjs";
import { twMerge } from "../../utils/tw-merge.mjs";
import { Icon, IconName, IconSize } from "../Icon/index.mjs";
import { Text, FontWeight, TextColor } from "../Text/index.mjs";
import { TWCLASSMAP_BUTTONBASE_SIZE_DIMENSION } from "./ButtonBase.constants.mjs";
export const ButtonBase = forwardRef(({ children, className, size = ButtonBaseSize.Lg, isFullWidth, asChild, isDisabled, isLoading, loadingText, loadingIconProps, loadingTextProps, startIconName, startIconProps, startAccessory, endIconName, endIconProps, endAccessory, textProps, style, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, 'aria-describedby': ariaDescribedby, 'aria-pressed': ariaPressed, 'aria-expanded': ariaExpanded, 'aria-controls': ariaControls, 'aria-haspopup': ariaHaspopup, ...props }, ref) => {
const Component = asChild ? Slot : 'button';
const isInteractive = !(isDisabled ?? isLoading);
// Calculate tabIndex based on asChild and disabled state
const getTabIndex = () => {
if (asChild) {
return undefined;
}
return isDisabled ? -1 : undefined;
};
const renderLoadingState = () => (React.createElement(React.Fragment, null,
React.createElement("span", { className: "absolute inline-flex items-center", "aria-hidden": "true" },
React.createElement(Icon, { name: IconName.Loading, size: IconSize.Sm, className: twMerge('mr-2 animate-spin text-inherit', loadingIconProps?.className), ...loadingIconProps }),
React.createElement(Text, { fontWeight: FontWeight.Medium, color: TextColor.Inherit, asChild: true, ...loadingTextProps },
React.createElement("span", null, loadingText))),
React.createElement("span", { className: "invisible inline-flex items-center" }, children),
React.createElement("span", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true" }, loadingText || 'Loading')));
const renderStartContent = () => {
if (startIconName) {
return (React.createElement(Icon, { name: startIconName, size: IconSize.Sm, className: twMerge('mr-2 shrink-0 text-inherit', startIconProps?.className), "aria-hidden": "true", ...startIconProps }));
}
if (startAccessory) {
return (React.createElement("span", { className: "mr-2", "aria-hidden": "true" }, startAccessory));
}
return null;
};
const renderEndContent = () => {
if (endIconName) {
return (React.createElement(Icon, { name: endIconName, size: IconSize.Sm, className: twMerge('ml-2 shrink-0 text-inherit', endIconProps?.className), "aria-hidden": "true", ...endIconProps }));
}
if (endAccessory) {
return (React.createElement("span", { className: "ml-2", "aria-hidden": "true" }, endAccessory));
}
return null;
};
const renderContent = () => {
if (children && typeof children === 'string') {
return (React.createElement(Text, { fontWeight: FontWeight.Medium, color: TextColor.Inherit, asChild: true, ...textProps },
React.createElement("span", null, children)));
}
return children;
};
const mergedClassName = twMerge(
// Base styles
'inline-flex items-center justify-center', 'rounded-xl px-4', 'font-medium text-default', 'bg-muted', 'min-w-20 overflow-hidden',
// Add relative positioning for loading state
'relative',
// Size
TWCLASSMAP_BUTTONBASE_SIZE_DIMENSION[size],
// Full width
isFullWidth && 'w-full',
// Animation classes - only applied when interactive
isInteractive && [
'transition-all',
'duration-100',
'ease-linear',
'active:scale-[0.97]',
'active:ease-[cubic-bezier(0.3,0.8,0.3,1)]',
],
// Disabled state - apply to both isDisabled and isLoading
(isDisabled || isLoading) && 'cursor-not-allowed', isDisabled && 'opacity-50',
// Custom classes
className);
return (React.createElement(Component, { ref: ref, className: mergedClassName, disabled: asChild ? undefined : (isDisabled ?? isLoading), "aria-disabled": isDisabled ? 'true' : undefined, "aria-busy": isLoading ? 'true' : undefined, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby, "aria-pressed": ariaPressed, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, "aria-haspopup": ariaHaspopup, role: asChild ? undefined : 'button', tabIndex: getTabIndex(), style: style, ...props },
renderStartContent(),
React.createElement(Slottable, null, isLoading ? renderLoadingState() : renderContent()),
renderEndContent()));
});
ButtonBase.displayName = 'ButtonBase';
//# sourceMappingURL=ButtonBase.mjs.map