Skip to content

Commit

Permalink
feat(cdk/tree): Add levelAccessor and childrenAccessor to CDK tree API
Browse files Browse the repository at this point in the history
This is currently unimplemented and will allow a more reactive API for
the tree.

feat(cdk/tree): wording changes

feat(cdk/tree): wording changes

feat(cdk/tree): make getLevel getAccessor private

feat(cdk/tree): make nullable properties optional

feat(cdk/tree): fix lint issues

feat(cdk/tree): add TreeControl methods into the CdkTree itself

feat(cdk/tree): add missing tree errors

feat(cdk/tree): make nullable properties optional

feat(cdk/tree): fix build errors.

feat(cdk/tree): update tree API goldens

feat(cdk/tree): fix lint errors

feat(cdk/tree): fix tests

feat(cdk/tree): fix final lint and golden errors

feat(cdk/tree): fix comments and improve readability

feat(cdk/tree): remove ! assertion

feat(cdk/tree): implement the various expansion-related methods

fix(cdk/tree): fix merge conflict errors

fix(cdk/tree): remove TODOs and fix `isExpanded`

fix(cdk/tree): fix nested nodes not rendering children

fix(cdk/tree): remove childrenAccessor?. usage

fix(cdk/tree): address comments from review

feat(cdk/tree): add tests for the new cdk/tree APIs (angular#24500)

* feat(cdk/tree): complete migrated tests

* feat(cdk/tree): fix tests

* fix(cdk/tree): add docs to _getAllDescendants

* fix(cdk/tree): add explanatory comment for tree-redesign.spec.ts

feat(cdk/tree): improve aria attributes (angular#24658)

* feat(cdk/tree): add demos to the dev-app

* feat(cdk/tree): add flat-node with levelAccessor example to the demo
page

* feat(cdk/tree): move new demos to cdk-tree-redesign dir

* fix(cdk/tree): fix unused error

* feat(cdk/tree): move demos back to their own dirs

* fix(cdk/tree): address review comments

* feat(cdk/tree): use _getDirectChildren method in nested node

* feat(cdk/tree): add cache of nodes to the tree

* fix(cdk/tree): fix cherry-pick errors

* feat(cdk/tree): add translation layer for nested nodes using levelAccessor

* feat(cdk/tree): add example with nested nodes & level accessor

* feat(cdk/tree): fix examples

* feat(cdk/tree): add example with flat nodes & childrenAccessor

* feat(cdk/tree): flatten data that uses childrenAccessor

* fix(cdk/tree): fix padding not showing for `childrenAccessor` trees

* fix(cdk/tree): fix flat tree demo

* fix(cdk/tree): convert generator function to return a regular array in demo

* fix(cdk/tree): fix build error

* feat(cdk/tree): update API goldens

* fix(cdk/tree): fix some failing tests, one remaining

* fix(cdk/tree): fix test errors and children conversion; also make `renderNodeChanges` private

* fix(cdk/tree): update api goldens

* fix(cdk/tree): fix lint errors

* feat(cdk/tree): deprecate the TreeControl APIs

* fix(cdk/tree): make the toggle button not focusable by keyboard

* fix(cdk/tree): add aria attributes for the flat nodes

* feat(cdk/tree): maintain a cache of parents and node groups

* feat(cdk/tree): implement aria-posinset and aria-setsize

* feat(cdk/tree): update goldens, add descriptions to methods

* feat(cdk/tree): fix lint errors

* fix(cdk/tree): fix build errors

* fix(cdk/tree): change explicit breaking-change version to PLACEHOLDER

* fix(cdk/tree): also update flat level accessor example

* fix(cdk/tree): update API goldens

* fix(cdk/tree): update API goldens

* feat(cdk/tree): add a translation function to the tree to get children

* fix(cdk/tree): lint

feat(cdk/a11y): add a TreeKeyManager, with next/prev implemented (angular#24659)

* feat(cdk/a11y): add API for TreeKeyManager

* feat(cdk/a11y): add activeItem into the TreeKeyManager

* feat(cdk/a11y): store the options into the key manager

* feat(cdk/a11y): add _getItems translation layer

* feat(cdk/a11y): add skeleton for keydown actions

* feat(cdk/a11y): implement activate item

* feat(cdk/a11y): implement various focus methods

* feat(cdk/a11y): implement onClick, remove lint disables

* feat(cdk/a11y): partial spec migration, fixed some bugs in impl

* fix(cdk/tree): fix lint errors

* fix(cdk/a11y): fix lint errors pt2

feat(cdk/tree): implement expansion methods for TreeKeyManager (angular#26586)

* feat(cdk/a11y): implement expansion methods

* feat(cdk/a11y): add tests and fixes for expand/collapse interactions

* feat(cdk/a11y): actually fix build

* feat(cdk/a11y): use skipPredicate instead of disabled

feat(cdk/tree): implement typeahead for TreeKeyManager (angular#27202)

* feat(cdk/a11y): implement typeahead (needs test)

* feat(cdk/a11y): handle typeahead in keydown handler

* feat(cdk/a11y): fix typeahead build errors

* feat(cdk/a11y): add tests for typeahead

* feat(cdk/a11y): add TreeKeyManager to public a11y API

* fix(cdk/a11y): tree key manager build errors/weird merge

* feat(cdk/a11y): fix api goldens

* fix(cdk/a11y): fix tests

feat(cdk/tree): integrate TreeKeyManager with cdk/tree (angular#27285)

* feat(cdk/tree): add cache of nodes to the tree

* feat(cdk/tree): bug fixes for tree and key manager

* feat(cdk/tree): flatten data that uses childrenAccessor

* feat(cdk/tree): add examples, fix bugs

* fix(cdk/tree): fix build errors

* fix(cdk/tree): restoring incorrectly removed code

* fix(cdk/tree): fix minor typo

* fix(cdk/tree): fix lint

* feat(cdk/tree): add additional tests, fix bug with aria-posinset

* fix(cdk/tree): update goldens, remove fdescribe

* fix(cdk/tree): dev app compilation

* fix(cdk/tree): fix tests

* fix(material/tree): update tests & API

* fix(material/tree): api goldens

* feat(cdk/tree): add `isExpandable` parameter to NestedTreeControl, fix some tests

* fix(cdk/tree): update api goldens

* fix(material/tree): lint

* fix(cdk/tree): update API goldens

feat(cdk/tree): general bug fixes, error handling, updating examples & docs (angular#27305)

* feat(cdk/a11y): add some missing focus functions to TreeKeyManager, fix tests

* feat(cdk/tree): report an error when the API consumer tries to expand a non-expandable node.

* fix(cdk/tree): set node role through component host

* fix(material/tree): fix duplicate keydown events

* fix(cdk/tree): make keyboard behaviour consistent across all configurations

This also removes the need for specifying `nodeType` manually.

* fix(cdk/tree): remove unnecessary change detection

* fix(cdk/tree): update API goldens

* refactor(cdk/tree): organize imports

* fix(cdk/a11y): update API goldens

* fix(cdk/tree): remove `_preFlattenedNodes`

* fix(cdk/tree): lint

* fix(cdk/tree): use `findIndex` instead of `indexOf`; fixes inconsistent aria-posinset

* feat(cdk/tree): add complex redux-like demo

* fix(cdk/tree): refactor rendering pipeline

This also refactors the parent/level/group data processing in order to
make it significantly more consistent in all tree configurations.

* feat(cdk/tree): update tree documentation

* feat(cdk/a11y): update docs for `TreeKeyManager`.

* fix(cdk/tree): update API goldens, fix lint errors

* fix(cdk/tree): empty commit; retry ci actions

docs(material/tree): fix demos where keyboard navigates to hidden nodes

Fix an issue in the tree demos where the keyboard can navigate to nodes
that are not rendered to the screen. This happend because nodes where
hidden using CSS and the TreeKeyManager did not know to skip over them.
Fix this issue by disabled nodes that are hidden so that the
TreeKeyManager will skip them.

Steps to reproduce issue
1. Go to CDK Flat tree (levelAccessor) demo
2. Tab onto Fruit
3. Press down the up
4. (Expands the collapses)
5. Press down
6. (Expecting Vegetables to be focused but focus ring is still around Fruit)
7. Press down five times.
8. (Focus ring is around Fruit).

With this commit applied, above issue no longer reproduces.

This commit message is only for code reviewers and can be deleted when
landing this change in main.

fix(cdk/tree): CdkTreeNodeToggle responds to Enter and Space keys

Implement keydown event for CdkTreeNodeToggle to perform that same
action as click when receiving Enter or Space. Update examples to
expand/collapse nodes when pressing enter.

Fix a11y issue in demos where pressing Enter when focused on a tree node
seems to not perform any action. Use CdkTreeNodeToggle to perform the
action of expanding or collaping the node.

Align with instructions in [APG Tree View
Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/):

"Enter: activates a node, i.e., performs its default action. For parent
nodes, one possible default action is to open or close the node. In
single-select trees where selection does not follow focus (see note
below), the default action is typically to select the focused node."

docs(material/tree): fix keyboard issues with "Load more flat tree"

Fix keyboard navigation issues with the "Load more flat tree" demo.

 - "Load more" button will respond to Enter or Space keys
 - Expanding and collapsing using keyboard shortcuts will trigger
   loading.

fix(cdk/tree): CdkTreeNodeToggle focuses node when toggling it

Fix focus behavior of CdkTreeNodeToggle. When toggling the expanded or
collapsed state of a node, focus that node. Fix issue where end user
cannot tab into tree component when collaping the parent of the active
node.

Before this commit is applied, there is a bug where end user cannot tab
into the tree.

Reproduction steps
1. Active a tree node
2. (focus state renders)
3. Using mouse, collapse parent of node from step 1.
4. (tree node collapses)
5. Press Tab, then shift + tab
6. (item before tree is focused. Can tab into the tree)

With this commit applied, above issue is no longer expected to
reproduce.

This commit message is only for reviewers of this PR and can be deleted
when landing this change in main.

build: fix formatting

docs(material/tree): make "Load More" tree node a button

in the "Load More" tree demo, fix unable to press "Load More" button
when navigating onto it using arrow keys.

DEPRECATED
 * `BaseTreeControl` deprecated in favor of using one of `levelAccessor` or `childrenAccessor`
 * `TreeControl` deprecated in favor of using one of `levelAccessor` or `childrenAccessor`
 * `FlatTreeControl` deprecated in favor of using one of `levelAccessor` or `childrenAccessor`
 * `NestedTreeControl` deprecated in favor of using one of `levelAccessor` or `childrenAccessor`
 * `@Input treeControl` on `CdkTree` deprecated in favor of using one of `levelAccessor` or `childrenAccessor`
 * `@Input tabIndex` on `MatTreeNode` deprecated. Ignore this input and automatically determine the appropriate tabindex for the tree node
 * `@Input defaultTabIndex` on `MatTreeNode` deprecated. Ignore this input and automatically determine the appropriate tabindex for the tree node
 * `@Input tabIndex` on `MatNestedTreeNode` deprecated. Ignore this input and automatically determine the appropriate tabindex for the tree node
 * `@Input disabled` on `MatTreeNode` renamed to `isDisabled`
 * `@Input disabled` on `MatNestedTreeNode` renamed to `isDisabled`
  • Loading branch information
BobobUnicorn authored and zarend committed Sep 22, 2023
1 parent fbc7bdd commit 01e8c0a
Show file tree
Hide file tree
Showing 50 changed files with 6,164 additions and 418 deletions.
60 changes: 59 additions & 1 deletion src/cdk/a11y/a11y.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Navigation through options can be made to wrap via the `withWrap` method
this.keyManager = new FocusKeyManager(...).withWrap();
```

#### Types of key managers
#### Types of list key managers

There are two varieties of `ListKeyManager`, `FocusKeyManager` and `ActiveDescendantKeyManager`.

Expand Down Expand Up @@ -55,6 +55,64 @@ interface Highlightable extends ListKeyManagerOption {

Each item must also have an ID bound to the listbox's or menu's `aria-activedescendant`.

### TreeKeyManager

`TreeKeyManager` manages the active option in a tree view. This is intended to be used with
components that correspond to a `role="tree"` pattern.

#### Basic usage

Any component that uses a `TreeKeyManager` will generally do three things:
* Create a `@ViewChildren` query for the tree items being managed.
* 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:
```ts
interface TreeKeyManagerItem {
/** Whether the item is disabled. */
isDisabled?: (() => boolean) | boolean;

/** The user-facing label for this item. */
getLabel?(): string;

/** Perform the main action (i.e. selection) for this item. */
activate(): void;

/** Retrieves the parent for this item. This is `null` if there is no parent. */
getParent(): TreeKeyManagerItem | null;

/** Retrieves the children for this item. */
getChildren(): TreeKeyManagerItem[] | Observable<TreeKeyManagerItem[]>;

/** Determines if the item is currently expanded. */
isExpanded: (() => boolean) | boolean;

/** Collapses the item, hiding its children. */
collapse(): void;

/** Expands the item, showing its children. */
expand(): void;

/**
* Focuses the item. This should provide some indication to the user that this item is focused.
*/
focus(): void;
}
```

#### Focus management

The `TreeKeyManager` will handle focusing the appropriate item on keyboard interactions. However,
the component should call `onInitialFocus` when the component is focused for the first time (i.e.
when there is no active item).

`tabindex` should also be set by the component when the active item changes. This can be listened to
via the `change` property on the `TreeKeyManager`. In particular, the tree should only have a
`tabindex` set if there is no active item, and should not have a `tabindex` set if there is an
active item. Only the HTML node corresponding to the active item should have a `tabindex` set to
`0`, with all other items set to `-1`.


### FocusTrap

Expand Down
Loading

0 comments on commit 01e8c0a

Please sign in to comment.