From d727b2b9226ae532a75787b66828030bf1e7b33f Mon Sep 17 00:00:00 2001 From: Jacob Topp-Mugglestone <55137073+jacobtoppm@users.noreply.github.com> Date: Fri, 16 Apr 2021 18:11:56 +0100 Subject: [PATCH] Feature/commenting a11y pass 1 (#7016) * Add a keyboard shortcut to Draftail for adding/focusing comments * Increase the timeout for unfocusing comments to reflect doing it on mousedown * Update react-focus-trap and add focus trap to comments * Remove extra focusing logic and replace with focusTrap initialFocus argument * Add forceFocus to tests * Remove todo * Update Draftail to 1.4.1 to allow plugin keyBindingFns to be called * Remove now unneeded icon hiding css due to Draftail update * Add data-comment-add class to buttons to prevent comment unfocus * Prevent comment button showing on streamfield root, and attach contentpath to field parent for single field * Add keyboard shortcut for field level comments * Consolidate comments keyboard shortcut check in case we change, and use keyCode instead of key * Formatting and eslint fixes * Update tests --- .../CommentApp/__fixtures__/state.tsx | 1 + .../components/CommentApp/actions/comments.ts | 6 +- .../CommentApp/components/Comment/index.tsx | 88 +-- .../CommentApp/components/TextArea/index.tsx | 5 +- client/src/components/CommentApp/main.tsx | 11 +- .../CommentApp/state/comments.test.ts | 7 +- .../components/CommentApp/state/comments.ts | 4 + .../CommentableEditor/CommentableEditor.scss | 8 - .../CommentableEditor.test.tsx | 1 + .../CommentableEditor/CommentableEditor.tsx | 89 ++- client/src/components/Draftail/index.js | 1 + .../src/components/Explorer/ExplorerPanel.tsx | 42 +- .../__snapshots__/ExplorerPanel.test.js.snap | 528 +++++++++--------- .../StreamField/blocks/FieldBlock.js | 1 + .../__snapshots__/FieldBlock.test.js.snap | 2 +- client/src/entrypoints/admin/comments.js | 36 +- package-lock.json | 194 +++---- package.json | 8 +- wagtail/admin/edit_handlers.py | 6 +- .../edit_handlers/single_field_panel.html | 32 +- .../templates/wagtailadmin/shared/field.html | 4 +- 21 files changed, 575 insertions(+), 499 deletions(-) diff --git a/client/src/components/CommentApp/__fixtures__/state.tsx b/client/src/components/CommentApp/__fixtures__/state.tsx index 6f72f10d1a..91616423f4 100644 --- a/client/src/components/CommentApp/__fixtures__/state.tsx +++ b/client/src/components/CommentApp/__fixtures__/state.tsx @@ -65,6 +65,7 @@ const localComment: Comment = { export const basicCommentsState: CommentsState = { focusedComment: 1, + forceFocus: false, pinnedComment: 1, remoteCommentCount: 1, comments: new Map([[remoteComment.localId, remoteComment], [localComment.localId, localComment]]), diff --git a/client/src/components/CommentApp/actions/comments.ts b/client/src/components/CommentApp/actions/comments.ts index 565f15c969..cf70f7b661 100644 --- a/client/src/components/CommentApp/actions/comments.ts +++ b/client/src/components/CommentApp/actions/comments.ts @@ -43,6 +43,7 @@ export interface SetFocusedCommentAction { type: typeof SET_FOCUSED_COMMENT; commentId: number | null; updatePinnedComment: boolean; + forceFocus: boolean; } export interface AddReplyAction { @@ -115,12 +116,13 @@ export function resolveComment(commentId: number): ResolveCommentAction { export function setFocusedComment( commentId: number | null, - { updatePinnedComment } = { updatePinnedComment: false } + { updatePinnedComment, forceFocus } = { updatePinnedComment: false, forceFocus: false } ): SetFocusedCommentAction { return { type: SET_FOCUSED_COMMENT, commentId, - updatePinnedComment + updatePinnedComment, + forceFocus }; } diff --git a/client/src/components/CommentApp/components/Comment/index.tsx b/client/src/components/CommentApp/components/Comment/index.tsx index 931eb23eb9..1700c1fa36 100644 --- a/client/src/components/CommentApp/components/Comment/index.tsx +++ b/client/src/components/CommentApp/components/Comment/index.tsx @@ -1,5 +1,8 @@ -import React, { MutableRefObject } from 'react'; +/* eslint-disable react/prop-types */ + +import React from 'react'; import ReactDOM from 'react-dom'; +import FocusTrap from 'focus-trap-react'; import type { Store } from '../../state'; import { Author, Comment, newCommentReply } from '../../state/comments'; @@ -75,6 +78,7 @@ export interface CommentProps { store: Store; comment: Comment; isFocused: boolean; + forceFocus: boolean; isVisible: boolean; layout: LayoutController; user: Author | null; @@ -82,13 +86,6 @@ export interface CommentProps { } export default class CommentComponent extends React.Component { - focusTargetRef: MutableRefObject - focusTimeoutId: number | undefined - - constructor(props: CommentProps) { - super(props); - this.focusTargetRef = React.createRef(); - } renderReplies({ hideNewReply = false } = {}): React.ReactFragment { const { comment, isFocused, store, user, strings } = this.props; @@ -195,7 +192,7 @@ export default class CommentComponent extends React.Component { } renderCreating(): React.ReactFragment { - const { comment, store, strings } = this.props; + const { comment, store, strings, isFocused } = this.props; const onChangeText = (value: string) => { store.dispatch( @@ -221,7 +218,7 @@ export default class CommentComponent extends React.Component {