/* eslint-disable react/button-has-type */ import React, { forwardRef, useCallback } from 'react'; import { clsx } from 'clsx'; import { useIntl, MessageDescriptor } from 'react-intl'; import messages from '../../i18n/commonMessages/Button.messages'; import type { PrimitiveButtonProps } from '.'; /** * The Primitive `PrimitiveButton` component can be used in various parts the Wise Design * System internally. It supports different states such as disabled and loading, * and provides event handlers for common interactions like click, focus, blur, * mouse enter, mouse leave, and keydown. * * @see {@link PrimitiveButton} for further information. * @see {@link https://storybook.wise.design/?path=/docs/primitive-button--docs|Storybook Wise Design} */ const PrimitiveButton = forwardRef( ( { children, className, id, disabled = false, loading = false, testId, type = 'button', onClick, onFocus, onBlur, onMouseEnter, onMouseLeave, onKeyDown, ...props }, ref, ) => { const intl = useIntl(); const classNames = clsx(className); const handleClick = useCallback( (event: React.MouseEvent) => { if (disabled || loading) { event.preventDefault(); } else { onClick?.(event); } }, [disabled, loading, onClick], ); const handleFocus = useCallback( (event: React.FocusEvent) => { onFocus?.(event); }, [onFocus], ); const handleBlur = useCallback( (event: React.FocusEvent) => { onBlur?.(event); }, [onBlur], ); const handleMouseEnter = useCallback( (event: React.MouseEvent) => { onMouseEnter?.(event); }, [onMouseEnter], ); const handleMouseLeave = useCallback( (event: React.MouseEvent) => { onMouseLeave?.(event); }, [onMouseLeave], ); const handleKeyDown = useCallback( (event: React.KeyboardEvent) => { onKeyDown?.(event); }, [onKeyDown], ); /** * The following props are used to manage the `disabled` and `loading` * states for the button: * * - `aria-disabled`: Communicates to assistive technologies that the button * is disabled when it is either disabled or loading. * - `aria-label`: Provides an accessible label for the button, using a * localized loading message when the button is in a loading state. * - `aria-live`: Ensures that updates to the button's content are announced * by assistive technologies, set to 'polite' during loading. */ const buttonProps = { 'aria-disabled': loading || undefined, 'aria-busy': loading || undefined, 'aria-label': loading ? intl.formatMessage(messages.loadingAriaLabel) : props['aria-label'], 'aria-live': (loading ? 'polite' : 'off') as 'polite' | 'off' | 'assertive' | undefined, className: classNames, 'data-testid': testId, disabled, id, ref, type, onBlur: handleBlur, onClick: handleClick, onFocus: handleFocus, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onKeyDown: handleKeyDown, ...props, }; return ; }, ); PrimitiveButton.displayName = 'PrimitiveButton'; export default PrimitiveButton;