aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/components/atoms/buttons/button.tsx35
-rw-r--r--src/components/molecules/buttons/help-button.tsx12
-rw-r--r--src/components/molecules/forms/select-with-tooltip.tsx11
-rw-r--r--src/utils/hooks/use-click-outside.tsx7
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]
);