Last active
October 8, 2024 21:42
-
-
Save hexadeciman/97948f8cc0c95a7e522acec4da7549e3 to your computer and use it in GitHub Desktop.
useHighlight - a hook that allows you to highlight new functionalities
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Backdrop fade in/out */ | |
.highlight-backdrop { | |
@apply fixed inset-0 bg-black bg-opacity-50 transition-opacity duration-300 opacity-0 pointer-events-none; | |
z-index: 1000; | |
} | |
.backdrop-visible { | |
@apply opacity-100 pointer-events-auto; /* Show the backdrop */ | |
} | |
/* Got it button fade in/out */ | |
.got-it-button { | |
@apply absolute bg-gray-200 text-black font-semibold px-4 py-2 rounded-full transition-opacity duration-300 opacity-0 pointer-events-none; | |
z-index: 1001; | |
} | |
.button-visible { | |
@apply opacity-100 pointer-events-auto; /* Show the button */ | |
} | |
/* Positioning logic based on props */ | |
.top { | |
@apply top-0 left-1/2 transform -translate-x-1/2 mt-4; | |
} | |
.top-right { | |
@apply top-0 right-0 mt-4 mr-4; | |
} | |
.bottom { | |
@apply bottom-0 left-1/2 transform -translate-x-1/2 mb-4; | |
} | |
.bottom-right { | |
@apply bottom-[-50px] right-0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useState, RefObject } from 'react'; | |
import './useHighlight.scss'; | |
type Position = 'top' | 'bottom' | 'bottom-right' | 'top-right'; | |
interface UseHighlightProps { | |
elementRef: RefObject<HTMLElement>; // Ref to the element you want to highlight | |
position?: Position; // Position of the dismiss button | |
buttonMessage?: string; // Text for the "Got it" button | |
open?: boolean; // Whether the highlight should be open or closed | |
onDismiss?: () => void; // Callback when the highlight is dismissed | |
} | |
export const useHighlight = ({ | |
elementRef, | |
position = 'top', | |
buttonMessage = 'Got it', | |
open = false, | |
onDismiss, | |
}: UseHighlightProps) => { | |
const [isVisible, setIsVisible] = useState(open); | |
useEffect(() => { | |
setIsVisible(open); | |
}, [open]); | |
useEffect(() => { | |
if (!elementRef.current || !isVisible) return; | |
const element = elementRef.current; | |
// Set the element on top of everything | |
element.style.position = 'relative'; | |
element.style.zIndex = '1001'; | |
// Create and add the backdrop | |
const backdrop = document.createElement('div'); | |
backdrop.className = 'highlight-backdrop'; | |
document.body.appendChild(backdrop); | |
// Create and add the "Got it" button | |
const gotItButton = document.createElement('button'); | |
gotItButton.innerText = buttonMessage; | |
gotItButton.className = `got-it-button ${position}`; | |
gotItButton.onclick = () => { | |
// Fade out both the backdrop and button before removal | |
backdrop.classList.remove('backdrop-visible'); | |
gotItButton.classList.remove('button-visible'); | |
setTimeout(() => { | |
setIsVisible(false); // Hide button after animation completes | |
onDismiss?.(); // Call the dismiss callback if it exists | |
}, 300); // Match the duration of the transition | |
}; | |
// Append button to the target element | |
element.appendChild(gotItButton); | |
// Trigger the fade-in by adding the visibility classes | |
setTimeout(() => { | |
backdrop.classList.add('backdrop-visible'); | |
gotItButton.classList.add('button-visible'); | |
}, 10); // Ensure transition applies | |
// Cleanup function when component unmounts | |
return () => { | |
backdrop.remove(); | |
gotItButton.remove(); | |
element.style.zIndex = ''; // Reset z-index | |
}; | |
}, [elementRef, isVisible, position, buttonMessage, onDismiss]); | |
return { isVisible, setIsVisible }; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment