feat: Bind keyboard events to the current excalidraw container and add handleKeyboardGlobally prop to allow host to bind to document (#3430)

* fix: Bind keyboard events to excalidraw container

* fix cases around blurring

* fix modal rendering so keyboard shortcuts work on modal as well

* Revert "fix modal rendering so keyboard shortcuts work on modal as well"

This reverts commit 2c8ec6be8e.

* Attach keyboard event in react way so we need not handle portals separately (modals)

* dnt propagate esc event when modal shown

* focus the container when help dialog closed with shift+?

* focus the help icon when help dialog on close triggered

* move focusNearestTabbableParent to util

* rename util to focusNearestParent and remove outline from excal and modal

* Add prop bindKeyGlobally to decide if keyboard events should be binded to document and allow it in excal app, revert tests

* fix

* focus container after installing library, reset library and closing error dialog

* fix tests and create util to focus container

* Add excalidraw-container class to focus on the container

* pass focus container to library to focus current instance of excal

* update docs

* remove util as it wont be used anywhere

* fix propagation not being stopped for React keyboard handling

* tweak reamde

Co-authored-by: David Luzar <luzar.david@gmail.com>

* tweak changelog

* rename prop to handleKeyboardGlobally

Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
Aakansha Doshi 2021-04-13 01:29:25 +05:30 committed by GitHub
parent 153ca6a7c6
commit d126d04d17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 537 additions and 409 deletions

View file

@ -72,6 +72,7 @@ interface LayerUIProps {
viewModeEnabled: boolean;
libraryReturnUrl: ExcalidrawProps["libraryReturnUrl"];
UIOptions: AppProps["UIOptions"];
focusContainer: () => void;
}
const useOnClickOutside = (
@ -111,6 +112,7 @@ const LibraryMenuItems = ({
setAppState,
setLibraryItems,
libraryReturnUrl,
focusContainer,
}: {
library: LibraryItems;
pendingElements: LibraryItem;
@ -120,6 +122,7 @@ const LibraryMenuItems = ({
setAppState: React.Component<any, AppState>["setState"];
setLibraryItems: (library: LibraryItems) => void;
libraryReturnUrl: ExcalidrawProps["libraryReturnUrl"];
focusContainer: () => void;
}) => {
const isMobile = useIsMobile();
const numCells = library.length + (pendingElements.length > 0 ? 1 : 0);
@ -178,6 +181,7 @@ const LibraryMenuItems = ({
if (window.confirm(t("alerts.resetLibrary"))) {
Library.resetLibrary();
setLibraryItems([]);
focusContainer();
}
}}
/>
@ -242,6 +246,7 @@ const LibraryMenu = ({
onAddToLibrary,
setAppState,
libraryReturnUrl,
focusContainer,
}: {
pendingElements: LibraryItem;
onClickOutside: (event: MouseEvent) => void;
@ -249,6 +254,7 @@ const LibraryMenu = ({
onAddToLibrary: () => void;
setAppState: React.Component<any, AppState>["setState"];
libraryReturnUrl: ExcalidrawProps["libraryReturnUrl"];
focusContainer: () => void;
}) => {
const ref = useRef<HTMLDivElement | null>(null);
useOnClickOutside(ref, (event) => {
@ -322,6 +328,7 @@ const LibraryMenu = ({
setAppState={setAppState}
setLibraryItems={setLibraryItems}
libraryReturnUrl={libraryReturnUrl}
focusContainer={focusContainer}
/>
)}
</Island>
@ -347,6 +354,7 @@ const LayerUI = ({
viewModeEnabled,
libraryReturnUrl,
UIOptions,
focusContainer,
}: LayerUIProps) => {
const isMobile = useIsMobile();
@ -517,6 +525,7 @@ const LayerUI = ({
onAddToLibrary={deselectItems}
setAppState={setAppState}
libraryReturnUrl={libraryReturnUrl}
focusContainer={focusContainer}
/>
) : null;
@ -660,7 +669,15 @@ const LayerUI = ({
/>
)}
{appState.showHelpDialog && (
<HelpDialog onClose={() => setAppState({ showHelpDialog: false })} />
<HelpDialog
onClose={() => {
const helpIcon = document.querySelector(
".help-icon",
)! as HTMLElement;
helpIcon.focus();
setAppState({ showHelpDialog: false });
}}
/>
)}
{appState.pasteDialog.shown && (
<PasteChartDialog