1
0
mirror of https://gitlab.nic.cz/turris/reforis/foris-js.git synced 2024-11-14 17:35:35 +01:00

Compare commits

..

No commits in common. "b7a4613cf45aad15a6a97559b0189dd817d1e4f0" and "c86e2c894459332b3294a4c6a7305f6dab0d0970" have entirely different histories.

5 changed files with 9 additions and 58 deletions

View File

@ -5,12 +5,10 @@
* See /LICENSE for more information. * See /LICENSE for more information.
*/ */
import React, { useRef } from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useFocusTrap } from "../utils/hooks";
export const ALERT_TYPES = Object.freeze({ export const ALERT_TYPES = Object.freeze({
PRIMARY: "primary", PRIMARY: "primary",
SECONDARY: "secondary", SECONDARY: "secondary",
@ -39,15 +37,11 @@ Alert.defaultProps = {
}; };
function Alert({ type, onDismiss, children }) { function Alert({ type, onDismiss, children }) {
const alertRef = useRef();
useFocusTrap(alertRef, !!onDismiss);
return ( return (
<div <div
ref={alertRef}
className={`alert alert-${type} ${ className={`alert alert-${type} ${
onDismiss ? "alert-dismissible" : "" onDismiss ? "alert-dismissible" : ""
}`.trim()} }`.trim()}
role="alert"
> >
{onDismiss && ( {onDismiss && (
<button <button

View File

@ -9,7 +9,7 @@ import React, { useRef, useEffect } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useClickOutside, useFocusTrap } from "../utils/hooks"; import { useClickOutside } from "../utils/hooks";
import Portal from "../utils/Portal"; import Portal from "../utils/Portal";
import "./Modal.css"; import "./Modal.css";
@ -29,11 +29,10 @@ Modal.propTypes = {
}; };
export function Modal({ shown, setShown, scrollable, size, children }) { export function Modal({ shown, setShown, scrollable, size, children }) {
const modalRef = useRef(); const dialogRef = useRef();
let modalSize = "modal-"; let modalSize = "modal-";
useClickOutside(modalRef, () => setShown(false)); useClickOutside(dialogRef, () => setShown(false));
useFocusTrap(modalRef, shown);
useEffect(() => { useEffect(() => {
const handleEsc = (event) => { const handleEsc = (event) => {
@ -66,13 +65,11 @@ export function Modal({ shown, setShown, scrollable, size, children }) {
return ( return (
<Portal containerId="modal-container"> <Portal containerId="modal-container">
<div <div
ref={modalRef}
className={`modal fade ${shown ? "show" : ""}`.trim()} className={`modal fade ${shown ? "show" : ""}`.trim()}
role="dialog" role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
> >
<div <div
ref={dialogRef}
className={`${modalSize.trim()} modal-dialog modal-dialog-centered ${ className={`${modalSize.trim()} modal-dialog modal-dialog-centered ${
scrollable ? "modal-dialog-scrollable" : "" scrollable ? "modal-dialog-scrollable" : ""
}`.trim()} }`.trim()}
@ -93,7 +90,7 @@ ModalHeader.propTypes = {
export function ModalHeader({ setShown, title }) { export function ModalHeader({ setShown, title }) {
return ( return (
<div className="modal-header"> <div className="modal-header">
<h1 className="modal-title fs-5">{title}</h1> <h5 className="modal-title">{title}</h5>
<button <button
type="button" type="button"
className="btn-close" className="btn-close"

View File

@ -6,8 +6,6 @@ exports[`<RebootButton/> Render modal. 1`] = `
id="modal-container" id="modal-container"
> >
<div <div
aria-labelledby="modal-title"
aria-modal="true"
class="modal fade show" class="modal fade show"
role="dialog" role="dialog"
> >
@ -21,11 +19,11 @@ exports[`<RebootButton/> Render modal. 1`] = `
<div <div
class="modal-header" class="modal-header"
> >
<h1 <h5
class="modal-title fs-5" class="modal-title"
> >
Warning! Warning!
</h1> </h5>
<button <button
aria-label="Close" aria-label="Close"
class="btn-close" class="btn-close"

View File

@ -7,7 +7,6 @@ exports[`AlertContext should render alert 1`] = `
> >
<div <div
class="alert alert-danger alert-dismissible" class="alert alert-danger alert-dismissible"
role="alert"
> >
<button <button
aria-label="Close" aria-label="Close"

View File

@ -40,40 +40,3 @@ export function useClickOutside(element, callback) {
}; };
}); });
} }
/* Trap focus inside element. */
export function useFocusTrap(elementRef, condition = true) {
useEffect(() => {
if (!condition) {
return;
}
const currentElement = elementRef.current;
const focusableElements = currentElement.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
const handleTab = (event) => {
if (event.key === "Tab") {
if (event.shiftKey) {
if (document.activeElement === firstElement) {
lastElement.focus();
event.preventDefault();
}
} else if (document.activeElement === lastElement) {
firstElement.focus();
event.preventDefault();
}
}
};
currentElement.addEventListener("keydown", handleTab);
firstElement.focus();
return () => {
currentElement.removeEventListener("keydown", handleTab);
};
}, [elementRef, condition]);
}