Commit Graph

216 Commits

Author SHA1 Message Date
Aaron Dodson
909c294e4a fix: Make left and right arrow keys only navigate within the current block/comment (#9531)
* fix: Make left and right arrow keys only navigate within the current block/comment

* fix: Fix tests

* fix: Remove .only from test suite

* test: Reenable statement block navigation tests with modifications

* chore: Clarify comments
2026-01-05 09:23:22 -08:00
Aaron Dodson
40e9ac8e00 feat: Beep when navigating across nesting levels (#9521) 2025-12-09 11:44:36 -08:00
Aaron Dodson
d57e66ed8f fix: Make flyout navigation respect the cursor's looping setting (#9520) 2025-12-08 14:00:40 -08:00
Aaron Dodson
8522bfff61 feat: Make navigation looping configurable (#9511)
* feat: Make navigation looping configurable

* chore: Add TODO to clean up API
2025-12-05 14:25:44 -08:00
Ben Henning
38e30fa052 feat: Expand single field block labeling (experimental) (#9484)
## The basics

- [ ] ~I [validated my changes](https://developers.google.com/blockly/guides/contribute/core#making_and_verifying_a_change)~ (I can't really due to the nature of this change--I have to rely on tests and external testing)

## The details
### Resolves

Fixes part of #9456 (remainder will be in a change in the keyboard navigation plugin)

### Proposed Changes

Introduce and use new `Block` function for retrieving a configurably constrained singleton field for a given block. The constraints allow for some level of configuring (such as whether to isolate to only full or editable blocks). The existing simple reporter function has been retrofitted to use this new function, instead.

### Reason for Changes

This expanded support fixes the underlying use case.

Separately, this change reveals two noteworthy details:
1. There's inconsistency in the codebase as to when the singleton field needs to be editable, a full-block field, both, and neither. It would be ideal to make this consistent. Interestingly, the documentation for `isSimpleReporter` seems to have been wrong since it wasn't actually fulfilling its contract of returning an editable field (this has been retained for callsites except where the check was already happening).
2. There's a possible recursion case now possible between `getSingletonFullBlockField` and `isFullBlockField` due to `FieldInput`'s `isFullBlockField` depending on `isSimpleReporter`. Ideally this would be changed in the future to avoid that potential recursion risk (possibly as part of #9307).

### Test Coverage

No new automated tests are needed for this experimental work. Manual testing mainly comprised of cursory navigation and readout checks for single-field blocks to make sure nothing breaks. More thorough testing is difficult in core since the specific situation of multiple fields don't have a corresponding block to use in the playground to verify.

Automated tests are also being heavily relied on for correctness since all of the nuance behind the simple reporter cases would require a deeper testing pass.

### Documentation

No new documentation needed for this experimental work.

### Additional Information

None.
2025-12-02 12:32:15 -08:00
Ben Henning
d0a79faf7d Merge branch 'develop' into merge-develop-into-experimental-branch 2025-11-04 18:47:23 +00:00
Aaron Dodson
7e77b10706 fix: Make up/previous navigation consistent with down/next. (#9437)
* fix: Make up/previous navigation consistent with down/next.

* fix: Don't visit nested input blocks when moving up/previous.
2025-10-27 12:51:44 -07:00
Aaron Dodson
098a3aaffb fix: Add support for icons to getSourceBlockFromNode() (#9438) 2025-10-27 09:39:52 -07:00
Aaron Dodson
40aa0d3328 fix: Improve narration and navigation of C-shaped blocks. (#9416)
* fix: Improve narration and navigation of C-shaped blocks.

* chore: Satisfy the linter.

* chore: Refactor and comment `getBlockNavigationCandidates()`.

* refactor: Reduce code duplication in `LineCursor`.

* fix: Add missing case when labeling connections.
2025-10-13 12:18:38 -07:00
Aaron Dodson
47307a9e53 refactor: Make focusable elements responsible for scrolling themselves into bounds. (#9288)
* refactor: Make focusable elements responsible for scrolling themselves into bounds.

* chore: Add tests for scrolling focused elements into view.

* fix: Removed inadvertent `.only`.

* fix: Scroll parent block of connections into bounds on focus.
2025-08-28 11:28:40 -07:00
Aaron Dodson
f9d0ec9d24 refactor: Associate comment bar buttons with the comment view. (#9278) 2025-08-06 14:04:12 -07:00
Aaron Dodson
c037e7d47d fix: Scroll CommentBarButtons into view on selection. (#9259) 2025-07-30 09:48:00 -07:00
Aaron Dodson
d5f3d15726 feat: Add support for keyboard navigation to/from block comments. (#9227)
* refactor: Update `TextInputBubble` to use `CommentEditor` for text editing.

* feat: Designate `Bubble` as implementing `IFocusableNode`.

* feat: Dismiss focused bubbles on Escape.

* feat: Add support for keyboard navigation to block comments.

* fix: Scroll comment editors rather than zooming the workspace.

* chore: Add param to docstring.
2025-07-11 10:54:19 -07:00
Aaron Dodson
e3d17becbd fix: Improve workspace comment keyboard navigation behavior. (#9211)
* fix: Prevent tabbing into workspace comments.

* fix: Focus workspace comments when navigating to them using the keyboard.
2025-07-07 15:28:54 -07:00
Aaron Dodson
e5804e7095 feat: Add support for keyboard navigation in/to workspace comments. (#9182)
* 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.
2025-07-01 15:13:13 -07:00
Aaron Dodson
1e5b4e9f42 feat: Add support for keyboard navigation into mutator workspaces. (#9151)
* feat: Add support for keyboard navigation into mutators.

* fix: Prevent mutator bubbles from jumping wildly during keyboard nav.
2025-06-23 09:09:56 -07:00
Aaron Dodson
93a9b6bf2e fix: Fix navigation for blocks with multiple statement inputs. (#9143)
* fix: Fix navigation for blocks with multiple statement inputs.

* chore: Add tests to prevent regressions.
2025-06-13 15:08:58 -07:00
Aaron Dodson
fd5a7f4a18 refactor: Make the cursor use the focus manager for tracking the current node. (#9142) 2025-06-13 12:05:00 -07:00
Aaron Dodson
38df7c8776 feat: Allow visiting empty input connections. (#9104)
* feat: Update navigation policies to allow visiting empty input connections.

* fix: Fix tests.

* chore: Add JSDoc.

* fix: Add missing import.

* fix: Fix JSDoc.

* chore: Remove double comments.
2025-05-28 20:43:16 -07:00
RoboErikG
d5a4522dd2 fix: Skip invisible inputs in the field navigation policy (#9092)
* Skip over hidden inputs when navigating from a field

* Add tests and fix implementation
2025-05-28 08:16:54 -07:00
RoboErikG
cc9384ae87 fix: Don't visit collapsed blocks (#9090)
* WIP on line by line navigation

Doesn't work, likely due to isValid check.

* Add all inputs to the list of siblings

* Fix formatting

* Add tests

* Remove dupe keys

* fix: Make blocks with display: none not focusable

* Undo changes to canBeFocused

* Don't traverse inputs that are invisible
2025-05-23 13:11:30 -07:00
RoboErikG
e4d7245e86 fix: Visit all nodes in getNextSibling and getPreviousSibling (#9080)
* WIP on line by line navigation

Doesn't work, likely due to isValid check.

* Add all inputs to the list of siblings

* Fix formatting

* Add tests

* Remove dupe keys
2025-05-21 16:42:22 -07:00
Aaron Dodson
53d7876539 feat: Add keyboard navigation support for icons. (#9072)
* feat: Add keyboard navigation support for icons.

* chore: Satisfy the linter.
2025-05-20 08:52:18 -07:00
Ben Henning
91632a4861 fix: Limit LineCursor<-focus syncing. (#9062)
## 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/526

### Proposed Changes

This limits synchronizing in `LineCursor` from `FocusManager` to just nodes that have a corresponding block.

### Reason for Changes

Limiting the synchronizing in this way ensures that navigation can't enter a bad state. The reason for why this is needed is explained in https://github.com/google/blockly-keyboard-experimentation/issues/526#issuecomment-2885117998.

Longer term it would maybe be ideal to do one or both of the following:
- Figure out ways of making navigation a bit more robust (perhaps on the keyboard navigation side) such that if cursor _is_ in a bad state there's some way to recover (rather than ending up permanently broken).
- Remove `Marker`'s internal state in favor of always relying on `FocusManager`'s state to cover the cases where there can be automatic focus shifting.

### Test Coverage

This was manually tested with the keyboard navigation plugin and verified to ensure that both https://github.com/google/blockly-keyboard-experimentation/issues/526 and https://github.com/google/blockly-keyboard-experimentation/issues/499 are (still) working as expected. Some basic testing was done with the core simple playground with the developer console open to ensure there weren't any expected failures.

Automated testing cases would be better addressed as part of resolving #8915.

### Documentation

No new documentation is needed here.

### Additional Information

This behavior is expected to only affect the keyboard navigation plugin.
2025-05-19 10:16:38 -07:00
RoboErikG
3010ceee2c fix: Skip hidden fields when navigating (#9070) 2025-05-19 09:47:16 -07:00
RoboErikG
7d0414c5dd fix: When moving to a field, scroll the field's block into view (#9071)
* fix: When moving to a field, scroll the field's block into view

* fix formatting
2025-05-19 09:35:59 -07:00
Aaron Dodson
ad0563daf7 fix: Make clickable but non-editable fields navigable. (#9054) 2025-05-15 09:15:07 -07:00
Ben Henning
e1179808fd fix: Ensure cursor syncs with more than just focused blocks (#9032)
## 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/499

### Proposed Changes

This ensures that non-blocks which hold active focus correctly update `LineCursor`'s internal state.

### Reason for Changes

This is outright a correction in how `LineCursor` has worked up until now, and is now possible after several recent changes (most notably #9004). #9004 updated selection to be more explicitly generic (and based on `IFocusableNode`) which means `LineCursor` should also properly support more than just blocks when synchronizing with focus (in place of selection), particularly since lots of non-block things can be focusable.

What's interesting is that this change isn't strictly necessary, even if it is a reasonable correction and improvement in the robustness of `LineCursor`. Essentially everywhere navigation is handled results in a call to `setCurNode` which correctly sets the cursor's internal state (with no specific correction from focus since only blocks were checked and we already ensure that selecting a block correctly focuses it).

### Test Coverage

It would be nice to add test coverage specifically for the cursor cases, but it seems largely unnecessary since:
1. The main failure cases are test-specific (as mentioned above).
2. These flows are better left tested as part of broader accessibility testing (per #8915).

This has been tested with a cursory playthrough of some basic scenarios (block movement, insertion, deletion, copy & paste, context menus, and interacting with fields).

### Documentation

No new documentation should be needed here.

### Additional Information

This is expected to only affect keyboard navigation plugin behaviors, particularly plugin tests.

It may be worth updating `LineCursor` to completely reflect current focus state rather than holding an internal variable. This, in turn, may end up simplifying solving issues like #8793 (but not necessarily).
2025-05-14 10:50:00 -07:00
Aaron Dodson
ae22165cbe refactor: Remove INavigable in favor of IFocusableNode. (#9037)
* refactor: Remove INavigable in favor of IFocusableNode.

* chore: Fix JSDoc.

* chore: Address review feedback.
2025-05-13 15:04:49 -07:00
Aaron Dodson
ece662a45f Fix: don't visit connections with the cursor. (#9030) 2025-05-13 11:03:01 -07:00
Aaron Dodson
a1be83bad8 refactor: Make INavigable extend IFocusableNode. (#9033) 2025-05-12 15:46:27 -07:00
Ben Henning
4074cee31b feat!: Make everything ISelectable focusable (#9004)
* feat!: Make bubbles, comments, and icons focusable

* feat!: Make ISelectable and ICopyable focusable.

* feat: Consolidate selection calls.

Now everything is based on focus with selection only being used as a
proxy.

* feat: Invert responsibility for setSelected().

Now setSelected() is only for quasi-external use.

* feat: Push up shadow check to getters.

Needed new common-level helper.

* chore: Lint fixes.

* feat!: Allow IFocusableNode to disable focus.

* chore: post-merge lint fixes

* fix: Fix tests + text bubble focusing.

This fixed then regressed a circular dependency causing the node and
advanced compilation steps to fail. This investigation is ongoing.

* fix: Clean up & fix imports.

This ensures the node and advanced compilation test steps now pass.

* fix: Lint fixes + revert commented out logic.

* chore: Remove unnecessary cast.

Addresses reviewer comment.

* fix: Some issues and a bunch of clean-ups.

This addresses a bunch of review comments, and fixes selecting workspace
comments.

* chore: Lint fix.

* fix: Remove unnecessary shadow consideration.

* chore: Revert import.

* chore: Some doc updates & added a warn statement.
2025-05-09 08:16:14 -07:00
Rachel Fenichel
561129ac61 fix!: delete ASTNode and references (#9014) 2025-05-08 11:47:42 -07:00
Rachel Fenichel
bb76d6e12c fix!: remove MarkerSvg and uses (#8991)
* fix: delete MarkerSvg (marker drawer)

* fix: delete marker and cursor SVG elements

* chore: format

* chore: lint
2025-05-07 09:28:51 -07:00
Aaron Dodson
acdad98653 refactor!: Use navigation rulesets instead of ASTNode to control keyboard navigation. (#8992)
* feat: Add interfaces for keyboard navigation.

* feat: Add the Navigator.

* feat: Make core types conform to INavigable.

* feat: Require FlyoutItems elements to be INavigable.

* feat: Add navigation policies for built-in types.

* refactor: Convert Marker and LineCursor to operate on INavigables instead of ASTNodes.

* chore: Delete dead code in ASTNode.

* fix: Fix the tests.

* chore: Assuage the linter.

* fix: Fix advanced build/tests.

* chore: Restore ASTNode tests.

* refactor: Move isNavigable() validation into Navigator.

* refactor: Exercise navigation instead of ASTNode.

* chore: Rename astnode_test.js to navigation_test.js.

* chore: Enable the navigation tests.

* fix: Fix bug when retrieving the first child of an empty workspace.
2025-05-07 08:47:52 -07:00
Robert Knight
1c79e1ed77 fix: Address remaining invisible input positions (#8948) 2025-05-02 10:17:11 -07:00
Ben Henning
fdeaa7692b feat: Update line cursor to use focus manager (#8941)
## The basics

- [x] I [validated my changes](https://developers.google.com/blockly/guides/contribute/core#making_and_verifying_a_change)

## The details
### Resolves

Fixes #8940
Fixes #8954
Fixes #8955

### Proposed Changes

This updates `LineCursor` to use `FocusManager` rather than selection (principally) as the source of truth.

### Reason for Changes

Ensuring that keyboard navigation works correctly with eventual screen reader support requires ensuring that ever navigated component is focused, and this is primarily what `FocusManager` has been designed to do. Since these nodes are already focused, `FocusManager` can be used as the primary source of truth for determining where the user currently has navigated, and where to go next.

Previously, `LineCursor` relied on selection for this purpose, but selection is now automatically updated (for blocks) using focus-controlled `focus` and `blur` callbacks. Note that the cursor will still fall back to synchronizing with selection state, though this will be removed once the remaining work to eliminate `MarkerSvg` has concluded (which requires further consideration on the keyboard navigation side viz-a-viz styling and CSS decisions) and once mouse clicks are synchronized with focus management.

Note that the changes in this PR are closely tied to https://github.com/google/blockly-keyboard-experimentation/pull/482 as both are necessary in order for the keyboard navigation plugin to correctly work with `FocusManager`.

Some other noteworthy changes:
- Some special handling exists for flyouts to handle navigating across stacks (per the current cursor design).
- `FocusableTreeTraverser` is needed by the keyboard navigation plugin (in https://github.com/google/blockly-keyboard-experimentation/pull/482) so it's now being exported.
- `FocusManager` had one bug that's now patched and tested in this PR: it didn't handle the case of the browser completely forcing focus loss. It would continue to maintain active focus even though no tracked elements now hold focus. One such case is the element being deleted, but there are other cases where this can happen (such as with dialog prompts).
- `FocusManager` had some issues from #8909 wherein it would overeagerly call tree focus callbacks and slightly mismanage the passive node. Since tests haven't yet been added for these lifecycle callbacks, these cases weren't originally caught (per #8910).
- `FocusManager` was updated to move the tracked manager into a static function so that it can be replaced in tests. This was done to facilitate changes to setup_teardown.js to ensure that a unique `FocusManager` exists _per-test_. It's possible for DOM focus state to still bleed across tests, but `FocusManager` largely guarantees eventual consistency. This change prevents a class of focus errors from being possible when running tests.
- A number of cursor tests needed to be updated to ensure that a connections are properly rendered (as this is a requirement for focusable nodes, and cursor is now focusing nodes). One test for output connections was changed to use an input connection, instead, since output connections can no longer be navigated to (and aren't rendered, thus are not focusable). It's possible this will need to be changed in the future if we decide to reintroduce support for output connections in cursor, but it seems like a reasonable stopgap. Huge thanks to @rachel-fenichel for helping investigate and providing an alternative for the output connection test.

**Current gaps** to be fixed after this PR is merged:
- The flyout automatically closes when creating a variable with with keyboard or mouse (I think this is only for the keyboard navigation plugin). I believe this is a regression from previous behavior due to how the navigation plugin is managing state. It would know the flyout should be open and thus ensure it stays open even when things like dialog prompts try to close it with a blur event. However, the new implementation in https://github.com/google/blockly-keyboard-experimentation/pull/482 complicates this since state is now inferred from `FocusManager`, and the flyout _losing_ focus will force it closed. There was a fix introduced in this PR to fix it for keyboard navigation, but fails for clicks because the flyout never receives focus when the create variable button is clicked. It also caused the advanced compilation tests to fail due to a subtle circular dependency from importing `WorkspaceSvg` directly rather than its type.
- The flyout, while it stays open, does not automatically update past the first variable being created without closing and reopening it. I'm actually not at all sure why this particular behavior has regressed.

### Test Coverage

No new non-`FocusManager` tests have been added. It's certainly possible to add unit tests for the focusable configurations being introduced in this PR, but it may not be highly beneficial. It's largely assumed that the individual implementations should work due to a highly tested FocusManager, and it may be the case that the interactions of the components working together is far more important to verify (that is, the end user flows). The latter is planned to be tackled as part of #8915.

Some new `FocusManager` tests were added, but more are still needed and this is tracked as part of #8910.

### Documentation

No new documentation should be needed for these changes.

### Additional Information

This includes changes that have been pulled from #8875.
2025-05-01 22:18:22 -07:00
Grace
8f59649956 fix: LineCursor can loop forward, but not back (#8926)
* fix: loop cursor when moving to prev node

* chore: add loop tests for LineCursor prev and out

* chore: fix out loop test for line cursor
2025-04-25 08:26:58 -07:00
Aaron Dodson
296ad33c21 fix: Fix bug that allowed some invisible fields/inputs to be navigated to. (#8899) 2025-04-17 09:48:17 -07:00
Aaron Dodson
7a3eb62142 fix: Don't visit invisible inputs with the cursor. (#8892) 2025-04-14 13:20:33 -07:00
Rachel Fenichel
fac75043dd feat: add loopback in cursor navigation, and add tests (#8883)
* chore: tests for cursor getNextNode

* chore: add tests for getPreviousNode

* feat: add looping to getPreviousNode and getNextNode

* chore: inline returns

* chore: fix test that results in a stack node

* chore: fix annotations
2025-04-14 09:58:58 -07:00
Rachel Fenichel
3160e3d321 feat: add getFirstNode and getLastNode to cursor with tests (#8878)
* feat: add getFirstNode and getlastNode to line_cursor.ts

* chore: add simple tests for getFirstNode and getLastNode

* chore: broken tests for debugging

* chore: additional cursor tests

* chore: lint, format, reenable tasks
2025-04-11 10:13:10 -07:00
Rachel Fenichel
58cd954fc0 feat: make getNextNode and getPreviousNode public (#8859) 2025-04-03 22:59:34 +00:00
Aaron Dodson
ca362725ee refactor!: Backport LineCursor to core. (#8834)
* refactor: Backport LineCursor to core.

* fix: Fix instantiation of LineCursor.

* fix: Fix tests.

* chore: Assauge the linter.

* chore: Fix some typos.

* feat: Make padding configurable for scrollBoundsIntoView.

* chore: Merge in the latest changes from keyboard-experimentation.

* refactor: Clarify name and docs for findSiblingOrParentSibling().

* fix: Improve scrollBoundsIntoView() behavior.

* fix: Export CursorOptions.

* refactor: Further clarify second parameter of setCurNode().

* fix: Revert change that could prevent scrolling bounds into view.
2025-04-03 12:15:17 -07:00
Aaron Dodson
7171350992 fix!: Tighten and correct typings on ASTNode (#8835)
* fix!: Tighten typings on ASTNode.create*Node() methods.

* fix: Restore missing condition.

* fix: Fix unsafe casts, non-null assertions and incorrect types.

* refactor: Simplify parent input checks.
2025-04-01 14:59:40 -07:00
Aaron Dodson
7a07b4b2ba refactor!: Remove old cursor and tab support. (#8803) 2025-03-28 13:54:33 -07:00
Aaron Dodson
0f07567965 fix: Allow the marker's current node to be null. (#8802) 2025-03-20 09:46:31 -07:00
Aaron Dodson
75efba92e3 fix: Fix bug that prevented keyboard navigation in flyouts. (#8687)
* fix: Fix bug that prevented keyboard navigation in flyouts.

* refactor: Add an `isFocusable()` method to FlyoutItem.
2025-01-09 14:31:51 -08:00
Aaron Dodson
9fcd5a3037 release: Merge branch 'rc/v11.2.0' into rc/v12.0.0 2024-12-04 12:06:12 -08:00
Aaron Dodson
e777086f16 refactor!: Update flyouts to use inflaters. (#8601)
* refactor: Update flyouts to use inflaters.

* fix: Specify an axis when creating flyout separators.

* chore: Remove unused import.

* chore: Fix tests.

* chore: Update documentation.

* chore: Improve code readability.

* refactor: Use null instead of undefined.
2024-10-02 09:20:45 -07:00