Commit 1afc7062 authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Allow notebook to be closed by pressing Esc

parent 1d898d40
import { IconButton, CancelIcon } from '@hypothesis/frontend-shared'; import { IconButton, CancelIcon } from '@hypothesis/frontend-shared';
import classnames from 'classnames'; import classnames from 'classnames';
import type { ComponentChildren } from 'preact'; import type { ComponentChildren } from 'preact';
import { useEffect, useMemo, useRef, useState } from 'preact/hooks'; import {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'preact/hooks';
import { addConfigFragment } from '../../shared/config-fragment'; import { addConfigFragment } from '../../shared/config-fragment';
import { createAppConfig } from '../config/app'; import { createAppConfig } from '../config/app';
...@@ -56,9 +62,13 @@ export type NotebookModalProps = { ...@@ -56,9 +62,13 @@ export type NotebookModalProps = {
document_?: Document; document_?: Document;
}; };
type DialogProps = { isHidden: boolean; children: ComponentChildren }; type DialogProps = {
isHidden: boolean;
children: ComponentChildren;
onClose: () => void;
};
const NativeDialog = ({ isHidden, children }: DialogProps) => { const NativeDialog = ({ isHidden, children, onClose }: DialogProps) => {
const dialogRef = useRef<HTMLDialogElement | null>(null); const dialogRef = useRef<HTMLDialogElement | null>(null);
useEffect(() => { useEffect(() => {
...@@ -69,18 +79,14 @@ const NativeDialog = ({ isHidden, children }: DialogProps) => { ...@@ -69,18 +79,14 @@ const NativeDialog = ({ isHidden, children }: DialogProps) => {
} }
}, [isHidden]); }, [isHidden]);
// Prevent the dialog from closing when `Esc` is pressed, to keep previous
// behavior
useEffect(() => { useEffect(() => {
const dialogElement = dialogRef.current; const dialogElement = dialogRef.current;
const listener = (event: Event) => event.preventDefault();
dialogElement?.addEventListener('cancel', listener);
dialogElement?.addEventListener('cancel', onClose);
return () => { return () => {
dialogElement?.removeEventListener('cancel', listener); dialogElement?.removeEventListener('cancel', onClose);
}; };
}, []); }, [onClose]);
return ( return (
<dialog <dialog
...@@ -171,17 +177,17 @@ export default function NotebookModal({ ...@@ -171,17 +177,17 @@ export default function NotebookModal({
}; };
}, [eventBus]); }, [eventBus]);
const onClose = () => { const onClose = useCallback(() => {
setIsHidden(true); setIsHidden(true);
emitterRef.current?.publish('closeNotebook'); emitterRef.current?.publish('closeNotebook');
}; }, []);
if (groupId === null) { if (groupId === null) {
return null; return null;
} }
return ( return (
<Dialog isHidden={isHidden}> <Dialog isHidden={isHidden} onClose={onClose}>
<div className="absolute right-0 m-3"> <div className="absolute right-0 m-3">
<IconButton <IconButton
title="Close the Notebook" title="Close the Notebook"
......
...@@ -173,6 +173,14 @@ describe('NotebookModal', () => { ...@@ -173,6 +173,14 @@ describe('NotebookModal', () => {
assert.isTrue(wrapper.exists('dialog')); assert.isTrue(wrapper.exists('dialog'));
}); });
[
// Close via clicking close button
wrapper => getCloseButton(wrapper).props().onClick(),
// Close via "cancel" event, like pressing `Esc` key
wrapper =>
wrapper.find('dialog').getDOMNode().dispatchEvent(new Event('cancel')),
].forEach(closeDialog => {
it('opens and closes native dialog', () => { it('opens and closes native dialog', () => {
const wrapper = createComponent({}); const wrapper = createComponent({});
const isDialogOpen = () => wrapper.find('dialog').getDOMNode().open; const isDialogOpen = () => wrapper.find('dialog').getDOMNode().open;
...@@ -181,11 +189,12 @@ describe('NotebookModal', () => { ...@@ -181,11 +189,12 @@ describe('NotebookModal', () => {
wrapper.update(); wrapper.update();
assert.isTrue(isDialogOpen()); assert.isTrue(isDialogOpen());
act(() => getCloseButton(wrapper).prop('onClick')()); act(() => closeDialog(wrapper));
wrapper.update(); wrapper.update();
assert.isFalse(isDialogOpen()); assert.isFalse(isDialogOpen());
}); });
}); });
});
it('resets document scrollability on closing the modal', () => { it('resets document scrollability on closing the modal', () => {
const wrapper = createComponent(); const wrapper = createComponent();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment