1
0
mirror of https://gitlab.nic.cz/turris/reforis/foris-js.git synced 2024-12-25 00:11:36 +01:00

Merge branch 'add-alert-animation-and-timeout' into 'dev'

Add Alert animation and timeout

See merge request turris/reforis/foris-js!249
This commit is contained in:
Aleksandr Gumroian 2024-10-02 13:48:31 +02:00
commit 6795c3941b
4 changed files with 27 additions and 8 deletions

View File

@ -5,7 +5,7 @@
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React, { useRef } from "react"; import React, { useRef, useEffect, useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
@ -40,20 +40,36 @@ Alert.defaultProps = {
function Alert({ type, onDismiss, children }) { function Alert({ type, onDismiss, children }) {
const alertRef = useRef(); const alertRef = useRef();
const [isVisible, setIsVisible] = useState(true);
useFocusTrap(alertRef, !!onDismiss); useFocusTrap(alertRef, !!onDismiss);
useEffect(() => {
if (onDismiss) {
const timeout = setTimeout(() => setIsVisible(false), 7000);
return () => clearTimeout(timeout);
}
}, [onDismiss]);
const handleAnimationEnd = () => {
if (!isVisible && onDismiss) {
onDismiss();
}
};
return ( return (
<div <div
ref={alertRef} ref={alertRef}
className={`alert alert-${type} ${ className={`alert alert-${type} ${isVisible ? "alert-fade-in" : "alert-slide-out-top"} ${
onDismiss ? "alert-dismissible" : "" onDismiss ? "alert-dismissible" : ""
}`.trim()} }`.trim()}
role="alert" role="alert"
onAnimationEnd={handleAnimationEnd}
> >
{onDismiss && ( {onDismiss && (
<button <button
type="button" type="button"
className="btn-close" className="btn-close"
onClick={onDismiss} onClick={() => setIsVisible(false)}
aria-label={_("Close")} aria-label={_("Close")}
/> />
)} )}

View File

@ -18,9 +18,9 @@ ThreeDotsMenu.propTypes = {
children: PropTypes.arrayOf(PropTypes.node).isRequired, children: PropTypes.arrayOf(PropTypes.node).isRequired,
}; };
function ThreeDotsMenu({ children }) { function ThreeDotsMenu({ children, ...props }) {
return ( return (
<div className="dropdown"> <div className="dropdown position-static" {...props}>
<Button <Button
className="btn-sm btn-link text-body" className="btn-sm btn-link text-body"
data-bs-toggle="dropdown" data-bs-toggle="dropdown"

View File

@ -43,14 +43,17 @@ describe("AlertContext", () => {
expect(componentContainer).toMatchSnapshot(); expect(componentContainer).toMatchSnapshot();
}); });
it("should dismiss alert with alert button", () => { it("should dismiss alert with alert button", async () => {
fireEvent.click(getByText(componentContainer, "Set alert")); fireEvent.click(getByText(componentContainer, "Set alert"));
// Alert is present // Alert is present
expect(getByText(componentContainer, "Alert content")).toBeDefined(); expect(getByText(componentContainer, "Alert content")).toBeDefined();
fireEvent.click(componentContainer.querySelector(".btn-close")); fireEvent.click(componentContainer.querySelector(".btn-close"));
// Alert is gone // Alert is gone
expect(queryByText(componentContainer, "Alert content")).toBeNull(); await (() =>
expect(
queryByText(componentContainer, "Alert content")
).toBeNull());
}); });
it("should dismiss alert with external button", () => { it("should dismiss alert with external button", () => {

View File

@ -6,7 +6,7 @@ exports[`AlertContext should render alert 1`] = `
id="alert-container" id="alert-container"
> >
<div <div
class="alert alert-danger alert-dismissible" class="alert alert-danger alert-fade-in alert-dismissible"
role="alert" role="alert"
> >
<button <button