diff --git a/packages/editor/src/components/collab-sidebar/README.md b/packages/editor/src/components/collab-sidebar/README.md index eb5bb7f9416c96..7fac76541f0956 100644 --- a/packages/editor/src/components/collab-sidebar/README.md +++ b/packages/editor/src/components/collab-sidebar/README.md @@ -5,7 +5,7 @@ The Notes sidebar (a.k.a. collab sidebar) lets users attach threaded notes to in - **All notes** - a full sidebar (opened from the editor's More menu) listing every note thread on the current post. - **Floating notes** - on larger viewports, unresolved notes float next to their associated blocks, overlaying space reserved at the right edge of the canvas, positioned to track scroll and avoid overlap. The floating notes are part of the canvas surface: they occupy no sidebar, so they can coexist with the Settings sidebar and leave notices and the canvas scrollbar at the full editor width. -The floating notes render full threads, minimized avatar pills, or nothing; the mode is chosen from a "Notes" submenu in the Tools group of the editor's Options (ellipsis) menu, and also adapts automatically to the canvas width: full threads collapse to minimized pills when the canvas gets too narrow to fit them next to a readable content column, and even the pills yield when the canvas can't spare their reserved space (the "All notes" sidebar remains available throughout). +The floating notes render full threads, minimized avatar pills, or nothing; the mode is chosen from a "Notes" submenu in the Tools group of the editor's Options (ellipsis) menu (or with the `access` shortcuts `E`, `I` and `J`, shown alongside each choice), and also adapts automatically to the canvas width: full threads collapse to minimized pills when the canvas gets too narrow to fit them next to a readable content column, and even the pills yield when the canvas can't spare their reserved space (the "All notes" sidebar remains available throughout). Notes are stored as WordPress comments (`type: 'note'`) attached to the post. A block references its thread via `metadata.noteId` on block attributes. Each thread has a top-level note plus replies; threads can be resolved (stored as status `approved`) or reopened. diff --git a/packages/editor/src/components/collab-sidebar/index.jsx b/packages/editor/src/components/collab-sidebar/index.jsx index 16f82153360850..8b47559f694ab4 100644 --- a/packages/editor/src/components/collab-sidebar/index.jsx +++ b/packages/editor/src/components/collab-sidebar/index.jsx @@ -165,6 +165,35 @@ function NotesSidebar( { postId } ) { } ); + // Keyboard equivalents for the display-mode choices in the Options menu, + // available wherever those choices are. + const notesDisplayShortcutsDisabled = + isDistractionFree || ! showNotesDisplayOptions; + useShortcut( + 'core/editor/expand-notes', + ( event ) => { + event.preventDefault(); + applyNotesDisplayMode( 'full' ); + }, + { isDisabled: notesDisplayShortcutsDisabled } + ); + useShortcut( + 'core/editor/minimize-notes', + ( event ) => { + event.preventDefault(); + applyNotesDisplayMode( 'minimized' ); + }, + { isDisabled: notesDisplayShortcutsDisabled } + ); + useShortcut( + 'core/editor/hide-notes', + ( event ) => { + event.preventDefault(); + applyNotesDisplayMode( 'hidden' ); + }, + { isDisabled: notesDisplayShortcutsDisabled } + ); + // Surface one thread for the avatar indicator. const currentThreads = blockNoteIds.length > 0 diff --git a/packages/editor/src/components/collab-sidebar/notes-display-mode-menu.tsx b/packages/editor/src/components/collab-sidebar/notes-display-mode-menu.tsx index 59d69c1e8caa87..2ab2b2dcb860c4 100644 --- a/packages/editor/src/components/collab-sidebar/notes-display-mode-menu.tsx +++ b/packages/editor/src/components/collab-sidebar/notes-display-mode-menu.tsx @@ -1,7 +1,10 @@ import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; import { comment as commentIcon } from '@wordpress/icons'; // eslint-disable-next-line @wordpress/use-recommended-components import { Menu } from '@wordpress/ui'; +import type { ComponentProps } from 'react'; import NotesMoreMenuGroup from '../more-menu/notes-more-menu-group'; /** @@ -17,6 +20,71 @@ type NotesDisplayModeMenuProps = { onChange: ( value: NotesDisplayMode ) => void; }; +const CHOICES: { + value: NotesDisplayMode; + label: string; + shortcutName: string; +}[] = [ + { + value: 'hidden', + label: __( 'Hide notes' ), + shortcutName: 'core/editor/hide-notes', + }, + { + value: 'minimized', + label: __( 'Minimize notes' ), + shortcutName: 'core/editor/minimize-notes', + }, + { + value: 'full', + label: __( 'Expand notes' ), + shortcutName: 'core/editor/expand-notes', + }, +]; + +type NotesDisplayModeItemProps = { + value: NotesDisplayMode; + label: string; + shortcutName: string; +}; + +/** + * Renders one display-mode choice, advertising its keyboard shortcut + * alongside the label. + * + * @param props Component props. + * @param props.value The display mode the choice selects. + * @param props.label The label of the choice. + * @param props.shortcutName The registered shortcut that selects the mode. + */ +function NotesDisplayModeItem( { + value, + label, + shortcutName, +}: NotesDisplayModeItemProps ) { + const shortcut = useSelect( + ( select ) => + select( keyboardShortcutsStore ).getKeyboardShortcut( + shortcutName + ), + [ shortcutName ] + ); + + return ( +