Fix keyboard shortcuts bugs (#2936)

This PR moves the focus 

### Change Type

- [x] `minor` 

### Test Plan

1. Select an element.
2. Press the delete quick action menu button.
3. Undo the delete with a keyboard shortcut.

1. Create a geo shape
2. Use the style panel to change the geo type
3. Undo so that it deletes
4. Try to redo

### Release Notes

- [Fix] Keyboard shortcut focus bug

---------

Co-authored-by: David Sheldrick <d.j.sheldrick@gmail.com>
pull/2940/head
Steve Ruiz 2024-02-23 15:35:13 +00:00 zatwierdzone przez GitHub
rodzic fcf97958e8
commit 37bd92ef60
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
5 zmienionych plików z 67 dodań i 3 usunięć

Wyświetl plik

@ -0,0 +1,44 @@
import { Editor, Tldraw } from '@tldraw/tldraw'
import '@tldraw/tldraw/tldraw.css'
import { useEffect, useRef, useState } from 'react'
export default function EditorFocusExample() {
const [focused, setFocused] = useState(false)
const rEditorRef = useRef<Editor | null>(null)
useEffect(() => {
const editor = rEditorRef.current
if (!editor) return
editor.updateInstanceState({ isFocused: focused })
}, [focused])
return (
<div style={{ padding: 32 }}>
<div style={{ display: 'flex', gap: 4 }}>
<input
id={'focus'}
type={'checkbox'}
onChange={(e) => {
setFocused(e.target.checked)
}}
/>
<label htmlFor={'focus'}>Focus</label>
</div>
<p>
The checkbox controls the editor's <code>instanceState.isFocused</code> property.
</p>
<p>
When the editor is "focused", its keyboard shortcuts will work. When it is not focused, the
keyboard shortcuts will not work.
</p>
<div style={{ width: 800, maxWidth: '100%', height: 500 }}>
<Tldraw
autoFocus={false}
onMount={(editor) => {
rEditorRef.current = editor
}}
/>
</div>
</div>
)
}

Wyświetl plik

@ -0,0 +1,18 @@
---
title: Editor focus
component: ./EditorFocusExample.tsx
category: basic
priority: 7
---
The editor's keyboard shortcuts only work when the editor is "focused".
---
In this example, we drive the editor's focus in order to turn on and off keyboard shortcuts.
The editor's focus is different from—but usually corresponds to—the browser's concept of "focus", which is related to the document's [active element](https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement).
Unfortunately, the browser's focus cannot be relied on to determine whether the editor's keyboard shortcuts should work. While its possible to detect whether the document's active element is a descendant of the Tldraw component's own element, it's not 100% reliable. For example, iframes are not considered descendants of their parents, and many menus are portalled into different parts of the document tree.
For these reasons, the responsibility falls to you, dear developer, to manage focus for your Tldraw editor, especially in cases where there are more than one editor on the same page.

Wyświetl plik

@ -31,6 +31,8 @@ export default function MultipleExample() {
backgroundColor: '#fff',
padding: 32,
}}
// Sorry you need to do this yourself
onPointerDown={() => setFocusedEditor(null)}
>
<focusedEditorContext.Provider value={{ focusedEditor, setFocusedEditor }}>
<h1>Focusing: {focusedEditor ?? 'none'}</h1>

Wyświetl plik

@ -2,7 +2,7 @@
title: Multiple editors
component: ./MultipleExample.tsx
category: basic
priority: 7
priority: 8
---
Use multiple `<Tldraw/>` components on the same page.

Wyświetl plik

@ -33,13 +33,13 @@ export function useKeyboardShortcuts() {
hotkeys.setScope(editor.store.id)
const hot = (keys: string, callback: (event: KeyboardEvent) => void) => {
hotkeys(keys, { element: container, scope: editor.store.id }, callback)
hotkeys(keys, { element: document.body, scope: editor.store.id }, callback)
}
const hotUp = (keys: string, callback: (event: KeyboardEvent) => void) => {
hotkeys(
keys,
{ element: container, keyup: true, keydown: false, scope: editor.store.id },
{ element: document.body, keyup: true, keydown: false, scope: editor.store.id },
callback
)
}