## The basics
- [x] I [validated my changes](https://developers.google.com/blockly/guides/contribute/core#making_and_verifying_a_change)
## The details
### Resolves
Fixes part of #8207
Fixes part of #3370
### Proposed Changes
This introduces initial broad ARIA integration in order to enable at least basic screen reader support when using keyboard navigation.
Largely this involves introducing ARIA roles and labels in a bunch of places, sometimes done in a way to override normal built-in behaviors of the accessibility node tree in order to get a richer first-class output for Blockly (such as for blocks and workspaces).
### Reason for Changes
ARIA is the fundamental basis for configuring how focusable nodes in Blockly are represented to the user when using a screen reader. As such, all focusable nodes requires labels and roles in order to correctly communicate their contexts.
The specific approach taken in this PR is to simply add labels and roles to all nodes where obvious with some extra work done for `WorkspaceSvg` and `BlockSvg` in order to represent blocks as a tree (since that seems to be the best fitting ARIA role per those available: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles). The custom work specifically for blocks includes:
- Overriding the role description to be 'block' rather than 'tree item' (which is the default).
- Overriding the position, level, and number of sibling counts since those are normally determined based on the DOM tree and blocks are not laid out in the tree the same way they are visually or logically (so these computations were incorrect). This is also the reason for a bunch of extra computation logic being introduced.
One note on some of the labels being nonsensical (e.g. 'DoNotOverride?'): this was done intentionally to try and ensure _all_ focusable nodes (that can be focused) have labels, even when the specifics of what that label should be aren't yet clear. More components had these temporary labels until testing revealed how exactly they would behave from a screen reader perspective (at which point their roles and labels were updated as needed). The temporary labels act as an indicator when navigating through the UI, and some of the nodes can't easily be reached (for reasons) and thus may never actually need a label. More work is needed in understanding both what components need labels and what those labels should be, but that will be done beyond this PR.
### Test Coverage
No tests are added to this as it's experimental and not a final implementation.
The keyboard navigation tests are failing due to a visibility expansion of `connectionCandidate` in `BlockDragStrategy`. There's no way to avoid this breakage, unfortunately. Instead, this PR will be merged and then https://github.com/google/blockly-keyboard-experimentation/pull/684 will be finalized and merged to fix it. There's some additional work that will happen both in that branch and in a later PR in core Blockly to integrate the two experimentation branches as part of #9283 so that CI passes correctly for both branches.
### Documentation
No documentation is needed at this time.
### Additional Information
This work is experimental and is meant to serve two purposes:
- Provide a foundation for testing and iterating the core screen reader experience in Blockly.
- Provide a reference point for designing a long-term solution that accounts for all requirements collected during user testing.
This code should never be merged into `develop` as it stands. Instead, it will be redesigned with maintainability, testing, and correctness in mind at a future date (see https://github.com/google/blockly-keyboard-experimentation/discussions/673).
* feat: Enhance the Rect API.
* feat: Add support for sorting IBoundedElements in general.
* fix: Improve typings of getTopElement/Comment methods.
* feat: Add classes to represent comment icons.
* refactor: Use comment icons in comment view.
* feat: Update navigation policies to support workspace comments.
* feat: Make the navigator and workspace handle workspace comments.
* feat: Visit workspace comments when navigating with the up/down arrows.
* chore: Make the linter happy.
* chore: Rename comment icons to bar buttons.
* refactor: Rename CommentIcons to CommentBarButtons.
* chore: Improve docstrings.
* chore: Clarify unit type.
* refactor: Remove workspace argument from `navigateStacks()`.
* fix: Fix errant find and replace in CSS.
* fix: Fix issue that could cause delete button to become misaligned.
## The basics
- [x] I [validated my changes](https://developers.google.com/blockly/guides/contribute/core#making_and_verifying_a_change)
## The details
### Resolves
Fixes#9155
### Proposed Changes
In cases when an ID is missing for an element passed to `FocusableTreeTraverser.findFocusableNodeFor()`, always return `null`.
Additionally, the new short-circuit logic exposed that `Toolbox` actually wasn't being set up correctly (that is, its root element was not being configured with a valid ID). This has been fixed.
### Reason for Changes
These are cases when a valid node should never be matched (and it's technically possible to incorrectly match if an `IFocusableNode` is set up incorrectly and is providing a focusable element with an unset ID). This avoids the extra computation time of potentially calling deep into `WorkspaceSvg` and exploring all possible nodes for an ID that should never match.
Note that there is a weird quirk with `null` IDs actually being the string `"null"`. This is a side effect of how `setAttribute` and attributes in general work with HTML elements. There's nothing really that can be done here, so it's now considered invalid to also have an ID of string `"null"` just to ensure the `null` case is properly short-circuited.
Finally, the issue with toolbox being configured incorrectly was discovered with the introducing of a new hard failure in `FocusManager.registerTree()` when a tree with an invalid root element is registered. From testing there are no other such trees that need to be updated.
A new warning was also added if `focusNode()` is used on a node with an element that has an invalid ID. This isn't a hard failure to follow the convention of other invalid `focusNode()` situations. It's much more fragile for `focusNode()` to throw than `registerTree()` since the former generally happens much earlier in a page lifecycle, and is less prone to dynamic behaviors.
### Test Coverage
New tests were added to validate the various empty ID cases for `FocusableTreeTraverser.findFocusableNodeFor()`, and to validate the new error check for `FocusManager.registerTree()`.
### Documentation
No new documentation should be needed.
### Additional Information
Nothing to add.
## The basics
- [x] I [validated my changes](https://developers.google.com/blockly/guides/contribute/core#making_and_verifying_a_change)
## The details
### Resolves
Fixes https://github.com/google/blockly-keyboard-experimentation/issues/515
### Proposed Changes
This adds `canBeFocused()` checks to all the places that could currently cause problems if a node were to return `false`.
### Reason for Changes
This can't introduce a problem in current Core and, in fact, most of these classes can never return `false` even through subclasses. However, this adds better robustness and fixes the underlying issue by ensuring that `getFocusableElement()` isn't called for a node that has indicated it cannot be focused.
### Test Coverage
I've manually tested this through the keyboard navigation plugin. However, there are clearly additional tests that would be nice to add both for the traverser and for `WorkspaceSvg`, both likely as part of resolving #8915.
### Documentation
No new documentation changes should be needed here.
### Additional Information
This is fixing theoretical issues in Core, but a real issue tracked by the keyboard navigation plugin repository.
* feat: Allow resetting alert/prompt/confirm to defaults.
* chore: Add unit tests for Blockly.dialog.
* fix: Removed TEST_ONLY hack from Blockly.dialog.
* feat: Add a default toast notification implementation.
* feat: Add support for toasts to Blockly.dialog.
* chore: Add tests for default toast implementation.
* chore: Fix docstring.
* refactor: Use default arguments for dialog functions.
* refactor: Add 'close' to the list of messages.
* chore: Add new message in several other places.
* chore: clarify docstrings.
* feat: Make toast assertiveness configurable.
This adds new tests for the FocusableTreeTraverser and fixes a number of
issues with the original implementation (one of which required two new
API methods to be added to IFocusableTree). More tests have also been
added for FocusManager, and defocusing tracked nodes/trees has been
fully implemented in FocusManager.
This is the bulk of the work for introducing the central logical unit
for managing and sychronizing focus as a first-class Blockly concept
with that of DOM focus.
There's a lot to do yet, including:
- Ensuring clicks within Blockly's scope correctly sync back to focus
changes.
- Adding support for, and testing, cases when focus is lost from all
registered trees.
- Testing nested tree propagation.
- Testing the traverser utility class.
- Adding implementations for IFocusableTree and IFocusableNode
throughout Blockly.
At a high-level, this change ensures that cleaning up a workspace
doesn't move blocks in a way that overlaps with immovable blocks. It
also adds missing testing coverage for both Rect (used for bounding box
calculations during workspace cleanup) and WorkspaceSvg (for verifying
the updated clean up functionality).
This also renames the clean up function to be 'tidyUp' since that better
suits what's happening (as opposed to other clean-up routines which are
actually deinitializing objects).
* chore(deps): Add pretter-plugin-organize-imports
* chore: Remove insignificant blank lines in import sections
Since prettier-plugin-organize-imports sorts imports within
sections separated by blank lines, but preserves the section
divisions, remove any blank lines that are not dividing imports
into meaningful sections.
Do not remove blank lines separating side-effect-only imports
from main imports.
* chore: Remove unneded eslint-disable directives
* chore: Organise imports
* feat: Invalid Blocks
* Rename the new json property from invalid to invalidReasons.
* Merged isValid into isEnabled.
* Minor fixes.
* More minor fixes.
* Reverting some stuff that didn't need to change.
* Addressing PR feedback.
* Update the BlockInfo interface to match State.
* Make BlockChange.disabledReason private.
* (feat): added Set to prevent console logging multiple deprecation warnings #7719
* feat!: added Set to prevent console logging multiple deprecation warnings #7719
* refactor: renamed variable and rewrote comment
Edited By Cpcallen
Co-authored-by: Christopher Allen <cpcallen+github@gmail.com>
* refactor: added guard clause and rewrote comment
Edited By Cpcallen
Co-authored-by: Christopher Allen <cpcallen+github@gmail.com>
* refactor: removed checkMsg Variable name and replaced it with previousWarnings
* refactor: removed checkMsg Variable name and replaced it with previousWarnings
---------
Co-authored-by: Christopher Allen <cpcallen+github@gmail.com>
* Setting style property to make CSP less grumpy.
"Content-Security-Policy: The page’s settings blocked the loading of a resource at inline (“style-src”)."
The 'style' property should be set as an object, not as a string, according to CSP rules.
Back-ported from Blockly Games.
* fix(build): Restore erroneously-deleted filter function
This was deleted in PR #7406 as it was mainly being used to
filter core/ vs. test/mocha/ deps into separate deps files -
but it turns out also to be used for filtering error
messages too. Oops.
* refactor(tests): Migrate advanced compilation test to ES Modules
* refactor(build): Migrate main.js to TypeScript
This turns out to be pretty straight forward, even if it would
cause crashing if one actually tried to import this module
instead of just feeding it to Closure Compiler.
* chore(build): Remove goog.declareModuleId calls
Replace goog.declareModuleId calls with a comment recording the
former module ID for posterity (or at least until we decide
how to reformat the renamings file.
* chore(tests): Delete closure/goog/*
For the moment we still need something to serve as base.js for
the benefit of closure-make-deps, so we keep a vestigial
base.js around, containing only the @provideGoog declaration.
* refactor(build): Remove vestigial base.js
By changing slightly the command line arguments to
closure-make-deps and closure-calculate-chunks the need to have
any base.js is eliminated.
* chore: Typo fix for PR #7415
* feat: Parse message newlines as endOfRow dummies.
* Fix the multilineinput field test.
* Addressing PR feedback.
* Addressing PR feedback.
* Newline parsing now uses a new custom input.
* npm run format
* Added input_end_row to block factory.
* Addres feedback, fix endrow after external value.
* fix: removed X & Y from toolbox.ts and replaced movBy to moveTo in Horizontal/ Vertical flyout
* forget to run npm lint and format
* removed the mistakenly added comment