diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/atoms/buttons/button.tsx | 35 | ||||
| -rw-r--r-- | src/components/molecules/buttons/help-button.tsx | 12 | ||||
| -rw-r--r-- | src/components/molecules/forms/select-with-tooltip.tsx | 11 | ||||
| -rw-r--r-- | src/utils/hooks/use-click-outside.tsx | 7 |
4 files changed, 44 insertions, 21 deletions
diff --git a/src/components/atoms/buttons/button.tsx b/src/components/atoms/buttons/button.tsx index a6eef8b..9776687 100644 --- a/src/components/atoms/buttons/button.tsx +++ b/src/components/atoms/buttons/button.tsx @@ -1,4 +1,9 @@ -import { FC, MouseEventHandler, ReactNode } from 'react'; +import { + forwardRef, + ForwardRefRenderFunction, + MouseEventHandler, + ReactNode, +} from 'react'; import styles from './buttons.module.scss'; export type ButtonProps = { @@ -41,23 +46,27 @@ export type ButtonProps = { * * Use a button as call to action. */ -const Button: FC<ButtonProps> = ({ - className = '', - children, - disabled = false, - kind = 'secondary', - shape = 'rectangle', - type = 'button', - ...props -}) => { +const Button: ForwardRefRenderFunction<HTMLButtonElement, ButtonProps> = ( + { + className = '', + children, + disabled = false, + kind = 'secondary', + shape = 'rectangle', + type = 'button', + ...props + }, + ref +) => { const kindClass = styles[`btn--${kind}`]; const shapeClass = styles[`btn--${shape}`]; return ( <button - type={type} - disabled={disabled} className={`${styles.btn} ${kindClass} ${shapeClass} ${className}`} + disabled={disabled} + ref={ref} + type={type} {...props} > {children} @@ -65,4 +74,4 @@ const Button: FC<ButtonProps> = ({ ); }; -export default Button; +export default forwardRef(Button); diff --git a/src/components/molecules/buttons/help-button.tsx b/src/components/molecules/buttons/help-button.tsx index f19322f..e351453 100644 --- a/src/components/molecules/buttons/help-button.tsx +++ b/src/components/molecules/buttons/help-button.tsx @@ -1,5 +1,5 @@ import Button, { type ButtonProps } from '@components/atoms/buttons/button'; -import { FC } from 'react'; +import { forwardRef, ForwardRefRenderFunction } from 'react'; import { useIntl } from 'react-intl'; import styles from './help-button.module.scss'; @@ -15,7 +15,10 @@ export type HelpButtonProps = Pick<ButtonProps, 'onClick'> & { * * Render a button with an interrogation mark icon. */ -const HelpButton: FC<HelpButtonProps> = ({ className = '', onClick }) => { +const HelpButton: ForwardRefRenderFunction< + HTMLButtonElement, + HelpButtonProps +> = ({ className = '', onClick }, ref) => { const intl = useIntl(); const text = intl.formatMessage({ defaultMessage: 'Help', @@ -25,9 +28,10 @@ const HelpButton: FC<HelpButtonProps> = ({ className = '', onClick }) => { return ( <Button - shape="circle" className={`${styles.btn} ${className}`} onClick={onClick} + ref={ref} + shape="circle" > <span className="screen-reader-text">{text}</span> <span className={styles.icon}>?</span> @@ -35,4 +39,4 @@ const HelpButton: FC<HelpButtonProps> = ({ className = '', onClick }) => { ); }; -export default HelpButton; +export default forwardRef(HelpButton); diff --git a/src/components/molecules/forms/select-with-tooltip.tsx b/src/components/molecules/forms/select-with-tooltip.tsx index f576a15..29e2563 100644 --- a/src/components/molecules/forms/select-with-tooltip.tsx +++ b/src/components/molecules/forms/select-with-tooltip.tsx @@ -29,15 +29,21 @@ const SelectWithTooltip: FC<SelectWithTooltipProps> = ({ ...props }) => { const [isTooltipOpened, setIsTooltipOpened] = useState<boolean>(false); + const buttonRef = useRef<HTMLButtonElement>(null); const tooltipRef = useRef<HTMLDivElement>(null); const buttonModifier = isTooltipOpened ? styles['btn--activated'] : ''; const tooltipModifier = isTooltipOpened ? styles['tooltip--visible'] : styles['tooltip--hidden']; + const closeTooltip = (target: EventTarget) => { + if (buttonRef.current && !buttonRef.current.contains(target as Node)) + setIsTooltipOpened(false); + }; + useClickOutside( tooltipRef, - () => isTooltipOpened && setIsTooltipOpened(false) + (target) => isTooltipOpened && closeTooltip(target) ); return ( @@ -49,8 +55,9 @@ const SelectWithTooltip: FC<SelectWithTooltipProps> = ({ {...props} /> <HelpButton - onClick={() => setIsTooltipOpened(!isTooltipOpened)} className={`${styles.btn} ${buttonModifier}`} + onClick={() => setIsTooltipOpened(!isTooltipOpened)} + ref={buttonRef} /> <Tooltip title={title} diff --git a/src/utils/hooks/use-click-outside.tsx b/src/utils/hooks/use-click-outside.tsx index 066c1c2..cead98b 100644 --- a/src/utils/hooks/use-click-outside.tsx +++ b/src/utils/hooks/use-click-outside.tsx @@ -6,7 +6,10 @@ import { RefObject, useCallback, useEffect } from 'react'; * @param el - A React reference to an element. * @param callback - A callback function to execute on click outside. */ -const useClickOutside = (el: RefObject<HTMLElement>, callback: () => void) => { +const useClickOutside = ( + el: RefObject<HTMLElement>, + callback: (target: EventTarget) => void +) => { /** * Check if an event target is outside an element. * @@ -24,7 +27,7 @@ const useClickOutside = (el: RefObject<HTMLElement>, callback: () => void) => { const handleEvent = useCallback( (e: MouseEvent | FocusEvent) => { - if (e.target && isTargetOutside(el, e.target)) callback(); + if (e.target && isTargetOutside(el, e.target)) callback(e.target); }, [el, callback] ); |
