prefactor: generalize filterable index layout and components - #13768
prefactor: generalize filterable index layout and components#13768ericwindmill wants to merge 9 commits into
Conversation
Extract generic two-column filterable index layout styles and sidebar/search components from learning resources into reusable filterable_index.dart and _filterable-index.scss.
There was a problem hiding this comment.
Code Review
This pull request refactors the filterable index pages by extracting shared layout, sidebar, and search group components and styles into reusable Dart components (FiltersSidebar, FilterSearchGroup) and a shared SASS stylesheet (_filterable-index.scss), successfully reducing code duplication. The feedback highlights a critical issue in filterable_index.dart where event.target is unsafely cast to web.Element? using the 'as' operator, which can lead to a runtime TypeError. It is recommended to use a safe type check (is web.Element) instead.
| onClick: (event) { | ||
| final target = event.target as web.Element?; | ||
| if (target?.closest(_sidebarSelector) == null && | ||
| target?.closest('.show-filters-button') == null) { | ||
| _toggle?.checked = false; | ||
| } | ||
| }, |
There was a problem hiding this comment.
Casting event.target directly to web.Element? using as is unsafe and can throw a TypeError at runtime. In the DOM, event.target can be a Document, Window, or other non-element nodes (for example, if the user clicks on a scrollbar or outside the window). To prevent runtime crashes, use a safe type check (is web.Element) before calling element-specific methods like closest.
onClick: (event) {
final target = event.target;
final element = target is web.Element ? target : null;
if (element?.closest(_sidebarSelector) == null &&
element?.closest('.show-filters-button') == null) {
_toggle?.checked = false;
}
},There was a problem hiding this comment.
Is this not exactly the same?
There was a problem hiding this comment.
The underlying of the comment is sort of right, but its solution isn't accurate since is also doesn't work for web types. Instead use the isA method. Something like this:
onClick: (event) {
final target = event.target;
if (target == null || !target.isA<web.Element>()) return;
final element = target as web.Element;
if (element.closest(_sidebarSelector) == null &&
element.closest('.show-filters-button') == null) {
_toggle?.checked = false;
}
},|
Staged preview of the updated docs.flutter.dev site (updated for commit c932533): https://flutter-docs-prod--docs-pr13768-refactor-filterable-in-fnqqj8yi.web.app |
|
Staged preview of the updated flutter.dev site (updated for commit c932533): https://flutter-dev-230821--www-pr13768-refactor-filterable-in-6oidcs4i.web.app |
parlough
left a comment
There was a problem hiding this comment.
Thanks for extracting this out @ericwindmill! Mostly looks good to me.
Should the learning resources index be updated to use the new FilterSearchGroup?
| onClick: (event) { | ||
| final target = event.target as web.Element?; | ||
| if (target?.closest(_sidebarSelector) == null && | ||
| target?.closest('.show-filters-button') == null) { | ||
| _toggle?.checked = false; | ||
| } | ||
| }, |
There was a problem hiding this comment.
The underlying of the comment is sort of right, but its solution isn't accurate since is also doesn't work for web types. Instead use the isA method. Something like this:
onClick: (event) {
final target = event.target;
if (target == null || !target.isA<web.Element>()) return;
final element = target as web.Element;
if (element.closest(_sidebarSelector) == null &&
element.closest('.show-filters-button') == null) {
_toggle?.checked = false;
}
},…or-filterable-index
Co-authored-by: Parker Lougheed <parlough@gmail.com>
…r/website into refactor-filterable-index
…or-filterable-index
Description of what this PR is changing or adding, and why:
Extract generic two-column filterable index layout styles and sidebar/search components from learning resources index into reusable filterable_index.dart and _filterable-index.scss.
This change anticipates new content for FlutterBench, where I'm adding a CUJ index #13691