-
Notifications
You must be signed in to change notification settings - Fork 3.2k
[Due for payment 2025-04-23] [$500] Update Datepicker UX #52621
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
Comments
Job added to Upwork: https://www.upwork.com/jobs/~021857439292509917630 |
Triggered auto assignment to Contributor-plus team member for initial proposal review - @thesahindia ( |
@JmillsExpensify any opinion on which project makes the most sense for this? I was thinking |
Hi @dannymcclain I can't see the image and video attached. Can you reupload it, please? |
ProposalPlease re-state the problem that we are trying to solve in this issue.Update Datepicker UX What is the root cause of that problem?Feature Request What changes do you think we should make in order to solve the problem?We will:
|
@Pholenk Just re-uploaded! Hopefully that worked. Those are pretty important to be able to see 😂 |
Edited by proposal-police: This proposal was edited at 2024-11-16 08:52:21 UTC. ProposalPlease re-state the problem that we are trying to solve in this issue.What is the root cause of that problem?
What changes do you think we should make in order to solve the problem?
function DatePicker(
{
containerStyles,
defaultValue,
disabled,
errorText,
inputID,
label,
maxDate = setYear(new Date(), CONST.CALENDAR_PICKER.MAX_YEAR),
minDate = setYear(new Date(), CONST.CALENDAR_PICKER.MIN_YEAR),
onInputChange,
onTouched,
placeholder,
value,
shouldSaveDraft = false,
formID,
}: DatePickerProps,
ref: ForwardedRef<BaseTextInputRef>,
) {
const styles = useThemeStyles();
const {translate} = useLocalize();
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const [selectedDate, setSelectedDate] = useState(value || defaultValue || undefined);
const {shouldUseNarrowLayout} = useResponsiveLayout();
useEffect(() => {
// Value is provided to input via props and onChange never fires. We have to save draft manually.
if (shouldSaveDraft && !!formID) {
FormActions.setDraftValues(formID, {[inputID]: selectedDate});
}
if (selectedDate === value || !value) {
return;
}
setSelectedDate(value);
}, [formID, inputID, selectedDate, shouldSaveDraft, value]);
+ const show = useRef<() => void>();
+ const onSelected = (newValue: string) => {
+ onTouched?.();
+ onInputChange?.(newValue);
+ setSelectedDate(newValue);
+ hideTooltipRef.current?.();
+ ref?.current?.blur();
+ };
+ const hideTooltipRef = useRef<() => void>();
+ const [containerInputWidth, setContainerInputWidth] = useState();
+ const renderTooltipContent = useCallback(() => {
+ return (
+ <View
+ style={[styles.datePickerPopover, styles.border, {width: containerInputWidth, pointerEvents: 'auto', zIndex: +10000}]}
+ collapsable={false}
+ >
+ <CalendarPicker
+ minDate={minDate}
+ maxDate={maxDate}
+ value={selectedDate}
+ onSelected={onSelected}
+ />
+ </View>
+ );
+ }, [containerInputWidth, minDate, maxDate, selectedDate, onSelected]);
return (
+ <View style={styles.datePickerRoot}>
+ <GenericTooltip
+ shouldUseOverlay
+ wrapperStyle={{backgroundColor: 'transparent'}}
+ renderTooltipContent={renderTooltipContent}
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ anchorAlignment={{horizontal: 'center', vertical: 'top'}}
+ >
+ {({showTooltip, hideTooltip, updateTargetBounds}) => {
+ hideTooltipRef.current = hideTooltip;
+ return (
+ <View
+ onLayout={(e: LayoutChangeEventWithTarget) => {
+ // e.target is specific to native, use e.nativeEvent.target on web instead
+ const target = e.target || e.nativeEvent.target;
+ show.current = () => measureTooltipCoordinate(target, updateTargetBounds, showTooltip);
+ }}
+ style={[shouldUseNarrowLayout ? styles.flex2 : {}]}
+ >
+ <TextInput
+ disableKeyboard
+ onLayout={(e) => {
+ setContainerInputWidth(e.nativeEvent.layout.width);
+ }}
+ ref={ref}
+ inputID={inputID}
+ forceActiveLabel
+ icon={Expensicons.Calendar}
+ label={label}
+ accessibilityLabel={label}
+ role={CONST.ROLE.PRESENTATION}
+ value={selectedDate}
+ placeholder={placeholder ?? translate('common.dateFormat')}
+ errorText={errorText}
+ containerStyles={containerStyles}
+ disabled={disabled}
+ onFocus={() => show?.current?.()}
+ onBlur={() => hideTooltip()}
+ />
+ </View>
+ );
+ }}
+ </GenericTooltip>
+ </View>
+ );
} Explains: I am using
It will make sure the input is not blurred when we click on any button in the date picker.
<InputWrapper ref={inputCallbackRef} />
What alternative solutions did you explore? (Optional)ResultScreen.Recording.2024-11-27.at.17.28.40.mov |
Edited by proposal-police: This proposal was edited at 2024-11-21 19:23:22 UTC. ProposalPlease re-state the problem that we are trying to solve in this issue.Update Datepicker UX What is the root cause of that problem?UX enhancement What changes do you think we should make in order to solve the problem?
to this line App/src/components/DatePicker/index.tsx Line 74 in 4bb19d7
+ datePickerRoot: {
- position: 'relative',
- zIndex: 99,
+ width: '100%',
+ },
+ datePickerPopoverShow: {
+ display: 'flex',
+ },
+
+ datePickerPopoverHide: {
+ display: 'none',
+ },
- <View style={styles.datePickerRoot}>
- <View style={[shouldUseNarrowLayout ? styles.flex2 : {}, styles.pointerEventsNone]}>
+ <View style={[styles.flex0, styles.datePickerRoot, containerSize]}>
+ <View style={[shouldUseNarrowLayout ? styles.flex2 : {}]}>
<TextInput
- ref={ref}
+ ref={localRef}
inputID={inputID}
forceActiveLabel
icon={Expensicons.Calendar}
label={label}
accessibilityLabel={label}
role={CONST.ROLE.PRESENTATION}
value={selectedDate}
placeholder={placeholder ?? translate('common.dateFormat')}
errorText={errorText}
containerStyles={containerStyles}
textInputContainerStyles={[styles.borderColorFocus]}
- inputStyle={[styles.pointerEventsNone]}
disabled={disabled}
- readOnly
+ readOnly={false}
+ disableKeyboard
+ onFocus={toggleFocus}
+ onBlur={toggleFocus}
+ onLayout={onLayoutHandle}
/>
</View>
<View
- style={[styles.datePickerPopover, styles.border]}
+ style={[styles.datePickerPopover, styles.border, popoverDisplayStyle, popoverPosition]}
collapsable={false}
>
<CalendarPicker
minDate={minDate}
maxDate={maxDate}
value={selectedDate}
onSelected={onSelected}
/>
</View>
</View> ResultMobilescreencast-Genymotion-2024-11-21_23.54.13.555.mp4Websimplescreenrecorder-2024-11-22_02.14.18.mp4What alternative solutions did you explore? (Optional)Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job. |
@dannymcclain, @thesahindia Whoops! This issue is 2 days overdue. Let's get this updated quick! |
@thesahindia are you the official proposal reviewer for this one? |
Yeah, I am assigned as the C+. |
Thanks for the proposals everyone! Could you guys please share the end results? |
I've updated my proposal to add the video of the change result. cc: @thesahindia |
📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸 |
Not overdue. I think proposals are still being reviewed. |
@dannymcclain, @thesahindia Eep! 4 days overdue now. Issues have feelings too... |
|
The solution for this issue has been 🚀 deployed to production 🚀 in version 9.1.28-15-staging and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue: If no regressions arise, payment will be issued on 2025-04-23. 🎊 For reference, here are some details about the assignees on this issue:
|
BugZero Checklist: The PR adding this new feature has been merged! The following checklist (instructions) will need to be completed before the issue can be closed:
|
Triggered auto assignment to @trjExpensify ( |
Reassigning to handle payment as I'm heading OOO. Thanks for your help @trjExpensify! |
👋 @shubham1206agra can we get the checklist here please, and confirm the number of regressions? Sounds like just the 1 here, as the other here was observed in the PR for a follow-up. |
@trjExpensify The number of regression is 0 since this bug is repro on other inputs too #60243 (comment) |
@trjExpensify Read this line |
The offending PR was marked because we only focused on DatePicker at that time. |
Yeah, that line reads to me "this bug only appeared because of the offending PR". |
I think that when implementing |
Hm, but the ![]() Whereas with the DatePicker field it's displayed when not focused, which could be incorrect in itself? CC: @Expensify/design ![]() |
With input fields that is focused by default, the X will be shown without user interactions.
I've misused the word "focusing" here, what I meant was "user press/click to focus on the field" |
Ah right, that makes way more sense. To rephrase:
|
Since this is a new feature. So, only tests are require.d Test Case 1: Manual Date Selection and Clear Functionality
Test Case 2: Auto-Opening Date Picker in Settings Flow
Since there's only one actionable field (the date input) on these screens, the DatePicker should open automatically. The date picker should be automatically opened on the next screen:
|
Modifying this one. Typo in step 3, and step 5 is unclear you need to select the
|
Payment summary as follows:
Offer sent. |
@trjExpensify Offer accepted |
Paid, closing! |
Uh oh!
There was an error while loading. Please reload this page.
Problem
Currently our datepicker inputs always show the calendar popover, and this leads to a pretty cumbersome interface in places like the search filters where we have both a before and after date input.
Solution
Coming from this thread, let’s update our datepicker so that the calendar popover only appears when the input is focused.
CleanShot.2024-11-15.at.08.49.24.mp4
Notes:
Figma file
cc @Expensify/design
Upwork Automation - Do Not Edit
The text was updated successfully, but these errors were encountered: