diff --git a/src/components/Onboarding.tsx b/src/components/Onboarding.tsx index 63ae244..08a87c1 100644 --- a/src/components/Onboarding.tsx +++ b/src/components/Onboarding.tsx @@ -1,6 +1,7 @@ import { useState, useEffect, useCallback, useRef } from 'react'; import { createPortal } from 'react-dom'; import { useTranslation } from 'react-i18next'; +import { useFocusTrap } from '../hooks/useFocusTrap'; interface OnboardingStep { target: string; // data-onboarding attribute value @@ -126,6 +127,17 @@ export default function Onboarding({ steps, onComplete, onSkip }: OnboardingProp onSkip(); }; + // Trap focus inside the tooltip while the tour runs; Esc skips it. + // lockScroll stays off so scrollIntoView can bring each target into view. + const trapRef = useFocusTrap(true, { onEscape: handleSkip, lockScroll: false }); + const setTooltipNode = useCallback( + (node: HTMLDivElement | null) => { + tooltipRef.current = node; + trapRef.current = node; + }, + [trapRef], + ); + // Calculate tooltip position const getTooltipStyle = (): React.CSSProperties => { if (!targetRect) return { opacity: 0 }; @@ -205,7 +217,11 @@ export default function Onboarding({ steps, onComplete, onSkip }: OnboardingProp {/* Tooltip */}
{/* Content */} -

{step.title}

-

{step.description}

+

+ {step.title} +

+

+ {step.description} +

{/* Actions */}
@@ -259,6 +279,7 @@ export default function Onboarding({ steps, onComplete, onSkip }: OnboardingProp {/* Click handler to advance on target click — only when overlay is fully visible */} {targetRect && isVisible && (