feat: Add stopPropagation and event access support to useHover hook
๐ฏ Fixes Issue
Resolves streamich/react-use#2481
๐ Problem
I encountered a use case where I have multiple nested hoverable elements, and hovering over a child element triggers the hover on the parent as well due to event bubbling. I also needed access to the actual mouse events for more advanced hover interactions.
๐ง Solution
I've enhanced the useHover hook with optional configuration options that solve both issues while maintaining 100% backward compatibility.
1. stopPropagation Option
Prevents hover events from bubbling to parent elements: jsx const [childHoverable] = useHover( (hovered) =>
2. Event Access
Provides access to mouse events for advanced use cases: jsx const [hoverable] = useHover( (hovered) =>
3. Combined Usage
You can use both options together: jsx const [element] = useHover( (hovered) =>
โ Features
- โ 100% Backward Compatible - All existing code continues to work unchanged
- โ TypeScript Support - Full type safety with UseHoverOptions interface
- โ Event Propagation Control - Optional stopPropagation parameter
- โ Event Access - onMouseEnter/onMouseLeave callbacks with full event objects
- โ Preserves Original Handlers - Existing element handlers are maintained
- โ Production Ready - Comprehensive tests, documentation, and examples
๐ Files Changed
- src/useHover.ts - Enhanced hook implementation with new options
- src/index.ts - Updated TypeScript exports
- docs/useHover.md - Updated documentation with usage examples
- stories/useHover.story.tsx - Added comprehensive demo stories showing nested behavior
- tests/useHover.test.tsx - Added 17 comprehensive tests covering all scenarios
๐งช Testing
I've added comprehensive test coverage:
- โ Backward compatibility tests (no breaking changes)
- โ stopPropagation functionality tests
- โ Event callback access tests
- โ Combined options tests
- โ Edge case handling tests
- โ All 17 tests pass
- โ TypeScript compilation successful
- โ ESLint passes
๐ Type Definition
typescript interface UseHoverOptions { /** Prevents hover events from bubbling to parent elements / stopPropagation?: boolean; /* Callback when mouse enters - provides access to mouse event / onMouseEnter?: (event: React.MouseEvent) => void; /* Callback when mouse leaves - provides access to mouse event */ onMouseLeave?: (event: React.MouseEvent) => void; }
const useHover = (
element: Element,
options?: UseHoverOptions
): [React.ReactElement
This enhancement makes useHover much more powerful for complex interactive UIs while maintaining the simplicity that makes react-use great.