Skip to content

Commit

Permalink
TreeGrid: Convert to TypeScript (#47516)
Browse files Browse the repository at this point in the history
* TreeGridRow: Convert to TypeScript

* Add types for roving tab index

* Actually throw if context is undefined

* TreeGridItem: Add types

* TreeGridCell: Add types

* TreeGrid: Add types

* Fixup

* Convert stories

* Convert tests

* Exclude from tsconfig

* Improve prop description for `withoutGridItem`

* Simply focusable element type

* Remove unnecessary eslint-disable

* Tweak aria types

* Update readme

* Add changelog

* Change confusing story

* Shift all possible `Element`s to `HTMLElement`
  • Loading branch information
mirka authored Feb 3, 2023
1 parent 12791ec commit 464426a
Show file tree
Hide file tree
Showing 28 changed files with 609 additions and 333 deletions.
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
- `Button`: Convert to TypeScript ([#46997](https://github.com/WordPress/gutenberg/pull/46997)).
- `BoxControl`: Convert to TypeScript ([#47622](https://github.com/WordPress/gutenberg/pull/47622)).
- `QueryControls`: Convert to TypeScript ([#46721](https://github.com/WordPress/gutenberg/pull/46721)).
- `TreeGrid`: Convert to TypeScript ([#47516](https://github.com/WordPress/gutenberg/pull/47516)).
- `Notice`: refactor to TypeScript ([47118](https://github.com/WordPress/gutenberg/pull/47118)).

### Bug Fix
Expand Down
76 changes: 18 additions & 58 deletions packages/components/src/tree-grid/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This feature is still experimental. “Experimental” means this is an early im

## Development guidelines

`TreeGrid`, `TreeGridRow`, and `TreeGridCell` are components used to create a tree hierarchy. They're not visually styled components, but instead help with adding keyboard navigation and roving tab index behaviors to tree grid structures.
`TreeGrid`, `TreeGridRow`, and `TreeGridCell` are components used to create a tree hierarchy. They're not visually styled components, but instead help with adding keyboard navigation and roving tabindex behaviors to tree grid structures.

A tree grid is a hierarchical 2 dimensional UI component, for example it could be used to implement a file system browser.

Expand All @@ -31,69 +31,36 @@ function TreeMenu() {
<TreeGridRow level={ 1 } positionInSet={ 1 } setSize={ 2 }>
<TreeGridCell>
{ ( props ) => (
<Button onClick={ onSelect } { ...props }>
Select
</Button>
<Button onClick={ onSelect } { ...props }>Select</Button>
) }
</TreeGridCell>
<TreeGridCell>
{ ( props ) => (
<Button onClick={ onMoveUp } { ...props }>
Move Up
</Button>
) }
</TreeGridCell>
<TreeGridCell>
{ ( props ) => (
<Button onClick={ onMoveDown } { ...props }>
Move Down
</Button>
<Button onClick={ onMove } { ...props }>Move</Button>
) }
</TreeGridCell>
</TreeGridRow>
<TreeGridRow level={ 1 } positionInSet={ 2 } setSize={ 2 }>
<TreeGridCell>
{ ( props ) => (
<Button onClick={ onSelect } { ...props }>
Select
</Button>
) }
</TreeGridCell>
<TreeGridCell>
{ ( props ) => (
<Button onClick={ onMoveUp } { ...props }>
Move Up
</Button>
<Button onClick={ onSelect } { ...props }>Select</Button>
) }
</TreeGridCell>
<TreeGridCell>
{ ( props ) => (
<Button onClick={ onMoveDown } { ...props }>
Move Down
</Button>
<Button onClick={ onMove } { ...props }>Move</Button>
) }
</TreeGridCell>
</TreeGridRow>
<TreeGridRow level={ 2 } positionInSet={ 1 } setSize={ 1 }>
<TreeGridCell>
{ ( props ) => (
<Button onClick={ onSelect } { ...props }>
Select
</Button>
) }
</TreeGridCell>
<TreeGridCell>
{ ( props ) => (
<Button onClick={ onMoveUp } { ...props }>
Move Up
</Button>
<Button onClick={ onSelect } { ...props }>Select</Button>
) }
</TreeGridCell>
<TreeGridCell>
{ ( props ) => (
<Button onClick={ onMoveDown } { ...props }>
Move Down
</Button>
<Button onClick={ onMove } { ...props }>Move</Button>
) }
</TreeGridCell>
</TreeGridRow>
Expand All @@ -112,27 +79,24 @@ Aside from the documented callback functions, any props specified will be passed

`TreeGrid` should always have children.

###### onFocusRow( event: Event, startRow: HTMLElement, destinationRow: HTMLElement )
###### `onFocusRow`: `( event: KeyboardEvent, startRow: HTMLElement, destinationRow: HTMLElement ) => void`

Callback that fires when focus is shifted from one row to another via the Up and Down keys. Callback is also fired on Home and End keys which move focus from the beginning row to the end row.
The callback is passed the event, the start row element that the focus was on originally, and
the destination row element after the focus has moved.

- Type: `Function`
- Required: No

###### onCollapseRow( row: HTMLElement )
###### `onCollapseRow`: `( row: HTMLElement ) => void`

A callback that passes in the row element to be collapsed.

- Type: `Function`
- Required: No

###### onExpandRow( row: HTMLElement )
###### `onExpandRow`: `( row: HTMLElement ) => void`

A callback that passes in the row element to be expanded.

- Type: `Function`
- Required: No

#### TreeGridRow
Expand All @@ -141,32 +105,28 @@ A callback that passes in the row element to be expanded.

Additional props other than those specified below will be passed to the `tr` element rendered by `TreeGridRow`, so for example, it is possible to also set a `className` on a row.

###### level
###### `level`: `number`

An integer value designating the level in the hierarchical tree structure. Counting starts at 1. A value of `1` indicates the root level of the structure.

- Type: `Number`
- Required: Yes

###### positionInSet
###### `positionInSet`: `number`

An integer value that represents the position in the set. A set is the count of elements at a specific level. Counting starts at 1.

- Type: `Number`
- Required: Yes

###### setSize
###### `setSize`: `number`

An integer value that represents the total number of items in the set ... that is the total number of items at this specific level of the hierarchy.
An integer value that represents the total number of items in the set, at this specific level of the hierarchy.

- Type: `Number`
- Required: Yes

###### isExpanded
###### `isExpanded`: `boolean`

An optional value that designates whether a row is expanded or collapsed. Currently this value only sets the correct aria-expanded property on a row, it has no other built-in behavior.

- Type: `Boolean`
- Required: No

### TreeGridCell
Expand All @@ -182,14 +142,14 @@ An optional value that designates whether a row is expanded or collapsed. Curren
```jsx
<TreeGridCell>
{ ( props ) => (
<Button onClick={ onMoveDown } { ...props }>
Move Down
<Button onClick={ doSomething } { ...props }>
Do something
</Button>
) }
</TreeGridCell>
```

Props passed as an argument to the render prop must be passed to the child focusable component/element within the cell. If a component is used, it must correctly handle the `onFocus`, `tabIndex`, and `ref` props, passing these to the element it renders. These props are used to handle the roving tab index functionality of the tree grid.
Props passed as an argument to the render prop must be passed to the child focusable component/element within the cell. If a component is used, it must correctly handle the `onFocus`, `tabIndex`, and `ref` props, passing these to the element it renders. These props are used to handle the roving tabindex functionality of the tree grid.

## Related components

Expand Down
24 changes: 0 additions & 24 deletions packages/components/src/tree-grid/cell.js

This file was deleted.

41 changes: 41 additions & 0 deletions packages/components/src/tree-grid/cell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* WordPress dependencies
*/
import { forwardRef } from '@wordpress/element';

/**
* Internal dependencies
*/
import TreeGridItem from './item';
import type { WordPressComponentProps } from '../ui/context';
import type { TreeGridCellProps } from './types';

function UnforwardedTreeGridCell(
{
children,
withoutGridItem = false,
...props
}: WordPressComponentProps< TreeGridCellProps, 'td', false >,
ref: React.ForwardedRef< any >
) {
return (
<td { ...props } role="gridcell">
{ withoutGridItem ? (
<>{ children }</>
) : (
<TreeGridItem ref={ ref }>{ children }</TreeGridItem>
) }
</td>
);
}

/**
* `TreeGridCell` is used to create a tree hierarchy.
* It is not a visually styled component, but instead helps with adding
* keyboard navigation and roving tab index behaviors to tree grid structures.
*
* @see {@link https://www.w3.org/TR/wai-aria-practices/examples/treegrid/treegrid-1.html}
*/
export const TreeGridCell = forwardRef( UnforwardedTreeGridCell );

export default TreeGridCell;
Loading

1 comment on commit 464426a

@github-actions
Copy link

Choose a reason for hiding this comment

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

Flaky tests detected in 464426a.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/4084174285
📝 Reported issues:

Please sign in to comment.