0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2025-12-25 03:12:40 +00:00
Files
homebrewery/client/components/anchoredBox.jsx
Gazook89 a3dbaf9e6a refactor anchoredBox to handle focus
Refactoring the AnchoredBox component because I wanted to set focus on the trigger button when the expanded box was closed.  Wrapping the trigger into it's own component, with forwardRef, allows for passing the `ref` to the actual DOM node.  Then the `.focus()` method will work on it.
2024-10-11 22:34:40 -05:00

78 lines
1.8 KiB
JavaScript

import React, { useState, useRef, useEffect, forwardRef } from 'react';
import './anchoredBox.less';
const AnchoredBox = ({ anchorPoint = 'center', className, children, ...props })=>{
const [visible, setVisible] = useState(false);
const triggerRef = useRef(null);
const boxRef = useRef(null);
useEffect(()=>{
const handleClickOutside = (evt)=>{
if(
boxRef.current &&
!boxRef.current.contains(evt.target) &&
triggerRef.current &&
!triggerRef.current.contains(evt.target)
) {
setVisible(false);
}
};
window.addEventListener('click', handleClickOutside);
const iframe = document.querySelector('iframe');
if(iframe) {
iframe.addEventListener('load', ()=>{
const iframeDoc = iframe.contentWindow.document;
if(iframeDoc) {
iframeDoc.addEventListener('click', handleClickOutside);
}
});
}
return ()=>{
window.removeEventListener('click', handleClickOutside);
if(iframe?.contentWindow?.document) {
iframe.contentWindow.document.removeEventListener('click', handleClickOutside);
}
};
}, []);
const handleClick = ()=>{
setVisible(!visible);
triggerRef.current?.focus();
};
const handleKeyDown = (evt)=>{
if(evt.key === 'Escape') {
setVisible(false);
triggerRef.current?.focus();
}
};
return (
<>
<TriggerButton
className={`${className} anchored-trigger${visible ? ' active' : ''}`}
onClick={handleClick}
ref={triggerRef}
/>
<div
className={`anchored-box${visible ? ' active' : ''}`}
ref={boxRef}
onKeyDown={(evt)=>handleKeyDown(evt)}
>
<h1>{props.title}</h1>
{children}
</div>
</>
);
};
const TriggerButton = forwardRef((props, ref)=>(
<button ref={ref} {...props}>
<i className='fas fa-gear' />
</button>
));
export default AnchoredBox;