-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Add DatePicker component #5509
Add DatePicker component #5509
Conversation
For example the DatePicker sets the value in a text field without using the keyboard - the value is picked from a picker
Added accent as it's used for the datepicker background Moved colors to colors.xml
4eeaef1
to
73fbf05
Compare
On desktop and web the browser populates a pattern and a datepicker icon
Noticed the native picker on web has the word "reset" And the behavior to return to the previous value instead of closing the picker
Pressing inside the field (e.g. not on the label) is not activated without this
@Expensify/design The color choices for the Android calendar picker (see last screen recording) don't feel on-brand. Thoughts? |
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.
src/components/ExpensiTextInput/baseExpensiTextInputPropTypes.js
Outdated
Show resolved
Hide resolved
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.
Overall this implementation seems good to me. Didn't do much testing though
src/components/DatePicker/index.js
Outdated
componentDidMount() { | ||
if (this.inputRef) { | ||
// Adds nice native datepicker on web/desktop. Not possible to set this through props | ||
this.inputRef.type = 'date'; |
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.
This feels like a hack/code smell to me, but I don't have a better suggestion atm. Seems like it works so we can go with it for now.
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.
Yep, it's hackish ⌨️ but allows us to reuse ExpensiTextInput
Other options are:
- don't set the type to "date" and not have the native picker for web/mWeb/desktop.
- use html elements (since we're on a web/desktop file) and return
<input type=date />
. But we'll have to refactor or re-code all the styles to matchExpensiTextInput
I did a quick search for other ways to pass this attribute to the native element and didn't find anything
If it makes sense to refine this in the future, we can swap a web specific library (like react-datepicker) and provide a uniform datepicker experience
We're using ExpensiInput which override some styles and render the input differently There's no dropdown arrow. When we focus the empty datepicker field it's only highlighted in blue. The user needs to tap again in order to see the native datepicker To avoid this confusion we're showing the datepicker immediately
3220f91
to
9db7aa9
Compare
# Conflicts: # src/pages/ReimbursementAccount/IdentityForm.js
On safari the datepicker would show a done and reset buttons We're also passing the locale to the datepicker, because we're partially localizing the modal ourselves it will be weird if the buttons are shown in one locale while the month names in another. RNDatepicker respects the locale only on iOS
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.
Added notes on the last changes
/** | ||
* Pops the datepicker up when we focus this field. This only works on mWeb | ||
* On mWeb the user needs to tap on the field again in order to bring the datepicker. But our current styles | ||
* don't make this very obvious. To avoid confusion we open the datepicker when the user focuses the field | ||
*/ | ||
showDatepicker() { | ||
if (this.inputRef) { | ||
this.inputRef.click(); | ||
} | ||
} |
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.
This was mainly added due to very bad UX on mWeb Android (Chrome).
Tapping on the field would first highlight it. The datepicker would appear if you tap on the input element but due to our styles (from ExpensiInput
the input wrapped in a <div>
) the target area is actually smaller
Before
Android.Emulator.-.Pixel_2_API_29_5554.2021-09-28.21-22-55.mp4
- it might not be obvious but the picker would appear only when we tap below the field label near the middle of the field. And only after we've focused the field...
After
Android.Emulator.-.Pixel_2_API_29_5554.2021-09-28.21-24-08.mp4
- The picker appears as soon as we tap the field (similar to how it works on Android native)
Tested the rest of the platforms and there aren't any issues
web/index.html
Outdated
input[type=date]::-webkit-calendar-picker-indicator { | ||
position: absolute; | ||
right: 12px; | ||
top: 16px; | ||
} |
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.
@deetergp regarding:
After merging latest If this error happens again, try this, stop the RN metro server and start it again like this:
|
Changes are ready for review |
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.
The styles are not getting applied in storybook because they were in web/index.html To avoid such problems let's move them to the datepicker that uses them Using a `.css` file is a special case here, because it's impossible to target pseudo-elements from js code (e.g. ::-webkit)
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.
.expensify-datepicker::-webkit-calendar-picker-indicator { | ||
position: absolute; | ||
right: 12px; | ||
top: 13px; | ||
} | ||
.expensify-datepicker::-webkit-date-and-time-value { | ||
text-align: left; | ||
} |
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.
Noticed these styles weren't getting applied in storybook so I moved them here - in a .css
file
Using a .css
file is a special case here, because it's impossible to target pseudo-elements from js code (e.g. ::-webkit)
It also keeps things together. It was a bit weird for me to have these defined in index.html
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.
Please add a code comment explaining this 😄
export default { | ||
title: 'Components/Datepicker', | ||
component: DatePicker, | ||
argTypes: { | ||
onChange: {action: 'date changed'}, | ||
}, | ||
args: { | ||
value: '', | ||
label: 'Select Date', | ||
placeholder: 'Date Placeholder', | ||
errorText: '', | ||
hasError: false, | ||
}, | ||
}; |
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.
Added a storybook sample as per: #5509 (comment)
cc @roryabraham
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.
Looks good—-thank you for the changes.
Datepicker.propTypes = datepickerPropTypes; | ||
Datepicker.defaultProps = defaultProps; | ||
|
||
export default withLocalize(Datepicker); |
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.
NAB but maybe useful to mention somewhere that iOS is the only platform where we have to manage localization ourselves, and on all others it's controlled by the OS
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'll open a separate request to put a note about this
We're localizing the "Reset" and "Done" button that we put on our own popup.
RNDatepicker
would be shown in the system locale. I'm passing the locale
to RNDatepicker
because it will be weird to have the "Done" and "Reset" buttons in one locale and the picker months in another - it can happen
On Android the buttons and the modal are handled by the system so they are always in the system locale
.expensify-datepicker::-webkit-calendar-picker-indicator { | ||
position: absolute; | ||
right: 12px; | ||
top: 13px; | ||
} | ||
.expensify-datepicker::-webkit-date-and-time-value { | ||
text-align: left; | ||
} |
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.
Please add a code comment explaining this 😄
I'm not explicitly approving because I don't have time to test atm, but I'm removing my request for changes. @deetergp feel free to move forward on this PR without me if you've tested and feel comfortable
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
🚀 Deployed to production by @chiragsalian in version: 1.1.4-0 🚀
|
Details
Adds a native datepicker per each platform
Fixed Issues
$ #5340
Tests
DatePicker
(Reimbursement Account Page)IdentityForm
: BeneficialOwner step, Requestor step,<input type=date />
. It supports both typing and popping a calendar pickerI've made sure dates are sent as strings in the format
YYYY-MM-DD
and inspected that the submit payload contains the valueQA Steps
Same as above
Tested On
Screenshots
Web
Chrome
Screen.Recording.2021-09-24.at.22.44.52.mov
Safari
Screen.Recording.2021-09-24.at.22.50.37.mov
Firefox
New.Expensify.Mozilla.Firefox.2021-09-24.23-06-15.mp4
Mobile Web
iOS (Safari)
Screen.Recording.2021-09-27.at.10.25.55.mov
Android (Chrome)
Android.Emulator.-.Pixel_2_API_29_5554.2021-09-24.23-09-18.mp4
Desktop
Screen Recording 2021-09-24 at 22.53.19
iOS
Screen.Recording.2021-09-24.at.23.29.57.mov
Android
Android.Emulator.-.Pixel_2_API_29_5554.2021-09-24.23-02-40.mp4