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(material/tree): add levelAccessor, childrenAccessor, TreeKeyManager; a11y and docs improvements #29062

Open
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

BobobUnicorn
Copy link
Collaborator

Update multiple facets of Tree component. Add APIs to manage data models, improve existing behaviors, add keyboard functionality and update documentation.

Add APIs options to the Tree data model by introducing levelAccessor and childrenAccessor. See “Api Addition” for usage. Currently, Tree component use TreeControl to manage data model. When applied, add levelAccessor and childrenAccessor functions as alternatives to TreeControl.

Add TreeKeyManager, which provides keyboard functionality. Currently Tree component allows developers to manage focus by setting tabindex on each tree node. When applied, Tree manages its own focus using key manager pattern. Keyboard commands match WAI ARIA Tree View Pattern. See “Deprecated” for adopting changes to existing applications.

Correct the ARIA semantics of Tree and Tree node components.

Document updated APIs and behaviors. Refine documentation of existing APIs and behaviors.

Changes to Cdk Tree API also apply to Mat Tree API. See “Deprecated” for adopting changes to existing applications.

Accessibility:

  • add CdkTreeKeyManager to provide keyboard navigation for CdkTree and MatTree
  • Improve keyboard usability of CdkTreeNodeToggle.
  • Improve ARIA semantics of CdkTree, CdkTreeNode, Tree and TreeNode components
  • Fix miscellaneous accessibility issues in tree and cdk-tree examples
  • Add accessibility instructions to documentation

Documentation:

  • Add API and usage examples for TreeKeyManager
  • Update @angular/cdk/tree and @angular/material/tree to be more consistent
  • Update examples to use levelAccessor and childrenAccessor
  • Add example for (activation) on MatTreeNode and CdkTreeNode

API ADDITION: add CdkTree#childrenAccessor and CdkTree#levelAccessor

  • Add CdkTree#childrenAccessor. Given a data node, childrenAccessor determines the children of that node.
  • Add CdkTree#levelAccessor. Given a data node, levelAccessor determines the level of the node in the parent hierarchy.
  • CdkTreeNode#levelAcessor and CdkTreeNode#childrenAccessor replace CdkTreeNode#treeControl.

See “Deprecated” for updating apps using treeControl.

API ADDITION: control expanded state of tree nodes using isExpandable and isExpanded

  • Add CdkTreeNode#isExpandable, determines if argument tree node can be expanded or collapsed.
  • CdkTreeNode#isExpanded to specify the expanded state. Has no effect if node is not expandable.
  • Add NestedTreeControlOptions#isExpandable function, determines if argument tree node can be expanded or collapsed.

For trees using treeControl, recommend providing isExpandable if not already provided. See “Deprecated” for more information on updating applications.

API ADDITION: use CdkTree to manage expansion state

  • Add CdkTree#isExpanded method.
  • Add CdkTree#toggle, CdkTree#expand and CdkTree#collapse methods.
  • Add CdkTree#toggleDescendants, CdkTree#expandDescendants, and CdkTree#collapseDescendants methods to CdkTree
  • Add CdkTree#expandAll and CdkTree#collapseAll methods
  • Add expandedChange Output to CdkTreeNode

API ADDITION: add injection token for tree-key-manager

  • Add TREE_KEY_MANAGER injection token. When provided, tree uses given key manager
  • TreeKeyManagerStrategy interface, which defines API contract of TREE_KEY_MANAGER

BEHAVIOR CHANGE: MatTree and CdkTree components respond to keyboard navigation.

  • CdkTree and MatTree respond to arrow keys, page up, page down, etc.; Keyboard commands match WAI ARIA Tree View Pattern.
  • Can no longer set the tabindex on MatTreeNode. See “Deprecated” for adopting existing applications.
  • Add TreeKeyManager to cdk/a11y

DEPRECATED: Tree controller deprecated. Use one of levelAccessor or childrenAccessor instead. To be removed in a future version.

  • BaseTreeControl, TreeControl, FlatTreeControl, and NestedTreeControl deprecated
  • CdkTree#treeControl deprecated. Provide one of CdkTree#levelAccessor or CdkTree#childrenAccessor instead.
  • MatTreeFlattener deprecated. Use MatTree#childrenAccessor and MatTreeNode#isExpandable instead.
  • MatTreeFlatDataSource deprecated. Use one of levelAccessor or childrenAccessor instead of TreeControl.

Note when upgrading: isExpandable works differently on Trees using treeControl than trees using childrenAccessor or levelAccessor. Nodes on trees that have a treeControl are expandable by default. Nodes on trees using childrenAccessor or levelAccessor are not expandable by default. Provide isExpandable to override default behavior.

DEPRECATED: Setting tabindex of tree nodes deprecated. By default, Tree ignores tabindex passed to tree nodes.

  • MatTreeNode#tabIndex deprecated. MatTreeNode ignores Input tabIndex and manages its own focus behavior.
  • MatTreeNode#defaultTabIndex deprecated. MatTreeNode ignores defaultTabIndex and manages its own focus behavior.
  • MatNestedTreeNode#tabIndex deprecated. MatTreeNode ignores Input defaultTabIndex and manages its own focus behavior.
  • LegacyTreeKeyManager and LEGACY_TREE_KEY_MANAGER_FACTORY_PROVIDER deprecated. Inject a TreeKeyManagerFactory to customize keyboard behavior.

Note when upgrading: an opt-out is available for keyboard functionality changes. Provide LEGACY_TREE_KEY_MANAGER_FACTORY_PROVIDER to opt-out of Tree managing its own focus. When provided, Tree does not manage it’s own focus and respects tabindex passed to TreeNode. When provided, have the same focus behavior as before this commit is applied.

Add Legacy Keyboard Interface demo, which shows usage of LEGACY_TREE_KEY_MANAGER_FACTORY_PROVIDER. Add Custom Key Manager, which shows usage of injecting a TreeKeyManagerStrategy

DEPRECATED: disabled renamed to isDisabled.

  • CdkTreeNode#disabled deprecated and alias to CdkTreeNode#isDisabled

zarend and others added 11 commits May 16, 2024 19:14
…er; a11y and docs improvements

Update multiple facets of Tree component. Add APIs to manage data models, improve existing behaviors, add keyboard functionality and update documentation.

Add APIs options to the Tree data model by introducing levelAccessor and childrenAccessor. See “Api Addition” for usage. Currently, Tree component use TreeControl to manage data model. When applied, add levelAccessor and childrenAccessor functions as alternatives to TreeControl.

Add TreeKeyManager, which provides keyboard functionality. Currently Tree component allows developers to manage focus by setting tabindex on each tree node. When applied, Tree manages its own focus using key manager pattern. Keyboard commands match [WAI ARIA Tree View Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/). See “Deprecated” for adopting changes to existing applications.

Correct the ARIA semantics of Tree and Tree node components.

Document updated APIs and behaviors. Refine documentation of existing APIs and behaviors.

Changes to Cdk Tree API also apply to Mat Tree API. See “Deprecated” for adopting changes to existing applications.

Accessibility:
 * add CdkTreeKeyManager to provide keyboard navigation for CdkTree and MatTree
 * Improve keyboard usability of CdkTreeNodeToggle.
 * Improve ARIA semantics of CdkTree, CdkTreeNode, Tree and TreeNode components
 * Fix miscellaneous accessibility issues in tree and cdk-tree examples
 * Add accessibility instructions to documentation

Documentation:
 * Add API and usage examples for TreeKeyManager
 * Update @angular/cdk/tree and @angular/material/tree to be more consistent
 * Update examples to use levelAccessor and childrenAccessor
 * Add example for (activation) on MatTreeNode and CdkTreeNode

API ADDITION: add CdkTree#childrenAccessor and CdkTree#levelAccessor
 * Add CdkTree#childrenAccessor. Given a data node, childrenAccessor determines the children of that node.
 * Add CdkTree#levelAccessor. Given a data node, levelAccessor determines the level of the node in the parent hierarchy.
 * CdkTreeNode#levelAcessor and CdkTreeNode#childrenAccessor replace CdkTreeNode#treeControl.

See “Deprecated” for updating apps using treeControl.

API ADDITION: control expanded state of tree nodes using isExpandable and isExpanded
 * Add CdkTreeNode#isExpandable, determines if argument tree node can be expanded or collapsed.
 * CdkTreeNode#isExpanded to specify the expanded state. Has no effect if node is not expandable.
 * Add NestedTreeControlOptions#isExpandable function, determines if argument tree node can be expanded or collapsed.

For trees using treeControl, recommend providing isExpandable if not already provided. See “Deprecated” for more information on updating applications.

API ADDITION: use CdkTree to manage expansion state
 * Add CdkTree#isExpanded method.
 * Add CdkTree#toggle, CdkTree#expand and CdkTree#collapse methods.
 * Add  CdkTree#toggleDescendants, CdkTree#expandDescendants, and CdkTree#collapseDescendants methods to CdkTree
 * Add CdkTree#expandAll and CdkTree#collapseAll methods
 * Add expandedChange Output to CdkTreeNode

API ADDITION: add injection token for tree-key-manager
 * Add TREE_KEY_MANAGER injection token. When provided, tree uses given key manager
 * TreeKeyManagerStrategy interface, which defines API contract of TREE_KEY_MANAGER

BEHAVIOR CHANGE: MatTree and CdkTree components respond to keyboard navigation.
 * CdkTree and MatTree respond to arrow keys, page up, page down, etc.; Keyboard commands match [WAI ARIA Tree View Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/).
 * Can no longer set the tabindex on MatTreeNode. See “Deprecated” for adopting existing applications.
 * Add TreeKeyManager to cdk/a11y

DEPRECATED: Tree controller deprecated. Use one of levelAccessor or childrenAccessor instead. To be removed in a future version.
 * BaseTreeControl, TreeControl, FlatTreeControl, and NestedTreeControl deprecated
 * CdkTree#treeControl deprecated. Provide one of CdkTree#levelAccessor or CdkTree#childrenAccessor instead.
 * MatTreeFlattener deprecated. Use MatTree#childrenAccessor and MatTreeNode#isExpandable instead.
 * MatTreeFlatDataSource deprecated. Use one of levelAccessor or childrenAccessor instead of TreeControl.

Note when upgrading: isExpandable works differently on Trees using treeControl than trees using childrenAccessor or levelAccessor. Nodes on trees that have a treeControl are expandable by default. Nodes on trees using childrenAccessor or levelAccessor are *not* expandable by default. Provide isExpandable to override default behavior.

DEPRECATED: Setting tabindex of tree nodes deprecated. By default, Tree ignores tabindex passed to tree nodes.
 * MatTreeNode#tabIndex deprecated. MatTreeNode ignores Input tabIndex and manages its own focus behavior.
 * MatTreeNode#defaultTabIndex deprecated. MatTreeNode ignores defaultTabIndex and manages its own focus behavior.
 * MatNestedTreeNode#tabIndex deprecated. MatTreeNode ignores Input defaultTabIndex and manages its own focus behavior.
 * LegacyTreeKeyManager and LEGACY_TREE_KEY_MANAGER_FACTORY_PROVIDER deprecated. Inject a TreeKeyManagerFactory to customize keyboard behavior.

Note when upgrading: an opt-out is available for keyboard functionality changes. Provide LEGACY_TREE_KEY_MANAGER_FACTORY_PROVIDER to opt-out of Tree managing its own focus. When provided, Tree does not manage it’s own focus and respects tabindex passed to TreeNode. When provided, have the same focus behavior as before this commit is applied.

Add Legacy Keyboard Interface demo, which shows usage of LEGACY_TREE_KEY_MANAGER_FACTORY_PROVIDER. Add Custom Key Manager, which shows usage of injecting a TreeKeyManagerStrategy

DEPRECATED: disabled renamed to isDisabled.
 * CdkTreeNode#disabled deprecated and alias to CdkTreeNode#isDisabled
…er; a11y and docs improvements

Update multiple facets of Tree component. Add APIs to manage data models, improve existing behaviors, add keyboard functionality and update documentation.

Add APIs options to the Tree data model by introducing levelAccessor and childrenAccessor. See “Api Addition” for usage. Currently, Tree component use TreeControl to manage data model. When applied, add levelAccessor and childrenAccessor functions as alternatives to TreeControl.

Add TreeKeyManager, which provides keyboard functionality. Currently Tree component allows developers to manage focus by setting tabindex on each tree node. When applied, Tree manages its own focus using key manager pattern. Keyboard commands match [WAI ARIA Tree View Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/). See “Deprecated” for adopting changes to existing applications.

Correct the ARIA semantics of Tree and Tree node components.

Document updated APIs and behaviors. Refine documentation of existing APIs and behaviors.

Changes to Cdk Tree API also apply to Mat Tree API. See “Deprecated” for adopting changes to existing applications.

Accessibility:
 * add CdkTreeKeyManager to provide keyboard navigation for CdkTree and MatTree
 * Improve keyboard usability of CdkTreeNodeToggle.
 * Improve ARIA semantics of CdkTree, CdkTreeNode, Tree and TreeNode components
 * Fix miscellaneous accessibility issues in tree and cdk-tree examples
 * Add accessibility instructions to documentation

Documentation:
 * Add API and usage examples for TreeKeyManager
 * Update @angular/cdk/tree and @angular/material/tree to be more consistent
 * Update examples to use levelAccessor and childrenAccessor
 * Add example for (activation) on MatTreeNode and CdkTreeNode

API ADDITION: add CdkTree#childrenAccessor and CdkTree#levelAccessor
 * Add CdkTree#childrenAccessor. Given a data node, childrenAccessor determines the children of that node.
 * Add CdkTree#levelAccessor. Given a data node, levelAccessor determines the level of the node in the parent hierarchy.
 * CdkTreeNode#levelAcessor and CdkTreeNode#childrenAccessor replace CdkTreeNode#treeControl.

See “Deprecated” for updating apps using treeControl.

API ADDITION: control expanded state of tree nodes using isExpandable and isExpanded
 * Add CdkTreeNode#isExpandable, determines if argument tree node can be expanded or collapsed.
 * CdkTreeNode#isExpanded to specify the expanded state. Has no effect if node is not expandable.
 * Add NestedTreeControlOptions#isExpandable function, determines if argument tree node can be expanded or collapsed.

For trees using treeControl, recommend providing isExpandable if not already provided. See “Deprecated” for more information on updating applications.

API ADDITION: use CdkTree to manage expansion state
 * Add CdkTree#isExpanded method.
 * Add CdkTree#toggle, CdkTree#expand and CdkTree#collapse methods.
 * Add  CdkTree#toggleDescendants, CdkTree#expandDescendants, and CdkTree#collapseDescendants methods to CdkTree
 * Add CdkTree#expandAll and CdkTree#collapseAll methods
 * Add expandedChange Output to CdkTreeNode

API ADDITION: add injection token for tree-key-manager
 * Add TREE_KEY_MANAGER injection token. When provided, tree uses given key manager
 * TreeKeyManagerStrategy interface, which defines API contract of TREE_KEY_MANAGER

BEHAVIOR CHANGE: MatTree and CdkTree components respond to keyboard navigation.
 * CdkTree and MatTree respond to arrow keys, page up, page down, etc.; Keyboard commands match [WAI ARIA Tree View Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/).
 * Can no longer set the tabindex on MatTreeNode. See “Deprecated” for adopting existing applications.
 * Add TreeKeyManager to cdk/a11y

DEPRECATED: Tree controller deprecated. Use one of levelAccessor or childrenAccessor instead. To be removed in a future version.
 * BaseTreeControl, TreeControl, FlatTreeControl, and NestedTreeControl deprecated
 * CdkTree#treeControl deprecated. Provide one of CdkTree#levelAccessor or CdkTree#childrenAccessor instead.
 * MatTreeFlattener deprecated. Use MatTree#childrenAccessor and MatTreeNode#isExpandable instead.
 * MatTreeFlatDataSource deprecated. Use one of levelAccessor or childrenAccessor instead of TreeControl.

Note when upgrading: isExpandable works differently on Trees using treeControl than trees using childrenAccessor or levelAccessor. Nodes on trees that have a treeControl are expandable by default. Nodes on trees using childrenAccessor or levelAccessor are *not* expandable by default. Provide isExpandable to override default behavior.

DEPRECATED: Setting tabindex of tree nodes deprecated. By default, Tree ignores tabindex passed to tree nodes.
 * MatTreeNode#tabIndex deprecated. MatTreeNode ignores Input tabIndex and manages its own focus behavior.
 * MatTreeNode#defaultTabIndex deprecated. MatTreeNode ignores defaultTabIndex and manages its own focus behavior.
 * MatNestedTreeNode#tabIndex deprecated. MatTreeNode ignores Input defaultTabIndex and manages its own focus behavior.
 * LegacyTreeKeyManager and LEGACY_TREE_KEY_MANAGER_FACTORY_PROVIDER deprecated. Inject a TreeKeyManagerFactory to customize keyboard behavior.

Note when upgrading: an opt-out is available for keyboard functionality changes. Provide LEGACY_TREE_KEY_MANAGER_FACTORY_PROVIDER to opt-out of Tree managing its own focus. When provided, Tree does not manage it’s own focus and respects tabindex passed to TreeNode. When provided, have the same focus behavior as before this commit is applied.

Add Legacy Keyboard Interface demo, which shows usage of LEGACY_TREE_KEY_MANAGER_FACTORY_PROVIDER. Add Custom Key Manager, which shows usage of injecting a TreeKeyManagerStrategy

DEPRECATED: disabled renamed to isDisabled.
 * CdkTreeNode#disabled deprecated and alias to CdkTreeNode#isDisabled
Fix miscellaneous PR comments. Take a first pass to fix comments that
are easiest to fix. This commit message will be squashed away when
merging.
 * move type definitions in tree-key-manager.ts to a new file,
   tree-key-manager-strategy.ts
 * remove unnecessary comment
 * fix JSDoc comment syntax
 * remove isNotNullish
 * consolidate event handling code in CdkTreeNodeToggle
 * remove unnecessary type coerscion
 * simply logic for detecting TreeControlMissingError and MultipleTreeControlsError
 * adopt Input transform
 * remove unnecessary nesting in _updateActiveItemIndex
Use OnPush change detection in Tree examples.
refactor(cdk/tree): simplify code in lifecycle hooks

Refactor CdkTree implementation to simplify code in lifecycle hooks.
Create a RenderingData type definition to simplify the Tree's rendering
pipeline.

The render pipeline looks like this. It has two entry points
ngAfterContentChecked and whener the datasource is switched.

1. ngAfterContentChecked OR datasource changed

2. call _subscribeToDataChanges

From here, the pipeline diverges. Tree subscribes to changes in the
datasource and expansion state. From there, the pipeline goes on two
paths: emit changes to expansion state, and render the changes from the
datasource.

Add RenderingData type to make it more clear what stages are in the
pipeline.

This commit message will be squashed away.
Fix miscelaneous focus management details in response to PR feedback.

 * omit tabindex attribute on role="tree" element
 * Remove TreeKeyManagerStrategy#onInitialFocus
 * Implement focus/unfocus pattern for TreeKeyManagerOption and use a
   binding to set tabindex on tree nodes
 * algin with https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols
 * Add tree-using-legacy-key-manager.spec.ts
…8238)

Make miscelaneous fixes to documentation. Rename variables. Responding
to PR feedback.

 * remove comment about API contract of CdkTreeNodeToggle
 * rename CdkTree#_groups to CdkTree#_ariaSets
 * move documentation about default key manager configuration from
   TreeKeyManagerStrategy interface to TreeKeyManager class.
 * add JSDoc style comments for NoopTreeKeyManager
Add unit tests to cover the use of LegacyTreeKeyManager, which opts out
of updated focus management behavior.
* fix(cdk/tree): fix errors from testing

* fix(cdk/tree): tests

* fix(cdk/tree): update api docs

* fix(cdk/a11y): allows disabled items to receive initial focus

* fix(cdk/tree): don't focus on click, corrected updating aria-sets

* fix(cdk/tree): update api goldens
Implement typeahead labels for Tree. Follow the established pattern that
Menu and List use.
 - implement CdkTreeNode#cdkTreeNodeTypeaheadLabel
 - implement CdkTreeNode#getLabel
@angular-robot angular-robot bot added detected: deprecation PR contains a commit with a deprecation area: docs Related to the documentation labels May 16, 2024
@andrewseguin andrewseguin added dev-app preview When applied, previews of the dev-app are deployed to Firebase target: minor This PR is targeted for the next minor release labels May 28, 2024
Copy link

Deployed dev-app for 9b501c9 to: https://ng-dev-previews-comp--pr-angular-components-29062-dev-grqg8ezi.web.app

Note: As new commits are pushed to this pull request, this link is updated after the preview is rebuilt.

*/
private _horizontalOrientation: 'ltr' | 'rtl' = 'ltr';

// Keep tree items focusable when disabled. Align with
Copy link
Contributor

Choose a reason for hiding this comment

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

It's not immediately clear what this comment is trying to say. Is it part of the docs for _skipPredicateFn?

* Initialize the `TreeKeyManager`, passing in the options.
* Forward keyboard events from the managed component to the `TreeKeyManager` via `onKeydown`.

Each tree item should implement the `TreeKeyManagerItem` interface:
Copy link
Contributor

Choose a reason for hiding this comment

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

Ideally this links to the API docs so that we don't need to keep this in sync, e.g. https://v11.material.angular.io/cdk/a11y/api#TreeKeyManagerItem

* @deprecated NoopTreeKeyManager deprecated. Use TreeKeyManager or inject a
* TreeKeyManagerStrategy instead. To be removed in a future version.
*
* @breaking-change 19.0.0
Copy link
Contributor

Choose a reason for hiding this comment

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

each breaking-change should be updated to v21 (allowing two full releases with this deprecated item, v19 and v20)

@@ -0,0 +1,35 @@
<mat-spinner *ngIf="areRootsLoading | async; else treeTemplate"></mat-spinner>
Copy link
Contributor

Choose a reason for hiding this comment

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

If you have the bandwidth, it'd be great if the examples used Angular's latest control flow syntax https://angular.io/guide/control_flow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: docs Related to the documentation detected: deprecation PR contains a commit with a deprecation dev-app preview When applied, previews of the dev-app are deployed to Firebase target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants