Repository navigation
[#91727] Add Load more pattern to Workspace Workflows approval list - #94052
MonilBhavsar merged 9 commits into
Conversation
…91727) Render approval workflows in batches of WORKFLOW_APPROVALS_INITIAL_BATCH (5) with a "Load more" card that reveals the next batch and shows the remaining count (capped at 5). Search bypasses pagination and shows all matches. The card matches the Figma spec: bordered row with whole-card row-hover, a small CircularArrowBackwards icon (12px) + "Load X more" label in textSupporting, 8px radius to match the other workflow cards. Adds the workflowsPage.loadMoreWorkflows string to all locales and a UI test covering the batch, reveal, hide, and search-bypass behaviors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#91727) Per product decision, the "Load more" button reveals every remaining workflow at once (with the full remaining count in the label) instead of paging 5 at a time. Updates the UI test to match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use queryByRole(button, /load .* more/i) instead of the exact-count label so the absence checks fail if a load-more card appears with any count. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Hey, I noticed you changed If you want to automatically generate translations for other locales, an Expensify employee will have to:
Alternatively, if you are an external contributor, you can run the translation script locally with your own OpenAI API key. To learn more, try running: npx ts-node ./scripts/generateTranslations.ts --helpTypically, you'd want to translate only what you changed by running |
|
@dannymcclain @ikevin127 One of you needs to 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] |
|
@codex review |
|
@dannymcclain @abzokhattab One of you needs to 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] |
| hoverStyle={styles.hoveredComponentBG} | ||
| style={[styles.border, shouldUseNarrowLayout ? styles.ph3 : styles.ph4, styles.pv3, styles.mt6, styles.mbn3, styles.alignItemsCenter, styles.justifyContentCenter]} | ||
| > | ||
| <View style={[styles.flexRow, styles.alignItemsCenter, styles.justifyContentCenter, {minHeight: variables.componentSizeSmall}]}> |
There was a problem hiding this comment.
❌ UI-3 (docs)
This style array passes an inline object literal {minHeight: variables.componentSizeSmall}. Per STYLING.md, inline style object literals are not allowed — they create a new object on every render (breaking memoization) and duplicate values that belong in the style system. minHeight here is a static value derived from variables, so it belongs in the shared styles/StyleUtils.
Replace the inline object with a named style (or a StyleUtils helper). For example, add a minHeightComponentSizeSmall (or equivalent) entry to styles and use it:
<View style={[styles.flexRow, styles.alignItemsCenter, styles.justifyContentCenter, styles.minHeightComponentSizeSmall]}>Reviewed at: 1caab34 | Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.
| extraSmall | ||
| additionalStyles={styles.mr1} | ||
| /> | ||
| <Text style={[styles.buttonSmallText, {color: theme.textSupporting}]}>{label}</Text> |
There was a problem hiding this comment.
❌ UI-3 (docs)
This style array passes an inline object literal {color: theme.textSupporting}. Per STYLING.md, inline style objects are not allowed — they allocate a new object every render and bypass the shared style system. An equivalent already exists: the styles.textSupporting named style (and StyleUtils.getTextColorStyle(...)).
Use the existing named style instead of the inline object:
<Text style={[styles.buttonSmallText, styles.textSupporting]}>{label}</Text>Reviewed at: 1caab34 | Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1caab342db
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| }, [filteredApprovalWorkflows.length, setWorkflowSearchInput]); | ||
|
|
||
| // Searching reveals every match, so pagination is bypassed while a query is active. Pressing "Load more" reveals all remaining workflows at once. | ||
| const isSearchingWorkflows = workflowSearchInput.length > 0; |
There was a problem hiding this comment.
Keep batching until a real workflow search is applied
In workspaces with many workflows, this treats any non-empty raw input as a search even though useSearchResults trims and debounces before filtering. A whitespace-only value (and the first 300ms after a real keystroke) leaves searchFilteredWorkflows unfiltered while displayedWorkflows switches to the full list, so all workflow cards render and the Load more affordance disappears before any actual search is active. Base this on a trimmed/applied query, or keep the batch limit until the filtered results reflect the query.
Useful? React with 👍 / 👎.
- Replace inline {minHeight} and {color} style objects with the named
styles.minHeightComponentSizeSmall and styles.textSupporting (UI-3).
- Trim the workflow search input before bypassing pagination so a
whitespace-only query doesn't drop the Load more affordance while the
debounced filter hasn't applied.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@ikevin127 was assigned first, can you review please |
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reviewer Checklist
Screenshots/VideosiOS: NativeSimulator.Screen.Recording.-.iPhone.17.Pro.Max.-.2026-06-19.at.13.48.29.movMacOS: Chrome / SafariScreen.Recording.2026-06-19.at.13.41.46.mov |
…shrink Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Synced :) |
|
🚧 @mountiny has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
ikevin127
left a comment
There was a problem hiding this comment.
🟢 LGTM - Thanks for taking time to apply the suggested changes!
|
@Expensify/design should take a look at the new adhoc build to approve the design, example:
|
|
Do we have any updated videos we can review? |
|
@shawnborton Here are the ones from the review checklist, nothing changed UI wise since I posted these: iOS: NativeSimulator.Screen.Recording.-.iPhone.17.Pro.Max.-.2026-06-19.at.13.48.29.movMacOS: Chrome / SafariScreen.Recording.2026-06-19.at.13.41.46.mov
|
|
Thanks! I think those look good to me. |
joekaufmanexpensify
left a comment
There was a problem hiding this comment.
Good for product 👍
Single call site always passed CircularArrowBackwards; load it inside the component instead of threading it through a prop. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9595d00
|
🚧 MonilBhavsar has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
✋ 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 staging by https://github.com/MonilBhavsar in version: 9.4.19-1 🚀
Bundle Size Analysis (Sentry): |
|
🤖 Help site review — no changes required. I reviewed the changes in this PR against the help site articles under Why: This PR is a purely UI-level change. It adds a Load more progressive-disclosure pattern to the Approvals list on Workspace → Workflows — rendering the first 5 workflow cards initially, then revealing the rest on tap. There are no changes to:
The two relevant articles — Add Approvals and Workspace Workflows — describe how to enable and configure approval workflows. Neither documents the number of cards rendered or the list's display/pagination behavior, and the Load more control is self-explanatory in the UI. There is nothing in these articles that becomes inaccurate as a result of this change, so no draft docs PR was created. @elirangoshen — since no docs changes are required, there is no linked help site PR to review. If you believe this change does warrant a help site update, let me know and I'll draft one. |
|
🚀 Deployed to production by https://github.com/blimpich in version: 9.4.19-5 🚀
|
Explanation of Change
Adds a Load more progressive-disclosure pattern to the Approvals list on Workspace → Workflows (
WorkspaceWorkflowsPage). Workspaces with many custom approval workflows previously rendered every rich workflow card at once (member pills, approver chain, limits), causing a slow/janky initial render and burying the Add approval workflow button under heavy scrolling.What changed:
CONST.WORKFLOW_APPROVALS_INITIAL_BATCH(5) workflow cards.WorkflowsLoadMoreCardmatches the approved Figma spec: a bordered row (8px radius, same as the other workflow cards) where the whole card is the tap target and gets therow-hoverstate, with a 12pxCircularArrowBackwardsicon + "Load X more" label intextSupporting.workflowsPage.loadMoreWorkflowscopy to all locales (English string verbatim from Figma; other locales generated).tests/ui/WorkspaceWorkflowsLoadMoreTest.tsx) covering the initial batch, the button gate (>5), reveal-all on press, and the search-bypass behavior.No API or data-layer changes — workflow data is already client-side (derived from
policy.employeeListviaWorkflowUtils.convertPolicyEmployeesToApprovalWorkflows); this is purely UI pagination.Fixed Issues
$ #91727
PROPOSAL:
Tests
Offline tests
Workflow data is fully client-side, so the pattern behaves identically offline.
QA Steps
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)Avatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari