Skip to content

YPE-1143: Mitigate BibleCard UI page shifting#177

Merged
cameronapak merged 17 commits intomainfrom
cp/YPE-1143-react-sdk-bible-card-formerly-bible-widget-view-fix-fouc
Mar 2, 2026
Merged

YPE-1143: Mitigate BibleCard UI page shifting#177
cameronapak merged 17 commits intomainfrom
cp/YPE-1143-react-sdk-bible-card-formerly-bible-widget-view-fix-fouc

Conversation

@cameronapak
Copy link
Collaborator

@cameronapak cameronapak commented Feb 27, 2026

More info can be found in https://lifechurch.atlassian.net/browse/YPE-1143

Plz watch video demo first (1min)

Supporting SMOL video

CleanShot.2026-02-27.at.11.31.53.mp4

Replace static loading text with a spinning loader icon when book title
is not yet available. This improves the user experience by providing a
more visually clear indication that content is being fetched.
made it possible for the Bible text view to animate in height so that
changes aren't jarring in the Bible card whenever it loads fully.
Add a pulse animation to the BibleTextView when content is loading. This
improves
the user experience by providing visual feedback during data fetching.
Refactors the `AnimatedHeight` component to use `offsetHeight` for more
accurate height calculations. Also updates the Tailwind transition
timing function to `ease-out` for a smoother animation.
@changeset-bot
Copy link

changeset-bot bot commented Feb 27, 2026

🦋 Changeset detected

Latest commit: f345af0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@youversion/platform-react-ui Patch
@youversion/platform-react-hooks Patch
@youversion/platform-core Patch
nextjs Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

cameronapak and others added 2 commits February 27, 2026 11:37
…er loading state

- Add role="status" and aria-label="Loading" to LoaderIcon for accessibility
- Update bible-card and verse tests to use getByRole queries instead of CSS class selectors
- Fix verse story to properly await loading assertion

Amp-Thread-ID: https://ampcode.com/threads/T-019ca029-6aeb-73f2-970f-b06ef26ca45f
Co-authored-by: Amp <amp@ampcode.com>
@cameronapak cameronapak marked this pull request as ready for review February 27, 2026 17:38
@chatgpt-codex-connector
Copy link

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@cameronapak
Copy link
Collaborator Author

@greptileai, please review this PR

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 27, 2026

Greptile Summary

This PR successfully mitigates UI page shifting in BibleCard by implementing smooth height transitions and improved loading states. The solution introduces a new AnimatedHeight component that uses ResizeObserver for automatic height tracking with CSS transitions, and a useDelayedLoading hook that prevents spinner flashing by delaying its appearance for 250ms during refetches.

Key improvements:

  • New AnimatedHeight component with ResizeObserver and motion-reduce support
  • Delayed loading spinner (250ms) prevents UI flashing during quick refetches
  • Old content remains visible during refetch instead of showing spinner
  • LoaderIcon now has proper accessibility attributes (role="status", aria-label)
  • Comprehensive test coverage for delayed spinner and refetch behavior
  • Consistent loading UX across BibleCard and BibleReader components

Technical implementation:

  • useDelayedLoading hook properly cleans up timers to prevent memory leaks
  • AnimatedHeight properly cleans up ResizeObserver on unmount
  • Loading states correctly differentiate between initial load (show spinner) vs refetch (show old content + small spinner)
  • Previous error handling issue from review thread has been fixed (now only checks currentError)

All changes follow project conventions, respect package boundaries, maintain unified versioning, and include proper test coverage.

Confidence Score: 5/5

  • This PR is safe to merge with no issues found
  • The implementation is clean, well-tested, and follows all project conventions. Timer cleanup and ResizeObserver cleanup are properly handled. The error handling issue from previous reviews has been resolved. All accessibility requirements are met with proper ARIA attributes. The changeset correctly includes all three packages following unified versioning rules.
  • No files require special attention

Important Files Changed

Filename Overview
packages/ui/src/components/animated-height.tsx New component for smooth height transitions using ResizeObserver and CSS transitions with motion-reduce support
packages/ui/src/components/bible-card.tsx Added delayed loading spinner (250ms) and AnimatedHeight wrapper to prevent UI flashing during refetch
packages/ui/src/components/verse.tsx Updated to show old content during refetch instead of spinner, with pulse animation and disabled interactions
packages/ui/src/components/icons/loader.tsx Added role="status" and aria-label="Loading" for accessibility

Last reviewed commit: fa2afe8

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

10 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Adjusted the `BibleCard` component's styling to remove an unnecessary
gap between the header and the main content, and added a bottom margin
to the header section for better visual separation.
@cameronapak cameronapak self-assigned this Feb 27, 2026
Only render `VerseUnavailableMessage` if `currentError` exists.
Previously, it would also render if `fetchedError` existed, leading to
an incorrect UI state.
@cameronapak
Copy link
Collaborator Author

@greptileai, based on your latest review, please go and update your initial review. ty ty ty

@cameronapak
Copy link
Collaborator Author

@mic-mart would you be willing to review this PR if no one else can get to it?

Copy link
Collaborator

@mic-mart mic-mart left a comment

Choose a reason for hiding this comment

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

Overall

Nice work — this is a solid, well-tested approach to mitigating layout shift. The patterns here (stale-while-revalidate display, delayed spinner, ResizeObserver-based height animation) are all industry-standard best practices. Performance looks good: ResizeObserver avoids layout thrashing, animate-pulse is CSS-only, and timer cleanup is correct. Accessibility is in good shape with role="status", aria-label, and motion-reduce:transition-none.

A few optional suggestions inline — all non-blocking nits.

mic-mart
mic-mart previously approved these changes Mar 2, 2026
- Initialize AnimatedHeight with 'auto' instead of 0 to prevent flash-from-zero on mount
- Add aria-busy attribute to verse wrapper during refetch for assistive tech
- Add aria-hidden to LoaderIcon inside version picker button to prevent duplicate announcements

Amp-Thread-ID: https://ampcode.com/threads/T-019cb0c7-af0a-7229-8a84-4345c6625fdc
Co-authored-by: Amp <amp@ampcode.com>
@cameronapak
Copy link
Collaborator Author

@mic-mart ready for re-review or for final review

Copy link
Collaborator

@mic-mart mic-mart left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks for nit-picking so quickly. :shipit:

@cameronapak cameronapak merged commit 325dff9 into main Mar 2, 2026
5 checks passed
@cameronapak cameronapak deleted the cp/YPE-1143-react-sdk-bible-card-formerly-bible-widget-view-fix-fouc branch March 2, 2026 23:45
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.

2 participants