close element if clicked outside

This commit is contained in:
Erik 2022-11-24 00:00:50 +02:00
parent 74b4c343ea
commit 583e2eb8af
Signed by untrusted user: Navy.gif
GPG Key ID: 811EC0CD80E7E5FB
2 changed files with 65 additions and 13 deletions

View File

@ -1,24 +1,41 @@
import React from "react";
import React, { useRef } from "react";
import '../css/components/UserControls.css';
import { useLoginContext } from "../structures/UserContext";
import ClickDetector from "../util/ClickDetector";
import { clearSession, post } from "../util/Util";
const UserControls = () => {
const [user] = useLoginContext();
const [user, updateUser] = useLoginContext();
const detailsRef = useRef();
if (!user) return;
return <details className='dropdown user-controls'>
<summary className="is-vertical-align">
Hello {user.displayName}
<img className="profile-picture" src="https://cdn.discordapp.com/avatars/187613017733726210/ee764860975d78bfd52652c6ddaed47b.webp?size=64"></img>
</summary>
<div className="card">
<p><a href="#">Profile</a></p>
<hr/>
<p><a href="#" className="text-error">Logout</a></p>
</div>
</details>;
const logOut = async () => {
const response = await post('/api/logout');
if (response.status === 200) {
clearSession();
updateUser();
}
};
return <ClickDetector callback={() => {
if (detailsRef.current) detailsRef.current.removeAttribute('open');
}}>
<details ref={detailsRef} className='dropdown user-controls'>
<summary className="is-vertical-align">
Hello {user.displayName}
<img className="profile-picture" src="https://cdn.discordapp.com/avatars/187613017733726210/ee764860975d78bfd52652c6ddaed47b.webp?size=64"></img>
</summary>
<div className="card">
<p><a href="#">Profile</a></p>
<hr />
<p><a onClick={logOut} href="#" className="text-error">Logout</a></p>
</div>
</details>
</ClickDetector >;
};

35
src/util/ClickDetector.js Normal file
View File

@ -0,0 +1,35 @@
import React, { useEffect, useRef } from "react";
const alerter = (ref, callback) => {
useEffect(() => {
const listener = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
return callback();
}
};
document.addEventListener('mousedown', listener);
return () => {
document.removeEventListener('mousedown', listener);
};
}, [ref]);
};
// Component wrapper to enable listening for clicks outside of the given component
const ClickDetector = ({ children, callback }) => {
const wrapperRef = useRef(null);
alerter(wrapperRef, callback);
return (
<div ref={wrapperRef}>
{children}
</div>
);
};
export default ClickDetector;