-
Notifications
You must be signed in to change notification settings - Fork 6
Tree Specification
-
3.3 Globalization/Localization
3.5 API
Team Name: Astrea
Developer Name: Martin Evtimov, Monika Kirkova
Designer Name:
- Peer Developer Name | Date:
- Design Manager Name | Date:
- Radoslav Mirchev| Date:
- Radoslav Karaivanov | Date:
Version | Users | Date | Notes |
---|---|---|---|
1 |
The <igc-tree>
allows users to represent hierarchical data in a tree-view structure, maintaining parent-child relationships, as well as to define static tree-view structure without a corresponding data model.
<igc-tree>
<igc-tree-item *ngFor="let item of data" [value]="item" [expanded]="isItemExpanded(item)" [selected]="isItemSelected(item)">
{{ item.text }}
<img [src]="item.image" alt="item.imageAlt" />
<igc-tree-item*ngFor="let child of item.children" [value]="child" [expanded]="isItemExpanded(child)" [selected]="isItemSelected(child)">
{{ child.text }}
<igc-tree-item *ngFor="let leafChild of child.children" [value]="leafChild" [expanded]="isItemExpanded(leafChild)" [selected]="isItemSelected(leafChild)">
<a href="{{leafChild.location}}" target="_blank">{{ leafChild.text }}</a>
</igc-tree-item>
</igc-tree-item>
</igc-tree-item>
</igc-tree>
The <igc-tree>
should primarily be used as a navigational component when visualizing a nested data structure. The control is not data-bound and takes a declarative approach, giving users more control over what is being rendered.
The tree should have the following features out-of-the-box
- Rendering nested items in a hierarchical fashion, maintaining a parent-child relationship
- Expanding and collapsing items, so all crucial information can be clearly visible at all times
- Disabled items which do not support any user interaction (e.g. permission-based tree view)
- Active items - a note marked as "active" is highlighted w/ a specific style (e.g. the current location on a site map)
- Selection
- 5.1. None - no selection through user input. API selection manipulation is still possible
- 5.2. Multiple - each item has a checkbox through which it can be selected via user input. Each item has two states - selected or not. Supports multiple selection.
- 5.3. Cascading - selecting an item selects its child items. Partially selected collections mark the resp. items as indeterminate.
- Keyboard navigation, supporting all of the previously mention features
- Accessibility features - all items should have proper aria roles and be fully readable and traversable via screen readers
Developer stories:
- Story 1: As a developer, I want to be able to easily create a tree view declaring the item hierarchy.
- Story 2: As a developer, I want to have full control over an item's content, as well as its child items (declarative approach).
- Story 3: As a developer, I want to have an easy way to find an item inside of the control with out-of-the-box API.
- Story 4: As a developer, I want to expand/collapse one or more items programmatically.
- Story 5: As a developer, I want to enable/disable the selection of a single item.
- Story 6: As a developer, I want to enable/disable the selection of multiple items.
- Story 7: As a developer, I want to enable/disable cascading selection of items so that selecting an item, selects all items in the tree below it as well and the state of each item reflects the cumulative one of its children.
- Story 8: As a developer, I want to set an item's selection state programmatically.
- Story 9: As a developer, I want to set an item's selection state programmatically, even when selection through user interaction is disabled.
- Story 10: As a developer, I want to be able to perform custom handling on user interaction - item selection, expansion/collapsing.
- Story 11: As a developer, I expect that manipulating the data source would update the visualized tree accordingly.
- Story 12: As a developer, I want to be able to load data on demand to expedite initial load times.
- Story 13: As a developer, I want to be able to ensure accessibility e.g. via proper
aria
roles in different cases. - Story 14: As a developer, I want to be able to mark items as disabled, so they are ignored in user interaction.
- Story 15: As a developer, I want to mark an item as the tree's active item, styling it in a pre-defined way and marking it as a point of interest to the users.
- Story 16: As a developer, I want to be able to distinguish when the active item changes through user interaction.
- Story 17: As a developer, I want to be able to bind an item's expansion state to a data model and ensure consistency between the two.
- Story 18: As a developer, I want to be able to bind an item's selection state to a data model and ensure consistency between the two.
- Story 19: As a developer, I want to be able to template the expand/collapse indicators for the tree.
- Story 20: As a developer, I want to be able to specify how many expanded sibling items there can be (
singleBranchExpand
input).
End-user stories:
The tree should allow me, as an end-user, to understand the relationships between the various items and use it to navigate the hierarchy of content.
- Story 1: As an end-user, I want to have the items organized in a clear hierarchy, so that I can understand their relationship with one another.
- Story 2: As an end-user, I want to have the items organized in a clear hierarchy, so that I can easily expand/collapse them and select the items I am looking for.
- Story 3: As an end-user, I want to be able to expand/collapse items, so that I can create a state with the most viable information for me on my screen.
- Story 4: As an end-user, I want to have a clear indication of the selected (active) item, so that I have a better understanding of the information I'm looking at on the rest of my screen.
- Story 5: As an end-user, I want to have a clear indication if some/all/none of the child items of a given item are selected, so that I have a clear understanding of the current selection of items.
- Story 6: As an end-user, I want to select a single item, so that I navigate to the content it offers.
- Story 7: As an end-user, I want to select multiple items, so that I can perform an operation on all of them at once.
- Story 8: As an end-user, I want to have a cascading selection of a parent item implicitly selecting all of its children, grandchildren, etc., so that I can perform an operation on all of them at once.
- Story 9: As an end-user, I want to be able to quickly expand/collapse/select an item with a mouse and keyboard, so that I have a variety of convenient ways to interact with the hierarchy.
- Story 10: As an end-user, I want to have a clear visual indication of when an item is loading its information/children, so that I have expectancy in scenarios with remote data/load on demand.
Describe behavior, design, look and feel of the implemented feature. Always include visual mock-up
The IgcTreeComponent
should support the three display sizes available for other components - 'small'
, 'medium'
and 'large'
(default). They come with distinct item heights and padding.
** All use cases and variants above are also available for hand-off
Developers are able to declare the tree and its items by specifying the item hierarchy and iterating through a data set:
<!-- Standard example -->
<igc-tree>
<igc-tree-item *ngFor="let item of data" [value]="item" [expanded]="isItemExpaded(item)" [selected]="isItemSelected(item)">
{{ item.text }}
<img [src]="item.image" [alt]="item.imageAlt" />
<igc-tree-item *ngFor="let child of item.children" [value]="child" [expanded]="isItemExpaded(child)" [selected]="isItemSelected(child)">
{{ child.text }}
</igc-tree-item>
</igc-tree-item>
</igc-tree>
Tree items can be bound to a data model so that their expanded
and selected
states are reflected in the data.
<igc-tree (igcSelection)="handleSelectionEvent($event)">
<igc-tree-item *ngFor="let item of data" [value]="item" [(expanded)]="item.expanded" [(selected)]="item.selected">
{{ item.text }}
<img [src]="item.image" [alt]="item.imageAlt" />
<igc-tree-item *ngFor="let child of item.children" [value]="child">
<a [href]="child.url" target="_blank">{{ child.text }}</a>
</igc-tree-item>
</igc-tree-item>
</igc-tree>
To render a tree you do not necessarily need a data set - developers can create individual items w/o binding them to data:
<!-- Simple example with hardcoded items -->
<igc-tree>
<igc-tree-item [expanded]="true" [selected]="false">
I am a parent item 1
<img [src]="hard_coded_src.webb" alt="Alt Text" />
<igc-tree-item [expanded]="true" [selected]="false">
I am a child item 1
</igc-tree-item>
</igc-tree-item>
<igc-tree-item [expanded]="false" [selected]="false">
I am a parent item 2
<img src="hard_coded_src.webb" alt="Alt Text" />
<igc-tree-item [expanded]="false" [selected]="false">
I am a child item 1
</igc-tree-item>
</igc-tree-item>
</igx-tree>
3.3. Globalization/Localization
Describe any special localization requirements such as the number of localizable strings, regional formats
The keyboard can be used to navigate through all items in the tree.
The control distinguishes two states - focused
and active
.
The focused item is where all events are fired and from where navigation will begin/continue. Focused items are marked with a distinct style.
The active item, in most cases, is the last item on which user interaction took place. Active items also have a distinct style. Active items can be used to better accent an item in that tree that indicates the app's current state (e.g. a current route in the app when using a tree as a navigation component).
In most cases, moving the focused item also moves the active item.
When navigating to items that are outside of view, if the tree (igc-tree
tag) has a scrollbar, scrolls the focused item into view.
If the target item is outside of view AND if the tree (igc-tree
tag) has a scrollbar, scrolls the focused item into view.
When initializing the tree and an item is marked as active, if that item is outside of view AND if the tree (igc-tree
tag) has a scrollbar, scrolls the activated item into view.
FIRST and LAST item refers to the respective visible item WITHOUT expanding/collapsing any existing item.
Disabled items are not counted as visible items for the purpose of keyboard navigation.
Keys | Description | Activates Item |
---|---|---|
ARROW DOWN | Moves to the next visible item. Does nothing if on the LAST tree item. | true |
CTRL + ARROW DOWN | Performs the same as ARROW DOWN. | false |
ARROW UP | Moves to the previous visible item. Does nothing if on the FIRST tree item. | true |
CTRL + ARROW UP | Performs the same as ARROW UP. | false |
TAB | Navigate to the next focusable element on the page* | false |
SHIFT + TAB | Navigate to the previous focusable element on the page* | false |
HOME | Navigates to the FIRST tree item. | true |
END | Navigates to the LAST tree item. | true |
ARROW RIGHT | On an expanded parent item, navigate to the first child of the item. If on a collapsed parent item, expand it. | true |
ARROW LEFT | On an expanded parent item, collapses it. If on a child item, moves to its parent item. | true |
SPACE | Toggles selection of the current tree item. Marks the tree item as active. | true |
* | Expand the tree item and all sibling items on the same level w/ children | true |
CLICK | Focuses the tree item | true |
When selection is enabled, end-user selection of tree items is only allowed through the displayed checkbox. Since both selection types allow multiple selection, the following mouse + keyboard interaction is available:
Combination | Description | Activates Item |
---|---|---|
SHIFT + CLICK / SPACE | when multiple selection is enabled, toggles selection of all tree items between the active one and the one clicked while holding SHIFT. | true |
Name | Description | Type |
---|---|---|
items | Returns all of the tree's items | IgcTreeItemComponent[] |
Name | Description | Type | Default value | Reflected |
---|---|---|---|---|
selection | The selection state of the tree. |
"None" | "Multiple" | "Cascading"
|
"None" |
true |
singleBranchExpand | Whether a single or multiple of a parent's child items can be expanded. | boolean |
false |
true |
hasFocusableContent | Determines whether the tree items has content which should be tabbable. | boolean |
false |
true |
size | Get\Set the size of the tree. Affects all child items | small | medium | large |
large |
true |
Name | Description | Parameters | Returns |
---|---|---|---|
deselect | Deselects all items. If items array is passed, deselects only the specified items. Does not emit igcSelection event. |
items?: IgcTreeItemComponent[] |
void |
select | Selects all tree items. If items array is passed, selects only the specified items. Does not emit igcSelection event. |
items?: IgcTreeItemComponent[] |
void |
collapse | Collapses the specified tree items. If no items passed, collapses all parent items. | items?: IgcTreeItemComponent[] |
void |
expand | Sets the specified tree items as expanded. If no items passed, expands all parent items. | items?: IgcTreeItemComponent[] |
void |
Name | Description | Cancelable | Arguments |
---|---|---|---|
igcSelection | Emitted when item selection is changing, before the selection completes | true | { newSelection: IgcTreeItemComponent[], oldSelection: IgcTreeItemComponent[] } |
igcItemCollapsed | Emitted when tree item is collapsed. | false | { item: IgcTreeItemComponent } |
igcItemCollapsing | Emitted when tree item is collapsing, when item.expanded is set to transition from true to false . |
true | { item: IgcTreeItemComponent } |
igcItemExpanded | Emitted when tree item is expanded. | false | { item: IgcTreeItemComponent } |
igcItemExpanding | Emitted when tree item expanding animation starts, when item.expanded is set to transition from false to true . |
true | item: IgcTreeItemComponent, owner: IgcTreeComponent } |
igcItemActivated | Emitted when the tree's active item changes |
false | IgcTreeItemComponent |
Name | Description |
---|---|
(default) | Renders the tree. |
Name | Description | Type |
---|---|---|
parent | The parent item of the current tree item (if any) | IgcTreeItemComponent |
path | The full path to the tree item, starting from the top-most ancestor | IgcTreeItemComponent[] |
level | The "depth" of the tree item. If root item - 0, if a child of parent - parent.level + 1 |
number |
tree | A reference to the tree the item is a part of | IgcTreecomponent |
Name | Description | Type | Default value | Reflected |
---|---|---|---|---|
disabled | Get/Set whether the tree item is disabled. Disabled items are ignored for user interactions. | boolean |
false |
true |
expanded | The tree item expansion state. |
boolean | null
|
false |
true |
selected | The tree item selection state. | boolean |
false |
true |
value | The value entry that the tree item is visualizing. Required for searching through items. | any |
||
active | Marks the item as the tree's active item | boolean |
false |
true |
Name | Description | Parameters | Returns |
---|---|---|---|
expand | Expands the tree item | None | void |
collapse | Collapses the tree item | None | void |
toggle | Toggles tree item expansion state | None | void |
getChildren | Returns a collection of child items. If the parameter value is true returns all tree item's children, otherwise - only the direct children. |
{ flatten: boolean } |
IgxTreeItemComponent[] |
Name | Description |
---|---|
(default) | Renders the tree item. |
label | The tree item container. |
indicator | The expand indicator container. |
indentation | The container (by default the space) before the tree item. |
Automation
- Should render tree w/ items
- Should support multiple levels of nesting (igc-tree-item under igc-tree-item)
- Should calculate items'
path
andlevel
correctly, depending on data hierarchy - Should not render collapsed item's children
- Should not render expand indicator if an item has no children
- Should not render children if an item is loading
- Should not render default select indicator if selection mode is
'None'
- Should render default indicator for expansion properly depending on item state
- Should render default select marker properly depending on item state
- Should accept template for expansion indicator
- Should accept template for indentation area
- Should accept template for the item label
- Should emit igcActiveItem event when the active item changes
- Should activate the last tree item set as active if there are multiple
- Should render items correctly depending on
size
settings
- Should collapse items when user interacts w/ indicator and
item.expanded === false
- Should expand items when user interacts w/ indicator and
item.expanded === true
- Should emit
ing
anded
events when item state is toggled - Should collapse all child items when collapsing a item
- Should collapse sibling items when
singleBranchExpand === true
- Should collapse items when
item.expanded
is set tofalse
- Should expand items when
item.expanded
is set totrue
- Should expand items when
item.expand()
is called - Should collapse items when
item.collapse()
is called - Should toggle item state when
item.toggle()
is called
- Should be able to change selection type to all 3 options ('None' (default), 'Multiple', 'Cascading')
- Should deselect all selected items w/
tree.deselect()
- Should deselect only specified items w/
tree.deselect(item: IgcTreeItemComponent[])
- Should select all deselected items w/
tree.select()
- Should select only specified items w/
tree.select(item: IgcTreeItemComponent[])
- Should allow setting items as selected through API when
tree.selection === 'None'
- Should not render indicators when
tree.selection === 'None'
- Should select/deselect item by click on checkbox
- Should emit
igcSelection
event w/ correct args when an item is selected / deselected - Should support multiple selection (e.g. newly selected items do not empty selected collection)
- Should be able to set
item.selected
correctly
- Selecting an item should select its children
- Selecting all children of a parent should mark the parent as selected. All direct and non-direct parents should be affected correctly.
- Deselecting all children of a parent should mark the parent as deselected. All direct and non-direct parents should be affected correctly.
- Selecting a single child should mark the parent as indeterminate. All direct and non-direct parents should be affected correctly.
- Selecting the last non-selected child should mark the parent as selected and NOT indeterminate. All direct and non-direct parents should be affected correctly.
- Set nested child, that has its own children, as initially selected. Verify that direct and indirect parents have correct states.
- Partially selected parents should have the default indicator rendered as
indeterminate
- When selecting a range of records using Shift + click key selection of parents should select all their children even if they are not in the selected range.
- In case that there are already selected items in the tree, click on the parent item, that is not selected, should select only the newly clicked item and its children and deselect the rest.
- In case that there are already selected items in the tree, click on the parent item that is not selected should add the item and its children to the selected rows collection even if child items are not in the selected range.
- Should focus and activate the first tree item on
Home
key press - Should focus and activate the last visible tree item on
End
key press - Should not navigate when a tree item has no parent and item is collapsed on
Arrow Left
key press - Should navigate to the parent item of a tree item w/
expanded === true
onArrow Left
key press, moving focus and active - Should collapse expanded tree items on
Arrow Left
key press - Should not navigate when a tree item has no children on
Arrow Right
key press - Should navigate to the first child of an expanded on
Arrow Right
key press, moving focus and active - Should expand collapsed tree item w/ children on
Arrow Right
key press - Should focus and activate the next visible tree item on
Arrow Down
key press - Should only focus the next visible tree item on
Arrow Down + Ctrl
key press - Should focus and activate the previous visible tree item on
Arrow Up
key press - Should only focus the previous visible tree item on
Arrow Up + Ctrl
key press - Should expand all sibling tree items of the focused item on asterisk (
*
) key press - Should active the focused tree item on
Enter
key press - Should not prevent event's default behavior on
Enter
key press - Should perform nothing when
tree.selection === 'None'
onSpace
key press - Should select item when
tree.selection !== 'None'
onSpace
key press, moving active - Should select item range when
tree.selection !== 'None'
onSpace + Shift
keys press, moving active - Should emit
tree.igcActiveItemChange
when the active item changes - Should scroll to
active
item if the tree has scrollbar and item is out of view
- Should render disabled items as not reachable for tab navigation (
tabIndex
should-1
) - Should not count disabled items as traversable items for keyboard navigation purposes
- If a tree item is expanded and all its children are disabled the focus and activation should not be moved from the item on
Arrow Right
key press - If a tree item is expanded and has enabled children the focus and activation should be moved to the first enabled child on
Arrow Right
key press - Pressing Arrow Up/Down should move the focus and activation to the previous/next enabled and visible item (if there is any) (skipping disabled)
- Pressing Asterisk on a focused item should expand only the enabled and expandable items in the same group
- Should render proper role and attributes for the tree
- Should render proper aria attributes for each tree-item
ARIA Support Tree Aria example
An igc-tree
will have role="tree"
. aria-labelledby
should be manually added if there is a label/ heading associated w/ the tree.
An igc-tree-item
's child will be held in a container w/ role="group"
.
An igc-tree-item
will have role="treeitem"
if its disableTab
property is not enabled.
If it is enabled, the role="treeitem"
will go on the child element.
A item's expanded state will be properly reflected in the item's aria-expanded
attribute.
RTL Support
Assumptions | Limitation Notes |
---|---|