import React, { forwardRef } from 'react' import { Button as RACButton, type ButtonProps as RACButtonProps } from 'react-aria-components' import { useReversedColors } from '~components/utils' import { mergeClassNames } from '~components/utils/mergeClassNames' import { ButtonContent, PendingContent } from './subcomponents' import { type ButtonSizes, type ButtonVariants, type PendingButtonProps } from './types' import styles from './Button.module.css' /** Shared UI props between Button and LinkButton */ export type ButtonUIProps = { /** Visually hides the Button's child content used as the label and the `pendingLabel`. Use for icon-only `Button`. @default "false" */ hasHiddenLabel?: boolean /** The visual style of the button. * @default "default" */ variant?: ButtonVariants /** The visual size of the button. `medium` was formerly `regular` * @default "medium" */ size?: ButtonSizes /** Renders an icon at the `iconPosition` provided. To the size scales with the button, we recommend using the `Icon` component from `"@kaizen/components/next"` */ icon?: JSX.Element /** Controls the position of the Icon passed in as props. @default "start" */ iconPosition?: 'start' | 'end' /** Controls if the button inherits width from its parent. @default "false" */ isFullWidth?: boolean } export type ButtonProps = ButtonUIProps & PendingButtonProps & Omit & { /** Used as the label for the button. */ children: RACButtonProps['children'] } export const Button = forwardRef( ( { variant = 'primary', size = 'medium', className, children, isDisabled, isFullWidth = false, icon, iconPosition, hasHiddenLabel = false, isPending, hasHiddenPendingLabel: propsHasHiddenPendingLabel = false, pendingLabel, ...restProps }: ButtonProps, ref: React.ForwardedRef, ) => { const isReversedVariant = useReversedColors() const pendingProps: PendingButtonProps = isPending ? { isPending, hasHiddenPendingLabel: hasHiddenLabel || propsHasHiddenPendingLabel, pendingLabel, } : {} const buttonContentClass = isPending ? !hasHiddenLabel && propsHasHiddenPendingLabel ? styles.retainContentWidth : styles.hideContentWidth : undefined return ( {(racStateProps) => { const childIsFunction = typeof children === 'function' return ( <> {childIsFunction ? children(racStateProps) : children} {pendingProps.isPending && } ) }} ) }, ) Button.displayName = 'Button'