mirror of
https://github.com/cheeaun/phanpy.git
synced 2025-02-09 01:26:24 +01:00
Rework the modal close + focus logic
- 'Esc' a modal will focus on "behind" nested modal - All modals will have 'esc'
This commit is contained in:
parent
fce5e45bc9
commit
27274eeab1
4 changed files with 46 additions and 28 deletions
|
@ -11,8 +11,6 @@ function AccountSheet({ account, instance: propInstance, onClose }) {
|
||||||
const { masto, instance, authenticated } = api({ instance: propInstance });
|
const { masto, instance, authenticated } = api({ instance: propInstance });
|
||||||
const isString = typeof account === 'string';
|
const isString = typeof account === 'string';
|
||||||
|
|
||||||
const escRef = useHotkeys('esc', onClose, [onClose]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isString) {
|
if (!isString) {
|
||||||
states.accounts[`${account.id}@${instance}`] = account;
|
states.accounts[`${account.id}@${instance}`] = account;
|
||||||
|
|
|
@ -2,10 +2,11 @@ import './modal.css';
|
||||||
|
|
||||||
import { createPortal } from 'preact/compat';
|
import { createPortal } from 'preact/compat';
|
||||||
import { useEffect, useRef } from 'preact/hooks';
|
import { useEffect, useRef } from 'preact/hooks';
|
||||||
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
|
|
||||||
const $modalContainer = document.getElementById('modal-container');
|
const $modalContainer = document.getElementById('modal-container');
|
||||||
|
|
||||||
function Modal({ children, onClick, class: className }) {
|
function Modal({ children, onClose, onClick, class: className }) {
|
||||||
if (!children) return null;
|
if (!children) return null;
|
||||||
|
|
||||||
const modalRef = useRef();
|
const modalRef = useRef();
|
||||||
|
@ -19,8 +20,28 @@ function Modal({ children, onClick, class: className }) {
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const escRef = useHotkeys('esc', onClose, [onClose], {
|
||||||
|
enabled: !!onClose,
|
||||||
|
});
|
||||||
|
|
||||||
const Modal = (
|
const Modal = (
|
||||||
<div ref={modalRef} className={className} onClick={onClick}>
|
<div
|
||||||
|
ref={(node) => {
|
||||||
|
modalRef.current = node;
|
||||||
|
escRef.current = node?.querySelector?.('[tabindex="-1"]') || node;
|
||||||
|
}}
|
||||||
|
className={className}
|
||||||
|
onClick={(e) => {
|
||||||
|
onClick?.(e);
|
||||||
|
if (e.target === e.currentTarget) {
|
||||||
|
onClose?.(e);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
tabIndex="-1"
|
||||||
|
onFocus={(e) => {
|
||||||
|
modalRef.current?.querySelector?.('[tabindex="-1"]')?.focus?.();
|
||||||
|
}}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -76,10 +76,8 @@ export default function Modals() {
|
||||||
)}
|
)}
|
||||||
{!!snapStates.showSettings && (
|
{!!snapStates.showSettings && (
|
||||||
<Modal
|
<Modal
|
||||||
onClick={(e) => {
|
onClose={() => {
|
||||||
if (e.target === e.currentTarget) {
|
states.showSettings = false;
|
||||||
states.showSettings = false;
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Settings
|
<Settings
|
||||||
|
@ -91,10 +89,8 @@ export default function Modals() {
|
||||||
)}
|
)}
|
||||||
{!!snapStates.showAccounts && (
|
{!!snapStates.showAccounts && (
|
||||||
<Modal
|
<Modal
|
||||||
onClick={(e) => {
|
onClose={() => {
|
||||||
if (e.target === e.currentTarget) {
|
states.showAccounts = false;
|
||||||
states.showAccounts = false;
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Accounts
|
<Accounts
|
||||||
|
@ -107,10 +103,8 @@ export default function Modals() {
|
||||||
{!!snapStates.showAccount && (
|
{!!snapStates.showAccount && (
|
||||||
<Modal
|
<Modal
|
||||||
class="light"
|
class="light"
|
||||||
onClick={(e) => {
|
onClose={() => {
|
||||||
if (e.target === e.currentTarget) {
|
states.showAccount = false;
|
||||||
states.showAccount = false;
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AccountSheet
|
<AccountSheet
|
||||||
|
@ -127,10 +121,8 @@ export default function Modals() {
|
||||||
)}
|
)}
|
||||||
{!!snapStates.showDrafts && (
|
{!!snapStates.showDrafts && (
|
||||||
<Modal
|
<Modal
|
||||||
onClick={(e) => {
|
onClose={() => {
|
||||||
if (e.target === e.currentTarget) {
|
states.showDrafts = false;
|
||||||
states.showDrafts = false;
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Drafts onClose={() => (states.showDrafts = false)} />
|
<Drafts onClose={() => (states.showDrafts = false)} />
|
||||||
|
@ -161,10 +153,8 @@ export default function Modals() {
|
||||||
{!!snapStates.showShortcutsSettings && (
|
{!!snapStates.showShortcutsSettings && (
|
||||||
<Modal
|
<Modal
|
||||||
class="light"
|
class="light"
|
||||||
onClick={(e) => {
|
onClose={() => {
|
||||||
if (e.target === e.currentTarget) {
|
states.showShortcutsSettings = false;
|
||||||
states.showShortcutsSettings = false;
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ShortcutsSettings
|
<ShortcutsSettings
|
||||||
|
@ -175,10 +165,8 @@ export default function Modals() {
|
||||||
{!!snapStates.showGenericAccounts && (
|
{!!snapStates.showGenericAccounts && (
|
||||||
<Modal
|
<Modal
|
||||||
class="light"
|
class="light"
|
||||||
onClick={(e) => {
|
onClose={() => {
|
||||||
if (e.target === e.currentTarget) {
|
states.showGenericAccounts = false;
|
||||||
states.showGenericAccounts = false;
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<GenericAccounts
|
<GenericAccounts
|
||||||
|
|
|
@ -5,6 +5,17 @@ const focusDeck = () => {
|
||||||
// Focus first column
|
// Focus first column
|
||||||
// columns.querySelector('.deck-container')?.focus?.();
|
// columns.querySelector('.deck-container')?.focus?.();
|
||||||
} else {
|
} else {
|
||||||
|
const modals = document.querySelectorAll('#modal-container > *');
|
||||||
|
if (modals?.length) {
|
||||||
|
// Focus last modal
|
||||||
|
const modal = modals[modals.length - 1]; // last one
|
||||||
|
const modalFocusElement =
|
||||||
|
modal.querySelector('[tabindex="-1"]') || modal;
|
||||||
|
if (modalFocusElement) {
|
||||||
|
modalFocusElement.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
const backDrop = document.querySelector('.deck-backdrop');
|
const backDrop = document.querySelector('.deck-backdrop');
|
||||||
if (backDrop) return;
|
if (backDrop) return;
|
||||||
// Focus last deck
|
// Focus last deck
|
||||||
|
|
Loading…
Reference in a new issue