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

TreeGrid: Convert to TypeScript #47516

Merged
merged 20 commits into from
Feb 3, 2023
Merged

TreeGrid: Convert to TypeScript #47516

merged 20 commits into from
Feb 3, 2023

Conversation

mirka
Copy link
Member

@mirka mirka commented Jan 28, 2023

Part of #35744

What?

Convert the TreeGrid component and its subcomponents to TypeScript, including stories and tests.

How?

See inline comments.

Testing Instructions

npm run storybook:dev and check the Docs view for TreeGrid.

@mirka mirka added the [Package] Components /packages/components label Jan 28, 2023
@mirka mirka self-assigned this Jan 28, 2023
@github-actions
Copy link

github-actions bot commented Jan 28, 2023

Size Change: +63 B (0%)

Total Size: 1.31 MB

Filename Size Change
build/components/index.min.js 203 kB +63 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 993 B
build/annotations/index.min.js 2.78 kB
build/api-fetch/index.min.js 2.27 kB
build/autop/index.min.js 2.15 kB
build/blob/index.min.js 483 B
build/block-directory/index.min.js 7.2 kB
build/block-directory/style-rtl.css 1.04 kB
build/block-directory/style.css 1.04 kB
build/block-editor/content-rtl.css 4.11 kB
build/block-editor/content.css 4.1 kB
build/block-editor/default-editor-styles-rtl.css 403 B
build/block-editor/default-editor-styles.css 403 B
build/block-editor/index.min.js 192 kB
build/block-editor/style-rtl.css 14.3 kB
build/block-editor/style.css 14.3 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 138 B
build/block-library/blocks/audio/theme.css 138 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 91 B
build/block-library/blocks/avatar/style.css 91 B
build/block-library/blocks/block/editor-rtl.css 305 B
build/block-library/blocks/block/editor.css 305 B
build/block-library/blocks/button/editor-rtl.css 485 B
build/block-library/blocks/button/editor.css 485 B
build/block-library/blocks/button/style-rtl.css 532 B
build/block-library/blocks/button/style.css 532 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 239 B
build/block-library/blocks/calendar/style.css 239 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 100 B
build/block-library/blocks/categories/style.css 100 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 406 B
build/block-library/blocks/columns/style.css 406 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 199 B
build/block-library/blocks/comment-template/style.css 198 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 612 B
build/block-library/blocks/cover/editor.css 613 B
build/block-library/blocks/cover/style-rtl.css 1.57 kB
build/block-library/blocks/cover/style.css 1.56 kB
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 138 B
build/block-library/blocks/embed/theme.css 138 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 253 B
build/block-library/blocks/file/style.css 254 B
build/block-library/blocks/file/view.min.js 353 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 984 B
build/block-library/blocks/gallery/editor.css 988 B
build/block-library/blocks/gallery/style-rtl.css 1.55 kB
build/block-library/blocks/gallery/style.css 1.55 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 654 B
build/block-library/blocks/group/editor.css 654 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/html/editor-rtl.css 332 B
build/block-library/blocks/html/editor.css 333 B
build/block-library/blocks/image/editor-rtl.css 829 B
build/block-library/blocks/image/editor.css 828 B
build/block-library/blocks/image/style-rtl.css 627 B
build/block-library/blocks/image/style.css 630 B
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/latest-comments/style-rtl.css 298 B
build/block-library/blocks/latest-comments/style.css 298 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 478 B
build/block-library/blocks/latest-posts/style.css 478 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 507 B
build/block-library/blocks/media-text/style.css 505 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 716 B
build/block-library/blocks/navigation-link/editor.css 715 B
build/block-library/blocks/navigation-link/style-rtl.css 115 B
build/block-library/blocks/navigation-link/style.css 115 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 299 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation/editor-rtl.css 2.13 kB
build/block-library/blocks/navigation/editor.css 2.14 kB
build/block-library/blocks/navigation/style-rtl.css 2.22 kB
build/block-library/blocks/navigation/style.css 2.2 kB
build/block-library/blocks/navigation/view-modal.min.js 2.81 kB
build/block-library/blocks/navigation/view.min.js 447 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 376 B
build/block-library/blocks/page-list/editor.css 376 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 174 B
build/block-library/blocks/paragraph/editor.css 174 B
build/block-library/blocks/paragraph/style-rtl.css 279 B
build/block-library/blocks/paragraph/style.css 281 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 501 B
build/block-library/blocks/post-comments-form/style.css 501 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B
build/block-library/blocks/post-excerpt/editor.css 73 B
build/block-library/blocks/post-excerpt/style-rtl.css 134 B
build/block-library/blocks/post-excerpt/style.css 134 B
build/block-library/blocks/post-featured-image/editor-rtl.css 586 B
build/block-library/blocks/post-featured-image/editor.css 584 B
build/block-library/blocks/post-featured-image/style-rtl.css 318 B
build/block-library/blocks/post-featured-image/style.css 318 B
build/block-library/blocks/post-navigation-link/style-rtl.css 153 B
build/block-library/blocks/post-navigation-link/style.css 153 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 282 B
build/block-library/blocks/post-template/style.css 282 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 326 B
build/block-library/blocks/pullquote/style.css 325 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 288 B
build/block-library/blocks/query-pagination/style.css 284 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/query/editor-rtl.css 458 B
build/block-library/blocks/query/editor.css 457 B
build/block-library/blocks/quote/style-rtl.css 213 B
build/block-library/blocks/quote/style.css 213 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/read-more/style-rtl.css 132 B
build/block-library/blocks/read-more/style.css 132 B
build/block-library/blocks/rss/editor-rtl.css 149 B
build/block-library/blocks/rss/editor.css 149 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 409 B
build/block-library/blocks/search/style.css 406 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 234 B
build/block-library/blocks/separator/style.css 234 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 474 B
build/block-library/blocks/shortcode/editor.css 474 B
build/block-library/blocks/site-logo/editor-rtl.css 490 B
build/block-library/blocks/site-logo/editor.css 490 B
build/block-library/blocks/site-logo/style-rtl.css 203 B
build/block-library/blocks/site-logo/style.css 203 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.4 kB
build/block-library/blocks/social-links/style.css 1.39 kB
build/block-library/blocks/spacer/editor-rtl.css 332 B
build/block-library/blocks/spacer/editor.css 332 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 433 B
build/block-library/blocks/table/editor.css 433 B
build/block-library/blocks/table/style-rtl.css 651 B
build/block-library/blocks/table/style.css 650 B
build/block-library/blocks/table/theme-rtl.css 157 B
build/block-library/blocks/table/theme.css 157 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 404 B
build/block-library/blocks/template-part/editor.css 404 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 99 B
build/block-library/blocks/verse/style.css 99 B
build/block-library/blocks/video/editor-rtl.css 552 B
build/block-library/blocks/video/editor.css 555 B
build/block-library/blocks/video/style-rtl.css 179 B
build/block-library/blocks/video/style.css 179 B
build/block-library/blocks/video/theme-rtl.css 139 B
build/block-library/blocks/video/theme.css 139 B
build/block-library/classic-rtl.css 162 B
build/block-library/classic.css 162 B
build/block-library/common-rtl.css 1.05 kB
build/block-library/common.css 1.05 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 11.5 kB
build/block-library/editor.css 11.5 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/index.min.js 199 kB
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/style-rtl.css 12.5 kB
build/block-library/style.css 12.5 kB
build/block-library/theme-rtl.css 698 B
build/block-library/theme.css 703 B
build/block-serialization-default-parser/index.min.js 1.13 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/blocks/index.min.js 50.4 kB
build/components/style-rtl.css 11.6 kB
build/components/style.css 11.7 kB
build/compose/index.min.js 12.3 kB
build/core-data/index.min.js 15.9 kB
build/customize-widgets/index.min.js 11.8 kB
build/customize-widgets/style-rtl.css 1.41 kB
build/customize-widgets/style.css 1.41 kB
build/data-controls/index.min.js 663 B
build/data/index.min.js 8.06 kB
build/date/index.min.js 32.1 kB
build/deprecated/index.min.js 518 B
build/dom-ready/index.min.js 336 B
build/dom/index.min.js 4.71 kB
build/edit-post/classic-rtl.css 571 B
build/edit-post/classic.css 571 B
build/edit-post/index.min.js 34.5 kB
build/edit-post/style-rtl.css 7.46 kB
build/edit-post/style.css 7.45 kB
build/edit-site/index.min.js 64.2 kB
build/edit-site/style-rtl.css 9.65 kB
build/edit-site/style.css 9.65 kB
build/edit-widgets/index.min.js 16.9 kB
build/edit-widgets/style-rtl.css 4.49 kB
build/edit-widgets/style.css 4.49 kB
build/editor/index.min.js 45.5 kB
build/editor/style-rtl.css 3.57 kB
build/editor/style.css 3.57 kB
build/element/index.min.js 4.93 kB
build/escape-html/index.min.js 548 B
build/experiments/index.min.js 905 B
build/format-library/index.min.js 7.23 kB
build/format-library/style-rtl.css 598 B
build/format-library/style.css 597 B
build/hooks/index.min.js 1.66 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.79 kB
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.79 kB
build/keycodes/index.min.js 1.88 kB
build/list-reusable-blocks/index.min.js 2.14 kB
build/list-reusable-blocks/style-rtl.css 865 B
build/list-reusable-blocks/style.css 865 B
build/media-utils/index.min.js 2.99 kB
build/notices/index.min.js 977 B
build/plugins/index.min.js 1.95 kB
build/preferences-persistence/index.min.js 2.23 kB
build/preferences/index.min.js 1.35 kB
build/primitives/index.min.js 960 B
build/priority-queue/index.min.js 1.52 kB
build/react-i18n/index.min.js 702 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.75 kB
build/reusable-blocks/index.min.js 2.26 kB
build/reusable-blocks/style-rtl.css 265 B
build/reusable-blocks/style.css 265 B
build/rich-text/index.min.js 10.8 kB
build/server-side-render/index.min.js 2.09 kB
build/shortcode/index.min.js 1.52 kB
build/style-engine/index.min.js 1.53 kB
build/token-list/index.min.js 650 B
build/url/index.min.js 3.69 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.8 kB
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 1.09 kB
build/warning/index.min.js 280 B
build/widgets/index.min.js 7.31 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.18 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

@github-actions
Copy link

github-actions bot commented Jan 28, 2023

Flaky tests detected in 2497ee6.
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/4077659498
📝 Reported issues:

Comment on lines -41 to -50
<Button onClick={ onMoveUp } { ...props }>
Move Up
</Button>
) }
</TreeGridCell>
<TreeGridCell>
{ ( props ) => (
<Button onClick={ onMoveDown } { ...props }>
Move Down
</Button>
Copy link
Member Author

Choose a reason for hiding this comment

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

Simplified this code snippet a bit to cut down on the number of lines.

if ( ! focusablesInRow || ! focusablesInRow.length ) {
return;
}
} ) as FocusableElement[];
Copy link
Member Author

Choose a reason for hiding this comment

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

Anything that is returned from this function can be assumed to have a focus() method.

Copy link
Contributor

@ciampo ciampo Feb 1, 2023

Choose a reason for hiding this comment

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

Why not use HTMLElement directly instead of FocusableElement?

Or at least, could we Pick< HTMLElement, 'focus' > ?

Copy link
Member Author

@mirka mirka Feb 1, 2023

Choose a reason for hiding this comment

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

You're right, I think I misunderstood something. Fixed in 52cbdd9

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you!

I was wondering if we could push this further and see if more (if not all) of the Element types in this component can be changed to HTMLElement?

For example, I noticed that onFocusRow / onCollapseRow / onExpandRow were previously documented as accepting an HTMLElement

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea. Done in d30ea0b

@@ -65,7 +60,9 @@ function TreeGrid(

if (
hasModifierKeyPressed ||
! [ UP, DOWN, LEFT, RIGHT, HOME, END ].includes( keyCode )
! ( [ UP, DOWN, LEFT, RIGHT, HOME, END ] as number[] ).includes(
Copy link
Member Author

Choose a reason for hiding this comment

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

Apparently, importing these keycode constants implies that they are really consts.

// Normally, doing this in a single file is ok.
const UP = 30;
const foo = (n: number) => {
  return [UP].includes(n)
}

// But when `UP` is imported (I think) it becomes equivalent to
const UP = 30 as const;

// And then this won't pass
const foo = (n: number) => {
  // Argument of type 'number' is not assignable to parameter of type '30'.
  return [UP].includes(n)
}

🤷🤷🤷

Copy link
Contributor

Choose a reason for hiding this comment

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

🤷

if ( ! treeGridElement.contains( activeElement ) ) {

if (
! activeElement ||
Copy link
Member Author

Choose a reason for hiding this comment

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

This early return is just to appease TS, but actual runtime behavior should not change because if activeElement were falsey treeGridElement.contains( activeElement ) would also be falsey.

packages/components/src/tree-grid/index.tsx Show resolved Hide resolved
Comment on lines 7 to 14
| {
lastFocusedElement: Element | undefined;
setLastFocusedElement: React.Dispatch<
React.SetStateAction< Element | undefined >
>;
}
| undefined
>( undefined );
Copy link
Member Author

Choose a reason for hiding this comment

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

It would be easy to set up a "safer" default for this context value (for example an empty object {}), but a unit test implies that we should actually be throwing if the context is not properly initialized. So I'm leaving this as is (just more explicitly undefined I guess).

return children( allProps );
}

if ( ! Component ) return null;
Copy link
Member Author

Choose a reason for hiding this comment

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

Just an added guard, but nevertheless a runtime change.

Interestingly, there are no actual usages of this as prop in the repo.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe there were when the as = Component prop destructuring was introduced, but since then it was removed

Copy link
Contributor

Choose a reason for hiding this comment

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

Did some more investigation — this component was introduced as a separate component from TreeGrid and it seemed to have the as prop from its beginnings: https://github.com/WordPress/gutenberg/pull/18014/files#diff-b3f07d9e77626753ea74b8a24a73ef0f82bc0a9d537617976b8ad34415f13ac0

The as prop listed in the docs, in the Storybook examples, and even in the unit tests, but I don't think other components were using it at that point.

The component was later incorporated into TreeGrid as part of #22373

children: { control: { type: null } },
},
parameters: {
actions: { argTypesRegex: '^on.*' },
Copy link
Member Author

Choose a reason for hiding this comment

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

Note that this won't fire actions for onExpandRow until we add a specific story that allows it to happen. I'm not going to do that in this PR because it is somewhat non-trivial.

Copy link
Contributor

Choose a reason for hiding this comment

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

What is the specific config that we need to replicate? Is it worth adding it to the onExpandRow prop docs?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think a good example would need to implement a simple version of a file browser where you can expand folder rows. Most of the functionality isn't baked into the component so we'd need to manage it ourselves (toggling visibility, state, styling, etc). We can write a better description for onExpandRow once we better understand what it entails.

Comment on lines +61 to +62
as?: React.ComponentType< RovingTabIndexItemPassThruProps >;
[ key: string ]: any;
Copy link
Member Author

Choose a reason for hiding this comment

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

Honestly, in terms of TypeScript I think things could be a lot simpler if we didn't allow an as prop, and didn't allow pass-through of arbitrary props. All the same things would be possible with just a children render prop and no arbitrary pass-through props. We might want to revisit this API if these loose types cause more trouble than it's worth.

Copy link
Contributor

Choose a reason for hiding this comment

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

Absolutely, let's keep this in mind

const meta: ComponentMeta< typeof TreeGrid > = {
title: 'Components (Experimental)/TreeGrid',
component: TreeGrid,
subcomponents: { TreeGridRow, TreeGridCell },
Copy link
Member Author

Choose a reason for hiding this comment

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

I am hesitant to add TreeGridItem to the subcomponents table because:

  • It wasn't even documented in the main readme.
  • It seems quite low level, and I'm not sure if the few usages in the Gutenberg app are even warranted in the first place 🤔
  • The docgen refuses to generate anything, probably because the types are too loose. (It needs to accept any prop, as they are passed through to arbitrary children/as.)

Copy link
Contributor

Choose a reason for hiding this comment

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

The only reason why I'd add it is to "manifest" its existence in the TreeGrid family — ie., if you use TreeGrid, you should TreeGridItem too (since it enabled the roving tab index functionality)

Copy link
Member Author

@mirka mirka Feb 1, 2023

Choose a reason for hiding this comment

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

if you use TreeGrid, you should TreeGridItem too (since it enabled the roving tab index functionality)

I think the original intent was for people to use TreeGridCell (which is TreeGridItem wrapped in a <td> tag). Using TreeGridItem without the gridcell wrapper is an invitation for semantic issues. There are two instances in the Gutenberg app where a raw TreeGridItem is used, and I have a feeling these are both problematic. If I understand the treegrid spec correctly, there should not be multiple focusable elements in a gridcell.

Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense. Let's keep it out of the docs, and probably prepare a follow-up to see if we can fix those TreeGridItem usages and convert them to TreeGridCell

@mirka mirka requested review from ciampo and flootr January 30, 2023 16:39
@mirka mirka marked this pull request as ready for review January 30, 2023 16:39
@mirka mirka requested a review from ajitbohra as a code owner January 30, 2023 16:39
Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

Great work here!

I noticed that there a few mentions in the component's docs about the fact that the component internally renders a table / td / tr — do you think we should keep those references, even if they expose the internal DOM structure of the component?

Also, we're missing a CHANGELOG entry 🗒️

packages/components/src/tree-grid/README.md Outdated Show resolved Hide resolved
if ( ! focusablesInRow || ! focusablesInRow.length ) {
return;
}
} ) as FocusableElement[];
Copy link
Contributor

@ciampo ciampo Feb 1, 2023

Choose a reason for hiding this comment

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

Why not use HTMLElement directly instead of FocusableElement?

Or at least, could we Pick< HTMLElement, 'focus' > ?

@@ -65,7 +60,9 @@ function TreeGrid(

if (
hasModifierKeyPressed ||
! [ UP, DOWN, LEFT, RIGHT, HOME, END ].includes( keyCode )
! ( [ UP, DOWN, LEFT, RIGHT, HOME, END ] as number[] ).includes(
Copy link
Contributor

Choose a reason for hiding this comment

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

🤷

packages/components/src/tree-grid/index.tsx Show resolved Hide resolved
Comment on lines +27 to +30
// TODO: The original implementation simply used `ref.current` here, assuming
// that a forwarded ref would always be an object, which is not necessarily true.
// This workaround maintains the original runtime behavior in a type-safe way,
// but should be revisited.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice comment.

I guess the better way here could be to check if typeof ref === 'function' (i.e. a callback ref) and then act accordingly. Definitely a task for a follow-up, and not this PR.

Comment on lines +61 to +62
as?: React.ComponentType< RovingTabIndexItemPassThruProps >;
[ key: string ]: any;
Copy link
Contributor

Choose a reason for hiding this comment

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

Absolutely, let's keep this in mind

packages/components/src/tree-grid/types.ts Show resolved Hide resolved
packages/components/src/tree-grid/types.ts Outdated Show resolved Hide resolved
packages/components/src/tree-grid/types.ts Outdated Show resolved Hide resolved
children: { control: { type: null } },
},
parameters: {
actions: { argTypesRegex: '^on.*' },
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the specific config that we need to replicate? Is it worth adding it to the onExpandRow prop docs?

@ciampo
Copy link
Contributor

ciampo commented Feb 1, 2023

Another quick note — the "Move up" / "Move down" buttons in the Storybook example don't currently do anything when clicked — should we have them at least print something to console?

@mirka mirka requested a review from ellatrix as a code owner February 1, 2023 18:24
@mirka
Copy link
Member Author

mirka commented Feb 1, 2023

I noticed that there a few mentions in the component's docs about the fact that the component internally renders a table / td / tr — do you think we should keep those references, even if they expose the internal DOM structure of the component?

Yes, I think those semantics are an essential part of the component, and thus part of the non-breaking contract. Otherwise it would just be the roving tabindex behavior.

Also, we're missing a CHANGELOG entry 🗒️

🙈

the "Move up" / "Move down" buttons in the Storybook example don't currently do anything when clicked — should we have them at least print something to console?

I agree they're confusing. I swapped them out with text fields so they look less actionable. Wdyt? cd66379

TreeGrid example story with text fields instead of non-responsive buttons

@mirka mirka requested a review from ciampo February 1, 2023 19:13
Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

#47516 (comment)

I think this looks better and less confusing, thank you!


Since there are a lot of open convos that are not actionable for this PR, here's a quick recap for our future selves:

Needs addressing in this PR:

  • Element to HTMLElement (convo)

To be addressed separately from this PRs: (low-priority)

  • adding a specific Storybook example to highlight how to use the onExpandRow callback (convo)
  • consider removing the as prop (convo, convo)
  • see if we can clean remove all usages of TreeGridItem and replace them with TreeGridCell (convo)
  • Make the ref check in RovingTabIndexItem support callback refs too (convo)

@mirka
Copy link
Member Author

mirka commented Feb 2, 2023

  • Element to HTMLElement (convo)

Addressed in d30ea0b (That was easy! 😄)

@mirka mirka requested a review from ciampo February 2, 2023 18:20
Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

LGTM 🚀

@mirka mirka merged commit 464426a into trunk Feb 3, 2023
@mirka mirka deleted the ts-treegrid branch February 3, 2023 12:32
@github-actions github-actions bot added this to the Gutenberg 15.2 milestone Feb 3, 2023
@DaisyOlsen DaisyOlsen added the [Type] Code Quality Issues or PRs that relate to code quality label Feb 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] Code Quality Issues or PRs that relate to code quality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants