-
Notifications
You must be signed in to change notification settings - Fork 1.7k
timeseries: replace matInput with reusable FilterInputComponent #4938
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
Conversation
.tb-text-input { | ||
-webkit-appearance: none; | ||
box-sizing: content-box; | ||
font: inherit; | ||
border: none; | ||
outline: none; | ||
padding: 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of creating a CSS based components, just create an Angular widget.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a widget wrapper around <input>
seems to add unnecessary boilerplate, imo. Every attribute like autocomplete
or event binding like (input)
now requires extra @input's and @output's on this new widget. Also, every module that uses it must now import another NgModule.
What do we gain from a TBTextInputWidget, from this extra boilerplate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it has very consistent UX that we can supply with it, I think it is very well worth it. Kind of like mat-input; for me, I gain almost nothing by using it yet for the consistent UX, we use it.
CSS based widgetization is creating a new pattern unnecessarily.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switched to the custom widget approach, PTAL
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your willingness to compromise.
It mostly LGTM and the comments are for clarifications and they are not blockers.
One thing though: I do notice that the tests are missing. I understand that the component is quite trivial (mostly a visual component). Was the omission an oversight or an intentional one?
tensorboard/webapp/testing/dom.ts
Outdated
@@ -126,9 +126,16 @@ export function sendKey<T>( | |||
el.setSelectionRange(startingCursorIndex, startingCursorIndex); | |||
} | |||
|
|||
// Use to override default options on programmatic events to be closer to | |||
// user-initiated events, which bubble and cancel. | |||
const baseEventOptions = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool. Would you be able to spend a little bit of time to maybe find the TypeScript HTML typing for the event options? Since it is already checked when you pass it as the second argument to Event constructor, I guess it is okay as is, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. And good idea, cause I actually misspelled "cancelable" :)
styles: [ | ||
` | ||
:host { | ||
display: flex; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just wondering, is there a reason why this element has to be a non-inline element?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consumers of <tb-filter-input>
can still style it as display: inline-flex
from the outside. The 'flex' part is here to make the <input>
full height.
@ViewChild(MatAutocompleteTrigger) | ||
autocompleteTrigger!: MatAutocompleteTrigger; | ||
|
||
getAutocompleteTrigger(): MatAutocompleteTrigger { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider just exposing closeAutocomplete
unless the trigger has other APIs that must be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After some consideration, I think "hide on Enter" really applies to all filter inputs, and have moved it into the widget. This lets us avoid exposing matAutocompleteTrigger
entirely, since consumers should probably never have to worry about opening and closing the panel manually.
In the future, I think it probably makes sense to move the "invalid error icon" into a filter input widget as well. I've held off on that in this PR though.
@Component({ | ||
selector: 'tb-filter-input', | ||
template: ` | ||
<input |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that the two applications both have the <mat-icon svgIcon="search_24px">
. Would it maybe make sense to include the icon since it is literally for filters?
It would be close (in its contract) to this (on older safari): https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/search
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review!
I understand that the component is quite trivial (mostly a visual component). Was the omission an oversight or an intentional one?
In the previous commit, I was thinking it wasn't too valuable to test that this component properly passes props to 1 template element. However, writing the test ended up catching missed things, and I think checking that autocomplete overlays fire made it worth adding a test.
tensorboard/webapp/testing/dom.ts
Outdated
@@ -126,9 +126,16 @@ export function sendKey<T>( | |||
el.setSelectionRange(startingCursorIndex, startingCursorIndex); | |||
} | |||
|
|||
// Use to override default options on programmatic events to be closer to | |||
// user-initiated events, which bubble and cancel. | |||
const baseEventOptions = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. And good idea, cause I actually misspelled "cancelable" :)
styles: [ | ||
` | ||
:host { | ||
display: flex; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consumers of <tb-filter-input>
can still style it as display: inline-flex
from the outside. The 'flex' part is here to make the <input>
full height.
@ViewChild(MatAutocompleteTrigger) | ||
autocompleteTrigger!: MatAutocompleteTrigger; | ||
|
||
getAutocompleteTrigger(): MatAutocompleteTrigger { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After some consideration, I think "hide on Enter" really applies to all filter inputs, and have moved it into the widget. This lets us avoid exposing matAutocompleteTrigger
entirely, since consumers should probably never have to worry about opening and closing the panel manually.
In the future, I think it probably makes sense to move the "invalid error icon" into a filter input widget as well. I've held off on that in this PR though.
@Component({ | ||
selector: 'tb-filter-input', | ||
template: ` | ||
<input |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
// Convert typing to object. Sadly, because keyCode is deprecated, it is not | ||
// typed properly. | ||
const keyboardEventArg = {key, keyCode} as {}; | ||
const keyboardEventArg = {...baseEventOptions, key, keyCode} as {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, as {}
might have made you miss that typo.
The sync broke in #4938 because of property renaming-related errors. This change also fixes a minor lint warning. Test sync cl/374274713
Recently [1], we introduced a `<tb-input-filter>` component that replaced the runs selector's filter input field in Time Series. That change included a regression where the input's click target was no longer full width. This change restores the full width click target. Manually ran `bazel tensorboard:dev` and checked that clicking in the space to the right of the placeholder text still focuses the run selector's input field in the Time Series dashboard. [1] #4938
The Time Series tag filter input and run selector were using Angular's
matInput
whose styles are only included when anothermat-form-field
has been rendered on the page before [1].
To make the filter input styles deterministic, drop the
matInput
directiveand replace it with a custom, styled widget for filter inputs.
[1] angular/components#21871