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

[EuiSuperDatePicker] Allow setting absolute dates without Enter key #7732

Merged
merged 14 commits into from
May 8, 2024

Conversation

sakurai-youhei
Copy link
Member

@sakurai-youhei sakurai-youhei commented May 3, 2024

Summary

This PR adds the following two implicit date parsing triggers to EuiSuperDatePicker's absolute tabs, which allow users to set absolute dates without hitting the Enter key.

  • On focus lost from the text input - i.e., blur event on it.
  • Right before the absolute tab component's disposal - i.e., at componentWillUnmount().

Steps to set 01:05:00.000 to 01:05:15.000:

  1. Click start date.
  2. Click Absolute.
  3. Click 01:00.
  4. Select 0 to replace by mouse.
  5. Type in 5.
  6. No need to hit Enter.
  7. Select input text.
  8. Copy it by Ctrl+C.
  9. Click end date.
  10. Click Absolute.
  11. Select input text.
  12. Paste it by Ctrl-V.
  13. Select 00 to replace.
  14. Type in 15.
  15. No need to hit Enter.
  16. Click Update
    EuiSuperDatePicker

Closes #7731

QA

  1. Go to https://eui.elastic.co/pr_7732/#/templates/super-date-picker
  2. Open Absolute tab.
  3. Click Update.
  4. Open Absolute tab again.
  5. Change the date text.
  6. Click Refresh without hitting the Enter key.
  • The date should be updated if the input date is compliant with the date format.
  • The date shouldn't be updated if the input date is not compliant with the date format.
  • When leaving the Absolute tab, even if the input date is not compliant with the date format, users shouldn't be notified about it.

General checklist

  • Browser QA
    • Checked in both light and dark modes
    • Checked in mobile
    • Checked in Chrome, Safari, Edge, and Firefox
    • Checked for accessibility including keyboard-only and screenreader modes
  • Docs site QA
  • Code quality checklist
  • Release checklist
    • A changelog entry exists and is marked appropriately.
    • If applicable, added the breaking change issue label (and filled out the breaking change checklist)
  • Designer checklist
    • Updated the Figma library counterpart

@sakurai-youhei sakurai-youhei marked this pull request as ready for review May 5, 2024 14:06
@sakurai-youhei sakurai-youhei requested a review from a team as a code owner May 5, 2024 14:06
@cee-chen
Copy link
Member

cee-chen commented May 6, 2024

To be totally honest with you, I don't really love adding this complex of logic (setState overrides, a delay variable) for what is a fairly opinionated UX problem.

Instead of trying to validate onBlur, how about we conditionally add a Submit or Validate button to the right of the input that only appears whenever the user has manually changed/typed into the input? This would allow us to validate on very deliberate and conscious user decision, instead of us trying to guess when they want to submit vs cancel a date. It also still allows users like you to keep your hands on your mouse.

Bad mockup example:

@cee-chen
Copy link
Member

cee-chen commented May 6, 2024

CC @MichaelMarcialis in as well for thoughts (see above comment with bad mockup), since he's working on the next generation of EuiSuperDatePicker and I'd be curious to hear what UX he'd prefer for users manually entering dates for validation

@MichaelMarcialis
Copy link
Contributor

Thanks for the ping, @cee-chen! From a UX perspective, I agree with @sakurai-youhei that forcing the user to hit the enter key (or even click a separate button) to parse the date feels strange. I'm actually ashamed to admit it but, despite all my years here, I actually didn't know this was the behavior when manually typing in an absolute date. In EuiSuperDatePickers current form, I would expect that date parsing to occur on blur of the input, thus allowing me to immediately hit the "Update" button afterward and get my expected output. Unfortunately, if the user actually attempts to do that today, they don't get the expected outcome, as their last manually entered date will not have been parsed and would instead revert to its last parsed date.

That said, while I do agree with the changes, we are currently in the process of designing an updated and (hopefully) improved EuiSuperDatePicker component. In these updated designs, we do expect the parsing and auto-formatting of dates to occur on blur, but the inputs for the dates are no longer housed in a popover and are also being combined into a single input that encompasses both start and end dates. As such, it may make sense to hold off on merging this but keep the concept in mind during the design and development process for the component update. Thoughts?

@cee-chen
Copy link
Member

cee-chen commented May 6, 2024

I'm actually ashamed to admit it but, despite all my years here, I actually didn't know this was the behavior when manually typing in an absolute date.

It's a relatively recent change since we started accepting more timestamp formats in that input. See #7331 (comment) for more context and back-and-forth we've already had around timestamp validation.

In EuiSuperDatePickers current form, I would expect that date parsing to occur on blur of the input

my 2c, for what it's worth: I don't love the idea of submission happening on "blur" instead of a deliberate choice to click a very explicit button and say "yes, this is definitely the date timestamp I want to try and parse". The UX on blur feels ambiguous - what if I gave up halfway or wanted to cancel my changes? There's literally no way to avoid doing so without causing an error state (or potentially parsing an incorrect date) the second I click away from the half-complete input.

Michael, can you clarify what (if anything) you don't like about the explicit validation/submission button mock I made up above? It would only appear on user type/input change and if there are any changes to try and format/validate - it would not appear all the time.

As such, it may make sense to hold off on merging this but keep the concept in mind during the design and development process for the component update.

I'd like us to figure this out now instead of later as this will help us with the upcoming new component. I'm looking for us to find a good compromise both in terms of UX and code complexity.

@sakurai-youhei
Copy link
Member Author

@cee-chen @MichaelMarcialis Thank you for your comments. As a user, I would prefer as few clicks and types as possible, but I understand and totally agree that the code falls to the dark side. I had to increase the code complexity for the following minor perfection.

When leaving the Absolute tab, even if the input date is not compliant with the date format, users shouldn't be notified about it.

If it is reasonable to compromise on this, although the ambitious validation still remains, the code can be much simplified like THIS. The price of simplification is that when you leave the absolute tab with an invalid text input, the format error momentarily lights on red.

EuiSuperDatePicker-simplified

I hope some improvement will happen in some timeframe if the pain points make sense to some amount of users. Otherwise (i.e., in case only I feel them), I will train myself to be more conscious of triggering the date validation. ;-) Thanks again for your review. I appreciate your time and attention to this PR.

@cee-chen
Copy link
Member

cee-chen commented May 7, 2024

@MichaelMarcialis synced at our weekly team meeting about this and have agreed on an interim solution for now:

  • Adding a conditionally rendered EuiButtonIcon with the check icon to the right of the input with an accessible title/label
  • Remove the Press the enter key to parse as a date helptext, since the new button essentially serves as that behavior, but still allow pressing both the enter key and clicking the button to set an absolute date

@sakurai-youhei I'll go ahead and take over this PR if no objections, since this a pretty large deviation from your proposed solution and I don't want to make you do the work twice!

- using a `form` element allows us to take advantage of *both* native form enter key and click behavior OOTB without an extra listeners 🎉

- getting rid of the `Press enter` helptext also lets us simplify our logic and flex CSS 🎉

- fyi, slightly less granular commit history than my norm, apologies all
@cee-chen
Copy link
Member

cee-chen commented May 7, 2024

Screencap of the new UI with both click and button keypress behavior:

superdatepicker_absolute

I think this is a super nice UX improvement and a huge code cleanup and I'm very excited for it! What do you all think?

@sakurai-youhei
Copy link
Member Author

@cee-chen Thank you very much. I literally said, "Aha !!" when I played the new UI. I am amazed at how effectively the button catches my eye and encourages me to proceed naturally to the date parsing. I learned a lot - again :) - by seeing how the answer can be led out of the box.

Back to my findings, here is one point from my perspective - horizontal grouping. The added button looks separate from the text field(, which may be done so intentionally, though), so I wonder how you find grouping it horizontally to the text field, like the pictures below. This is all from me. 👍

Vertical grouping (now) Horizontal grouping
image image
diff of code
diff --git a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx
index 2d6a5e356..3f1a2bac1 100644
--- a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx
+++ b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx
@@ -198,33 +198,35 @@ export class EuiAbsoluteTab extends Component<
                     : undefined
                 }
               >
-                <EuiFieldText
-                  compressed
-                  isInvalid={isTextInvalid}
-                  value={textInputValue}
-                  onChange={this.handleTextChange}
-                  onPaste={(event) => {
-                    this.parseUserDateInput(
-                      event.clipboardData.getData('text')
-                    );
-                  }}
-                  data-test-subj="superDatePickerAbsoluteDateInput"
-                  prepend={<EuiFormLabel>{labelPrefix}</EuiFormLabel>}
-                />
+                <EuiFlexGroup responsive={false} gutterSize="s">
+                  <EuiFieldText
+                    compressed
+                    isInvalid={isTextInvalid}
+                    value={textInputValue}
+                    onChange={this.handleTextChange}
+                    onPaste={(event) => {
+                      this.parseUserDateInput(
+                        event.clipboardData.getData('text')
+                      );
+                    }}
+                    data-test-subj="superDatePickerAbsoluteDateInput"
+                    prepend={<EuiFormLabel>{labelPrefix}</EuiFormLabel>}
+                  />
+                  {hasUnparsedText && (
+                    <EuiButtonIcon
+                      type="submit"
+                      className="euiSuperDatePicker__absoluteDateFormSubmit"
+                      size="s"
+                      display="base"
+                      color={isTextInvalid ? 'danger' : 'primary'}
+                      iconType="check"
+                      aria-label={dateFormatButtonLabel}
+                      title={dateFormatButtonLabel}
+                      data-test-subj="parseAbsoluteDateFormat"
+                    />
+                  )}
+                </EuiFlexGroup>
               </EuiFormRow>
-              {hasUnparsedText && (
-                <EuiButtonIcon
-                  type="submit"
-                  className="euiSuperDatePicker__absoluteDateFormSubmit"
-                  size="s"
-                  display="base"
-                  color={isTextInvalid ? 'danger' : 'primary'}
-                  iconType="check"
-                  aria-label={dateFormatButtonLabel}
-                  title={dateFormatButtonLabel}
-                  data-test-subj="parseAbsoluteDateFormat"
-                />
-              )}
             </EuiFlexGroup>
           )}
         </EuiI18n>

- have to use CSS trickery for this as the EuiFormRow component needs a refactor before it can take flex children :|
@cee-chen
Copy link
Member

cee-chen commented May 8, 2024

Back to my findings, here is one point from my perspective - horizontal grouping. The added button looks separate from the text field(, which may be done so intentionally, though), so I wonder how you find grouping it horizontally to the text field, like the pictures below.

Nice catch, I think it makes sense to do! Sadly however we can't use an EuiFlexGroup as a child of EuiFormRow. Under the hood, EuiFormRow does a bunch of cloneElements on direct children, so it really wants its children to be the actual input element and nothing else. It's a tech debt item for me to replace this limiting API with React context instead (see #2493 (comment) for more info)

However, the good news is that we can still achieve the effect in your screenshots with some CSS hackery! 7253811

@MichaelMarcialis, do you mind giving this PR a final design review pass? If it looks good to you with no change requests, I'll go ahead and merge it.

Copy link
Contributor

@MichaelMarcialis MichaelMarcialis left a comment

Choose a reason for hiding this comment

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

Thanks for putting this together, @cee-chen! It looks like a good compromise. I left two small comments below, but nothing worth holding you up over. Assuming you're able to address them, I'll approve now.

Comment on lines +195 to +199
helpText={
hasUnparsedText && !isTextInvalid
? dateFormatError
: undefined
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make sense to show the help text, regardless if the date is parsed or unparsed? It could be useful for users to see the accepted formats prior to making any changes.

Copy link
Member

Choose a reason for hiding this comment

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

I think I have a slight preference to not showing it until needed? TBH, I do wonder how many people even use the absolute input, and it's kind of a lot of information to show 🙈

Co-authored-by: Michael Marcialis <michael.l.marcialis@gmail.com>
@kibanamachine
Copy link

Preview staging links for this PR:

@elasticmachine
Copy link
Collaborator

💚 Build Succeeded

History

@cee-chen cee-chen enabled auto-merge (squash) May 8, 2024 18:24
Copy link
Member

@cee-chen cee-chen left a comment

Choose a reason for hiding this comment

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

Thanks again for your terrific improvements on this component Youhei, as always it's so incredibly appreciated!

@cee-chen cee-chen merged commit 954ca22 into elastic:main May 8, 2024
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[EuiSuperDatePicker] Allow setting absolute dates without Enter key
5 participants