Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix link popover keyboard accessibility #10983

Merged
merged 8 commits into from
Oct 27, 2018
Merged

Conversation

talldan
Copy link
Contributor

@talldan talldan commented Oct 24, 2018

Description

Fixes #8266 by displaying the link popover whenever the caret is positioned within link formatting. As discussed in the issue, the agreed upon approach also involved displaying the toolbar whenever the caret is positioned within any formatting.

Also fixes #3350.

Changes:

  • Add core/editor state handling for storing whether caret is positioned within formatting.
  • Adjust toolbar rendering logic to show toolbar when caret is positioned within formatting.
  • Add e2e tests to ensure regressions don't occur.

How has this been tested?

  • e2e tests
  • manual testing

Screenshots

toolbar-formatting

Types of changes

New feature (non-breaking change which adds functionality)

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.

@talldan talldan self-assigned this Oct 24, 2018
@talldan talldan added this to the 4.2 milestone Oct 24, 2018
@talldan talldan requested a review from a team October 24, 2018 08:07
@talldan talldan added [Focus] Accessibility (a11y) Changes that impact accessibility and need corresponding review (e.g. markup changes). [Feature] Rich Text Related to the Rich Text component that allows developers to render a contenteditable labels Oct 24, 2018
@@ -426,7 +426,13 @@ export class RichText extends Component {
return;
}

const { start, end } = this.createRecord();
const { start, end, formats } = this.createRecord();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createRecord creates a new record form the DOM. getRecord gets the current record from props. Also I think this might be better to do in onChange right before or after you update the global state. You have direct access to the record there. Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like onChange only triggers when typing instead of when using cursor keys or changing selection with the mouse like I need.

The createRecord was there before, should it be getRecord instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, never mind then, I only saw the green line. :) Then this looks good, sorry!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries - thanks for taking a look. 😄

@@ -399,7 +400,7 @@ export class BlockListBlock extends Component {
// We render block movers and block settings to keep them tabbale even if hidden
const shouldRenderMovers = ! isFocusMode && ( isSelected || hoverArea === 'left' ) && ! showEmptyBlockSideInserter && ! isMultiSelecting && ! isPartOfMultiSelection && ! isTypingWithinBlock;
const shouldShowBreadcrumb = ! isFocusMode && isHovered && ! isEmptyDefaultBlock;
const shouldShowContextualToolbar = ! hasFixedToolbar && ! showSideInserter && ( ( isSelected && ! isTypingWithinBlock ) || isFirstMultiSelected );
const shouldShowContextualToolbar = ! hasFixedToolbar && ! showSideInserter && ( ( isSelected && ( ! isTypingWithinBlock || isCaretWithinFormattedText ) ) || isFirstMultiSelected );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These bools scare me - might be worth refactoring them into functions or something?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely yes, I recall them being quite scary the last time I worked on this file.

Might be worth a separate code quality issue as a follow-up, unless you have the time to do it now 😄

@talldan talldan requested a review from afercia October 24, 2018 09:15
@tofumatt tofumatt self-requested a review October 24, 2018 12:21
Copy link
Member

@tofumatt tofumatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a million, this was the bug that was irking me the most in the merge milestone.

Just one comment about "leave" vs "exit", but after that: 🚢


Returns an action object used in signalling that the caret has entered formatted text.

### leaveFormattedText
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be better-named as exitFormattedText? It matches enterFormattedText more, and the docs confused me at first because I read "left" as in "left/right" not "left/leave".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 changed this

@@ -388,4 +388,36 @@ describe( 'Links', () => {
await page.keyboard.press( 'Escape' );
expect( await page.$( '.editor-url-popover' ) ).toBeNull();
} );

it( 'can be modified using the keyboard once a link has been set', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️ for the test!

@tofumatt
Copy link
Member

Ah, hold off one second, getting some weird behaviour in Firefox, let me see...

@tofumatt
Copy link
Member

Never mind, my build was buggy; fixed it.

Confirmed to be working for me with the keyboard. Awesome, thanks, ship it! 👍

@chrisvanpatten
Copy link
Contributor

The only slightly weird thing is that it looks like the toolbar shows when your cursor is adjacent to the inline token but the token isn't itself highlighted. Not the end of the world, but it jumped out at me.

Either way this looks like an improvement!

@noisysocks
Copy link
Member

Can we make the link popover not move around?

I could have sworn it used to anchor itself to the link... maybe #6113 regressed...

@talldan
Copy link
Contributor Author

talldan commented Oct 25, 2018

@noisysocks - I might look at that on a separate PR today. I think it'll be related to this component:
https://github.com/WordPress/gutenberg/blob/master/packages/editor/src/components/rich-text/format-toolbar/positioned-at-selection.js

It might have been one my past changes that caused it to regress as I put out a fix to make it recalculate position whenever the selection changes - there was an issue where it didn't change position when clicking between links.

@chrisvanpatten - I see what you mean, and it works differently on the left and right side of the format. I think I can iron out the left/right inconsistency, but the highlighting of formatting is internal to tinymce (they're called inline boundaries), would have to hook into that somehow.

@talldan
Copy link
Contributor Author

talldan commented Oct 25, 2018

Looking some more the inconsistency with how the toolbar is displayed on the leading and trailing edge of formatted text is a bit of a deeper problem.

Currently if the caret is on the trailing edge of formatted text, the toolbar button to toggle the format doesn't work, but on the leading edge it does work. The logic in this PR for displaying the toolbar is consistent with that.

I think it's worth filing a separate issue to look at fixing both things at once.

@afercia
Copy link
Contributor

afercia commented Oct 25, 2018

Thanks for working on this! Quickly tested, I've noticed the same thing @chrisvanpatten and @talldan mentioned about the highlighting and inline boundaries (not only an inconsistency between left and right behaviors but it's also different from Classic Editor). Regardless, makes perfectly sense to me to try to address that separately. This PR is a good improvement for keyboard users and I'm all for it. Thank you.

@@ -372,6 +372,7 @@ export class BlockListBlock extends Component {
isPartOfMultiSelection,
isFirstMultiSelected,
isTypingWithinBlock,
isCaretWithinFormattedText,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like that the block's wrapper is aware of something very specific to the implementation of a given block (RichText). It doesn't seem like a generic enough solution for me. All blocks don't use RichText. As I see it the block wrapper should work similarily no matter what's the content of the edit function.

That said, I'm not familiar enough with the issue and the PR to propose an alternative. (which means I won't block this PR either)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point. I don't have a better solution either off the top of my head, aside from just documenting that it's RichText specific, which still isn't great/is the whole problem. 🤷‍♂️

@youknowriad
Copy link
Contributor

Let's rebase and merge.

@tofumatt tofumatt force-pushed the fix/link-popover-keyboard-a11y branch from ac5d270 to 7e4c15f Compare October 27, 2018 10:54
@tofumatt
Copy link
Member

Rebased and pushed, just waiting on Travis and then I'll get this merged.

@tofumatt
Copy link
Member

Urgh, something went wrong with the rebase, looking into it now...

@tofumatt
Copy link
Member

Rebase fixed… will merge when ready 😄

@tofumatt tofumatt force-pushed the fix/link-popover-keyboard-a11y branch from a20ba53 to 97dfc04 Compare October 27, 2018 20:14
@tofumatt tofumatt merged commit 432bfe5 into master Oct 27, 2018
@tofumatt tofumatt deleted the fix/link-popover-keyboard-a11y branch October 27, 2018 21:15
@aduth
Copy link
Member

aduth commented Oct 29, 2018

Is this new action expected to be so noisy? This is just in writing a few words in a paragraph:

image

There's a decent amount of work performed on each action dispatched. We should try to limit this if we can.

const { start, end } = this.createRecord();
const { start, end, formats } = this.createRecord();

if ( formats[ start ] ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be moved in start !== this.state.start || end !== this.state.end you think? Could we check right here which flag is set to avoid calling the prop?

@talldan
Copy link
Contributor Author

talldan commented Oct 30, 2018

Thanks for catching that - I've got a PR here to reduce the frequency of dispatches - #11235

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Rich Text Related to the Rich Text component that allows developers to render a contenteditable [Focus] Accessibility (a11y) Changes that impact accessibility and need corresponding review (e.g. markup changes).
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Can't edit an existing link using only the keyboard Cannot edit existing link in URLInput
8 participants