forked from Navy.gif/webserver-framework-frontend
close element if clicked outside
This commit is contained in:
parent
74b4c343ea
commit
583e2eb8af
@ -1,24 +1,41 @@
|
|||||||
import React from "react";
|
import React, { useRef } from "react";
|
||||||
import '../css/components/UserControls.css';
|
import '../css/components/UserControls.css';
|
||||||
import { useLoginContext } from "../structures/UserContext";
|
import { useLoginContext } from "../structures/UserContext";
|
||||||
|
import ClickDetector from "../util/ClickDetector";
|
||||||
|
import { clearSession, post } from "../util/Util";
|
||||||
|
|
||||||
const UserControls = () => {
|
const UserControls = () => {
|
||||||
|
|
||||||
const [user] = useLoginContext();
|
const [user, updateUser] = useLoginContext();
|
||||||
|
const detailsRef = useRef();
|
||||||
|
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|
||||||
return <details className='dropdown user-controls'>
|
const logOut = async () => {
|
||||||
<summary className="is-vertical-align">
|
const response = await post('/api/logout');
|
||||||
Hello {user.displayName}
|
if (response.status === 200) {
|
||||||
<img className="profile-picture" src="https://cdn.discordapp.com/avatars/187613017733726210/ee764860975d78bfd52652c6ddaed47b.webp?size=64"></img>
|
clearSession();
|
||||||
</summary>
|
updateUser();
|
||||||
<div className="card">
|
}
|
||||||
<p><a href="#">Profile</a></p>
|
};
|
||||||
<hr/>
|
|
||||||
<p><a href="#" className="text-error">Logout</a></p>
|
return <ClickDetector callback={() => {
|
||||||
</div>
|
if (detailsRef.current) detailsRef.current.removeAttribute('open');
|
||||||
</details>;
|
}}>
|
||||||
|
<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
35
src/util/ClickDetector.js
Normal 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;
|
Reference in New Issue
Block a user