## The basics - [x] I [validated my changes](https://developers.google.com/blockly/guides/contribute/core#making_and_verifying_a_change) ## The details ### Resolves Fixes #8965 Fixes #8978 Fixes #8970 Fixes https://github.com/google/blockly-keyboard-experimentation/issues/523 Fixes https://github.com/google/blockly-keyboard-experimentation/issues/547 Fixes part of #8910 ### Proposed Changes Fives groups of changes are included in this PR: 1. Support for automatic tab index management for focusable trees. 2. Support for automatic tab index management for focusable nodes. 3. Support for automatically hiding the flyout when back navigating from the toolbox. 4. A fix for `FocusManager` losing DOM syncing that was introduced in #9082. 5. Some cleanups for flyout and some tests for previous behavior changes to `FocusManager`. ### Reason for Changes Infrastructure changes reasoning: - Automatically managing tab indexes for both focusable trees and roots can largely reduce the difficulty of providing focusable nodes/trees and generally interacting with `FocusManager`. This facilitates a more automated navigation experience. - The fix for losing DOM syncing is possibly not reliable, but there are at least now tests to cover for it. This may be a case where a `try{} finally{}` could be warranted, but the code will stay as-is unless requested otherwise. `Flyout` changes: - `Flyout` no longer needs to be a focusable tree, but removing that would be an API breakage. Instead, it throws for most of the normal tree/node calls as it should no longer be used as such. Instead, its workspace has been made top-level tabbable (in addition to the main workspace) which solves the extra tab stop issues and general confusing inconsistencies between the flyout, toolbox, and workspace. - `Flyout` now correctly auto-selects the first block (#9103 notwithstanding). Technically it did before, however the extra `Flyout` tabstop before its workspace caused the inconsistency (since focusing the `Flyout` itself did not auto-select, only selecting its workspace did). Important caveats: - `getAttribute` is used in place of directly fetching `.tabIndex` since the latter can apparently default to `-1` (and possibly `0`) in cases when it's not actually set. This is a very surprising behavior that leads to incorrect test results. - Sometimes tab index still needs to be introduced (such as in cases where native DOM focus is needed, e.g. via `focus()` calls or clicking). This is demonstrated both by updates to `FocusManager`'s tests as well as toolbox's category and separator. This can be slightly tricky to miss as large parts of Blockly now depend on focus to represent their state, so clicking either needs to be managed by Blockly (with corresponding `focusNode` calls) or automatic (with a tab index defined for the element that can be clicked, or which has a child that can be clicked). Note that nearly all elements used for testing focus in the test `index.html` page have had their tab indexes removed to lean on `FocusManager`'s automatic tab management (though as mentioned above there is still some manual tab index management required for `focus()`-specific tests). ### Test Coverage New tests were added for all of the updated behaviors to `FocusManager`, including a new need to explicitly provide (and reset) tab indexes for all `focus()`-esque tests. This also includes adding new tests for some behaviors introduced in past PRs (a la #8910). Note that all of the new and affected conditionals in `FocusManager` have been verified as having at least 1 test that breaks when it's removed (inverted conditions weren't thoroughly tested, but it's expected that they should also be well covered now). Additional tests to cover the actual navigation flows will be added to the keyboard experimentation plugin repository as part of https://github.com/google/blockly-keyboard-experimentation/pull/557 (this PR needs to be merged first). For manual testing, I mainly verified keyboard navigation with some cursory mouse & click testing in the simple playground. @rachel-fenichel also performed more thorough mouse & click testing (that yielded an actual issue that was fixed--see discussion below). The core webdriver tests have been verified to have seemingly the same existing failures with and without these changes. All of the following new keyboard navigation plugin tests have been verified as failing without the fixes introduced in this branch (and passing with them): - `Tab navigating to flyout should auto-select first block` - `Keyboard nav to different toolbox category should auto-select first block` - `Keyboard nav to different toolbox category and block should select different block` - `Tab navigate away from toolbox restores focus to initial element` - `Tab navigate away from toolbox closes flyout` - `Tab navigate away from flyout to toolbox and away closes flyout` - `Tabbing to the workspace after selecting flyout block should close the flyout` - `Tabbing to the workspace after selecting flyout block via workspace toolbox shortcut should close the flyout` - `Tabbing back from workspace should reopen the flyout` - `Navigation position in workspace should be retained when tabbing to flyout and back` - `Clicking outside Blockly with focused toolbox closes the flyout` - `Clicking outside Blockly with focused flyout closes the flyout` - `Clicking on toolbox category focuses it and opens flyout` ### Documentation No documentation changes are needed beyond the code doc changes included in the PR. ### Additional Information An additional PR will be introduced for the keyboard experimentation plugin repository to add tests there (see test coverage above). This description will be updated with a link to that PR once it exists.
Blockly
Google's Blockly is a library that adds a visual code editor to web and mobile apps. The Blockly editor uses interlocking, graphical blocks to represent code concepts like variables, logical expressions, loops, and more. It allows users to apply programming principles without having to worry about syntax or the intimidation of a blinking cursor on the command line. All code is free and open source.
Getting Started with Blockly
Blockly has many resources for learning how to use the library. Start at our Google Developers Site to read the documentation on how to get started, configure Blockly, and integrate it into your application. The developers site also contains links to:
Help us focus our development efforts by telling us what you are doing with Blockly. The questionnaire only takes a few minutes and will help us better support the Blockly community.
Installing Blockly
Blockly is available on npm.
npm install blockly
For more information on installing and using Blockly, see the Getting Started article.
Getting Help
- Report a bug or file a feature request on GitHub
- Ask a question, or search others' questions, on our developer forum. You can also drop by to say hello and show us your prototypes; collectively we have a lot of experience and can offer hints which will save you time. We actively monitor the forums and typically respond to questions within 2 working days.
blockly-samples
We have a number of resources such as example code, demos, and plugins in another repository called blockly-samples. A plugin is a self-contained piece of code that adds functionality to Blockly. Plugins can add fields, define themes, create renderers, and much more. For more information, see the Plugins documentation.
Contributing to Blockly
Want to make Blockly better? We welcome contributions to Blockly in the form of pull requests, bug reports, documentation, answers on the forum, and more! Check out our Contributing Guidelines for more information. You might also want to look for issues tagged "Help Wanted" which are issues we think would be great for external contributors to help with.
Releases
We release by pushing the latest code to the master branch, followed by updating the npm package, our docs, and demo pages. If there are breaking bugs, such as a crash when performing a standard action or a rendering issue that makes Blockly unusable, we will cherry-pick fixes to master between releases to fix them. The releases page has a list of all releases.
We use semantic versioning. Releases that have breaking changes or are otherwise not backwards compatible will have a new major version. Patch versions are reserved for bug-fix patches between scheduled releases.
We now have a beta release on npm. If you'd like to test the upcoming release, or try out a not-yet-released new API, you can use the beta channel with:
npm install blockly@beta
As it is a beta channel, it may be less stable, and the APIs there are subject to change.
Branches
There are two main branches for Blockly.
master - This is the (mostly) stable current release of Blockly.
develop - This is where most of our work happens. Pull requests should always be made against develop. This branch will generally be usable, but may be less stable than the master branch. Once something is in develop we expect it to merge to master in the next release.
other branches: - Larger changes may have their own branches until they are good enough for people to try out. These will be developed separately until we think they are almost ready for release. These branches typically get merged into develop immediately after a release to allow extra time for testing.
New APIs
Once a new API is merged into master it is considered beta until the following release. We generally try to avoid changing an API after it has been merged to master, but sometimes we need to make changes after seeing how an API is used. If an API has been around for at least two releases we'll do our best to avoid breaking it.
Unreleased APIs may change radically. Anything that is in develop but not master is subject to change without warning.
Issues and Milestones
We typically triage all bugs within 1 week, which includes adding any appropriate labels and assigning it to a milestone. Please keep in mind, we are a small team so even feature requests that everyone agrees on may not be prioritized.
Good to Know
- Cross-browser Testing Platform and Open Source <3 Provided by Sauce Labs
- We test browsers using BrowserStack
