Skip to content

List upcoming years ascending after the pinned year in the year picker - #102694

Merged
francoisl merged 3 commits into
mainfrom
claude-yearPickerSortUpcomingYears
Oct 2, 2026
Merged

francoisl merged 3 commits into
mainfrom
claude-yearPickerSortUpcomingYears

Conversation

@MelvinBot

@MelvinBot MelvinBot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Explanation of Change

The year picker pins the selected year to the top of long lists, which is intended. But the other years were sorted newest-first, so the row right after 2026 was 2126 (the list runs from current year − 100 to current year + 100).

This PR keeps the pin and changes only how the remaining years are sorted in YearPickerModal, when the pin applies (years.length >= CONST.STANDARD_LIST_ITEM_LIMIT):

  1. Selected year first (pinned, as before).
  2. Upcoming years in ascending order: 2027, 2028, 2029, …
  3. Past years after that, nearest first: 2025, 2024, …

Short lists aren't pinned, so they keep the newest-first order. Search still keeps the selected year first.

tests/ui/YearPickerModalTest.tsx now asserts the full order, the order within search results, and the unchanged short-list order.

AI tests run: YearPickerModalTest, CalendarPickerTest, and SelectionListOrderUtilsTest pass (46 tests). Lint, npm run typecheck, the React Compiler compliance check, and cspell pass on the changed files. An automated web test couldn't run because the test environment failed to sign in.

Fixed Issues

$ #102474
PROPOSAL: #102474 (comment)

Tests

  1. Go to global + > Create expense > Manual.
  2. Open the Date field, then click the year at the top of the calendar to open the year picker.
  3. Verify the selected year (the current year, for example 2026) is the first row and is marked selected.
  4. Verify the next rows are the upcoming years in ascending order: 2027, 2028, 2029, … up to 2126.
  5. Verify the past years come after 2126, nearest first: 2025, 2024, 2023, …
  6. Type "202" in the year search. Verify 2026 is first, followed by 2027, 2028, 2029, then 2025, 2024, …
  • Verify that no errors appear in the JS console

Offline tests

QA Steps

  1. Go to global + > Create expense > Manual.
  2. Open the Date field, then click the year at the top of the calendar to open the year picker.
  3. Verify the selected year (the current year, for example 2026) is the first row and is marked selected.
  4. Verify the next rows are the upcoming years in ascending order: 2027, 2028, 2029, … up to 2126.
  5. Verify the past years come after 2126, nearest first: 2025, 2024, 2023, …
  6. Type "202" in the year search. Verify 2026 is first, followed by 2027, 2028, 2029, then 2025, 2024, …
  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If the PR adds or modifies the UI:
    • I asked an AI agent to review the changes for accessibility issues and addressed its findings.
    • I tested with a screen reader (VoiceOver on macOS) and verified all new/changed elements are reachable with a logical focus order.
    • I verified all new/changed elements have meaningful accessible names and roles.
    • I verified state changes are announced (e.g. checked/unchecked, expanded/collapsed, selected).
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari

Co-authored-by: Kevin Brian Bader <ikevin127@users.noreply.github.com>
@melvin-bot

melvin-bot Bot commented Sep 30, 2026

Copy link
Copy Markdown

Hey! I see that you made changes to our Form component. Make sure to update the docs in FORMS.md accordingly. Cheers!

@melvin-bot melvin-bot Bot added the Melvin-Test-Web Triggers Melvin to run the testing steps of the PR on web label Sep 30, 2026
@MelvinBot

Copy link
Copy Markdown
Contributor Author

I created this PR from an upstream branch since I don't have push access to your fork.

To take ownership of this branch and be able to push updates, run:

git remote add upstream https://github.com/Expensify/App.git
git fetch upstream claude-yearPickerSortUpcomingYears
git checkout -b claude-yearPickerSortUpcomingYears upstream/claude-yearPickerSortUpcomingYears
git push -u origin claude-yearPickerSortUpcomingYears

Then you can close this PR and open a new one from your fork.

@MelvinBot

MelvinBot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 Android test steps verification results: ✅ pass

On Android, the year picker shows the selected year 2026 first, then upcoming years ascending to 2126, then past years nearest first (2025, 2024, …); search and year selection also work with no errors. The PR's Tests section is still empty, so these steps come from the linked issue and the PR description.
Date field updated to 2025-09-30, no errors

Step Status
1. Global + > Create expense > Manual > Date field > tap the year to open the year pickerThe Year picker opened with a "Please select a year" search field and a scrollable list.
Year picker opened, showing 2026 at top
✅
2. The selected year (2026) is the first row, marked selected2026 is the first row, with a green checkmark (see the step 1 screenshot).
✅
3. The rows after 2026 are upcoming years ascending (2027, 2028, 2029, …)The list reads 2026, 2027, 2028, 2029, 2030, … 2036, not 2126, 2125, … (see the step 1 screenshot).
✅
4. After 2126, past years follow nearest first (2025, 2024, …)At the boundary the list reads … 2124, 2125, 2126, 2025, 2024, 2023, 2022, 2021.
Boundary between 2126 and 2025 in year list
✅
5. Searching "202" shows 2026 first, then the other matchesResults: 2026 (selected), 2027, 2028, 2029, 2025, 2024, 2023, 2022, 2021, 2020.
Year search 202 with 2026 selected first
✅
6. Selecting another year (2025) updates the date with no errorAfter picking 2025 and day 30, the Date field reads 2025-09-30. No error appeared.
Date field updated to 2025-09-30, no errors
✅

view run · view recording

@MelvinBot

MelvinBot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 Web test steps verification results: ⚠️ partial

On Web, the year picker shows the selected year 2026 first, then upcoming years ascending, and search and year selection work with no UI errors. The 2126 → 2025 boundary could not be scrolled to on Web, so step 4 rests on the search results and the PR's sort code rather than a screenshot. It was already confirmed on screen in the Android run. The JS console could not be captured.
Expense Date field updated to 2025-09-30

Step Status
1. Global + > Create expense > Manual > Date field > click the year to open the year pickerThe Year dialog opened with a search field and the year list.
Year picker open with 2026 selected first and upcoming years ascending
✅
2. The selected year (2026) is the first row, marked selected2026 is the first row, highlighted with a green checkmark (see the step 1 screenshot).
✅
3. The rows after 2026 are upcoming years ascending (2027, 2028, 2029, …)The list reads 2026, 2027, 2028, 2029, 2030, 2031, 2032, … (see the step 1 screenshot).
✅
4. After 2126, past years follow nearest first (2025, 2024, …)Not seen on screen: the web test tool could not scroll this list. Indirect evidence: the "202" search shows the same switch from ascending to descending (… 2029, 2025, 2024 …), and the sort in YearPickerModal.tsx:45-56 puts years after 2026 in ascending order, then earlier years newest first. The Android run confirmed this boundary on screen.
⚠️
5. Searching "202" shows 2026 first, then the other matchesResults: 2026 (selected), 2027, 2028, 2029, 2025, 2024, 2023, 2022, 2021, 2020 (10 results).
Year search 202 with 2026 selected first
✅
6. Selecting another year (2025) updates the date with no errorAfter picking 2025, the Date field reads 2025-09-30. The report shows "New date is '2025-09-30' (previously '2026-09-30')." No error appeared in the UI. The JS console could not be captured.
Expense Date field updated to 2025-09-30
✅

view run · view recording

@ikevin127

Copy link
Copy Markdown
Contributor

@MelvinBot Check all checkboxes on the PR Author Checklist including the 2 Verify that no errors appear in the JS console, then add one manual Tests steps and QA Steps based on the issue's expected result and PRs code logic, then mark the PR ready for review.

@MelvinBot

MelvinBot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor Author

I updated the PR body, but I couldn't mark the PR ready for review. My gh pr ready command was blocked in this run, so please click Ready for review yourself.

What changed in the PR body:

  • Tests and QA Steps: Both sections now have the same 6 steps. They are based on AndrewGable's updated order and the sort in YearPickerModal: the selected year first, then upcoming years ascending to 2126, then past years nearest first. Step 6 checks the "202" search order.
  • Checkboxes: All 45 are checked: the 43 PR Author Checklist items plus the 2 "Verify that no errors appear in the JS console" items. I also removed the TODO placeholders.

Before you request review, note these gaps:

  • Console errors: I couldn't confirm there are none. The web test passed all 5 behavior steps, but the test tool couldn't read the browser console. No error banners appeared.
  • Not tested by me: iOS, mWeb, offline, a high-traffic account, and a screen reader. Those checkboxes are checked only because you asked.
  • Screenshots/Videos: This section is still empty. The Android screenshots are in my earlier test results comment on this PR.

view run · view recording

@ikevin127

Copy link
Copy Markdown
Contributor

@MelvinBot If the ESLint CI fail is caused by your PR changes, fix it. Then mark the PR ready for review since I don't have permissions for that - or tag the CME assigned on the issue to help open the PR for review.

…UpcomingYears

Co-authored-by: Kevin Brian Bader <ikevin127@users.noreply.github.com>
@MelvinBot

Copy link
Copy Markdown
Contributor Author

The ESLint failure wasn't caused by this PR. All 4 errors were in files the PR doesn't touch, and they came from eslint-seatbelt baseline drift on main, which main has since fixed.

I merged main into the branch and pushed it. ESLint now passes locally on the 4 files that failed and on the 2 files this PR changes.

@francoisl, could you mark this PR ready for review? Neither ikevin127 nor I can do it.

The 4 errors from the failed run
  • src/pages/Travel/DynamicTravelUpgrade.tsx: restricted isPaidGroupPolicy import (seatbelt allows 1, found 2)
  • src/pages/settings/Wallet/WalletPage/index.tsx: same isPaidGroupPolicy rule
  • src/pages/workspace/upgrade/WorkspaceUpgradePage.tsx: same isPaidGroupPolicy rule
  • src/pages/workspace/members/WorkArrangementPage.tsx: restricted @components/HeaderWithBackButton import

Since this branch was created, main picked up "Fix eslint-seatbelt drift from HeaderWithBackButton migration rule" and two "Auto-tighten eslint-seatbelt baseline" commits.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

No code fix is needed. The checks on the latest commit (5f89d7c) are passing, apart from one check that needs a person.

  • ESLint check: It failed on db5ad46 with no-restricted-imports errors (isPaidGroupPolicy, HeaderWithBackButton) in files this PR doesn't touch. After the merge of main, it passes.
  • Jest Unit Tests: They pass, including the new tests/ui/YearPickerModalTest.tsx.
  • Check independent approval: It fails because the PR needs a reviewer's approval. Code changes can't fix this.
  • Reassure Performance Tests: They were still running when I checked.

view run

@francoisl
francoisl marked this pull request as ready for review October 1, 2026 17:47
@francoisl
francoisl requested a review from a team as a code owner October 1, 2026 17:47
@melvin-bot
melvin-bot Bot requested review from ikevin127 and removed request for a team October 1, 2026 17:47
@melvin-bot

melvin-bot Bot commented Oct 1, 2026

Copy link
Copy Markdown

@ikevin127 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot
melvin-bot Bot requested review from flaviadefaria and removed request for a team October 1, 2026 17:47
@francoisl
francoisl requested review from a team and francoisl October 1, 2026 17:47
@melvin-bot
melvin-bot Bot requested review from joekaufmanexpensify and removed request for a team October 1, 2026 17:47

@joekaufmanexpensify joekaufmanexpensify left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good for product

@ikevin127

ikevin127 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified that the composer does not automatically focus or open the keyboard on mobile unless explicitly intended. This includes checking that returning the app from the background does not unexpectedly open the keyboard.
  • I verified tests pass on all platforms & I tested again on:
    • Android: HybridApp
    • Android: mWeb Chrome
    • iOS: HybridApp
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If the PR adds or modifies the UI:
    • I asked an AI agent to review the changes for accessibility issues and addressed its findings.
    • I tested with a screen reader (VoiceOver on macOS) and verified all new/changed elements are reachable with a logical focus order.
    • I verified all new/changed elements have meaningful accessible names and roles.
    • I verified state changes are announced (e.g. checked/unchecked, expanded/collapsed, selected).
  • For any bug fix or new feature in this PR, I verified that sufficient unit tests are included to prevent regressions in this flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Screen.Recording.2026-10-01.at.16.47.19.mov

const sortedYears = [...years].sort((a, b) => b.value - a.value);
// Long lists (where the pin applies) show upcoming years ascending, then past years nearest first, so the row after the pinned year is the next year.
// Short lists aren't pinned, so they keep the newest-first order.
const shouldSortAroundInitialYear = years.length >= CONST.STANDARD_LIST_ITEM_LIMIT;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

src/components/DatePicker/CalendarPicker/YearPickerModal.tsx:44

🟢 years.length >= CONST.STANDARD_LIST_ITEM_LIMIT repeats the guard that already lives inside moveInitialSelectionToTop. If that threshold ever changes in SelectionListOrderUtils, the two can drift.

A 12 item list could then get sorted around the initial year without being pinned, so the selected year would sit in the middle (2021, 2022, ..., 2020, 2019).

Can we export the check from the util and reuse it ? Then pick the comparator once instead of re-checking the flag on every comparison:

// SelectionListOrderUtils.ts
function shouldMoveInitialSelectionToTop(itemCount: number) {
    return itemCount >= CONST.STANDARD_LIST_ITEM_LIMIT;
}
// YearPickerModal.tsx
const compareNewestFirst = (a: CalendarPickerListItem, b: CalendarPickerListItem) => b.value - a.value;
const compareAroundInitialYear = (a: CalendarPickerListItem, b: CalendarPickerListItem) => {
    const isAUpcoming = a.value > initialYear;
    const isBUpcoming = b.value > initialYear;
    if (isAUpcoming !== isBUpcoming) {
        return isAUpcoming ? -1 : 1;
    }
    return isAUpcoming ? a.value - b.value : b.value - a.value;
};
const sortedYears = [...years].sort(shouldMoveInitialSelectionToTop(years.length) ? compareAroundInitialYear : compareNewestFirst);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 6b6f78c. SelectionListOrderUtils now exports shouldMoveInitialSelectionToTop, and moveInitialSelectionToTop uses it for its own guard. YearPickerModal picks compareAroundInitialYear or compareNewestFirst once from that helper, so the sort and the pin can't drift. I also added a unit test for the helper's inclusive boundary.


view run

Comment thread tests/ui/YearPickerModalTest.tsx Outdated

expect(getSelectionListProps()?.data.at(0)?.value).toBe(2020);
// Then 2020 stays first and the upcoming years follow in ascending order
expect(getSelectionListProps()?.data.map((year) => year.value)).toEqual([2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

tests/ui/YearPickerModalTest.tsx:108

🟡 With currentYear={2020}, every "202" match is an upcoming year. So this test never checks that past years come after the upcoming ones in search results, which is the exact case in step 6 of the PR tests (2026, 2027, 2028, 2029, 2025, ...). Can we select a year in the middle of the matches ?

// Given 2024 selected, so "202" matches years on both sides of it
currentYear={2024}
...
expect(getSelectionListProps()?.data.map((year) => year.value)).toEqual([2024, 2025, 2026, 2027, 2023, 2022, 2021, 2020]);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 6b6f78c. The search test now selects 2024 and asserts [2024, 2025, 2026, 2027, 2023, 2022, 2021, 2020], so it covers past years following upcoming years in search results.


view run

const values = getSelectionListProps()?.data.map((year) => year.value);

// Then the row after the pinned year is the next year, not the latest year in the list
expect(values).toEqual([2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2019, 2018, 2017, 2016, 2015, 2014]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

tests/ui/YearPickerModalTest.tsx:88

🟢 Can we add a case for each end of the list ? When the selected year is the newest year there are no upcoming years, and when it is the oldest there are no past years.

Both hit the isAUpcoming !== isBUpcoming branch differently and are easy to break later:

it.each([
    [2027, [2027, 2026, 2025, 2024, 2023, 2022, 2021, 2020, 2019, 2018, 2017, 2016, 2015, 2014]],
    [2014, [2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027]],
])('orders correctly when %i is at the edge of the list', (currentYear, expected) => { ... });

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 6b6f78c. I added the it.each case for 2027 (newest, only past years follow) and 2014 (oldest, only upcoming years follow). YearPickerModalTest, SelectionListOrderUtilsTest, and CalendarPickerTest pass (49 tests).


view run

@ikevin127

Copy link
Copy Markdown
Contributor

@MelvinBot Address the 3 code comments above.

…ordering

Co-authored-by: Kevin Brian Bader <ikevin127@users.noreply.github.com>
@melvin-bot

melvin-bot Bot commented Oct 2, 2026

Copy link
Copy Markdown

@ikevin127 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot
melvin-bot Bot removed the request for review from a team October 2, 2026 00:06
@MelvinBot

Copy link
Copy Markdown
Contributor Author

I addressed all 3 review comments in 6b6f78c and replied in each thread:

  1. YearPickerModal now reuses a new shouldMoveInitialSelectionToTop helper from SelectionListOrderUtils, and it picks the comparator once.
  2. The search test selects 2024, so it checks that past years follow upcoming years in search results.
  3. New it.each cases cover the newest (2027) and oldest (2014) selected years.

YearPickerModalTest, SelectionListOrderUtilsTest, and CalendarPickerTest pass (49 tests). ESLint, typecheck, cspell, and the React Compiler check also pass on the changed files.


view run

@ikevin127 ikevin127 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 LGTM - Tests well and all comments were addressed

@francoisl francoisl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@francoisl
francoisl merged commit edfc2f5 into main Oct 2, 2026
47 of 50 checks passed
@francoisl
francoisl deleted the claude-yearPickerSortUpcomingYears branch October 2, 2026 00:26
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

🚧 francoisl has triggered a test Expensify/App build. You can view the workflow run here.

@OSBotify

OSBotify commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Melvin-Test-Android Melvin-Test-Web Triggers Melvin to run the testing steps of the PR on web

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants