/* InternalDismissIconButton aims to replace "dismiss" IconButtons in components that toggle on/off their visibility, p.ex. Modal, OverlayPanel, mobile SideNavigation. When visible, we require autofocus within the component in particular the dismiss IconButton. IconButton displays a Tooltip on focus, but for this particular usage the tooltip is not required as it creates a bad UX. InternalDismissIconButton is an IconButtons replacement without tooltip. */ import { ComponentProps, forwardRef, useImperativeHandle, useRef, useState } from 'react'; import classnames from 'classnames'; import styles from '../IconButton/InternalIconButton.css'; import Pog from '../Pog'; import touchableStyles from '../TapArea.css'; import useFocusVisible from '../useFocusVisible'; import useTapFeedback from '../useTapFeedback'; type Props = { accessibilityLabel: string; accessibilityControls?: string; iconColor?: ComponentProps['iconColor']; onClick?: (arg1: { event: React.MouseEvent | React.KeyboardEvent; }) => void; size?: ComponentProps['size']; }; const InternalDismissIconButtonWithForwardRef = forwardRef( function IconButton( { accessibilityLabel, accessibilityControls, iconColor = 'darkGray', onClick, size = 'lg', }: Props, ref, ) { const innerRef = useRef(null); // When using both forwardRef and innerRef, React.useimperativehandle() allows a parent component // that renders to call inputRef.current.focus() // @ts-expect-error - TS2322 - Type 'HTMLButtonElement | null' is not assignable to type 'HTMLButtonElement'. useImperativeHandle(ref, () => innerRef.current); const { compressStyle, isTapping, handleBlur, handleMouseDown, handleMouseUp, handleTouchStart, handleTouchMove, handleTouchCancel, handleTouchEnd, } = useTapFeedback({ height: innerRef?.current?.clientHeight, width: innerRef?.current?.clientWidth, }); const [isFocused, setFocused] = useState(false); const [isHovered, setHovered] = useState(false); const { isFocusVisible } = useFocusVisible(); const handleClick = ( event: React.MouseEvent | React.KeyboardEvent, ) => (onClick ? onClick({ event }) : undefined); const handleOnBlur = () => setFocused(false); const handleOnFocus = () => setFocused(true); const handleOnMouseEnter = () => setHovered(true); const handleOnMouseLeave = () => setHovered(false); return ( ); }, ); InternalDismissIconButtonWithForwardRef.displayName = 'InternalDismissIconButton'; export default InternalDismissIconButtonWithForwardRef;