YPE-2776 - Make it clear BibleReader is loading when changing chapters#258
Conversation
Fade the outgoing chapter text in place behind a sticky, viewport-centered spinner while the next chapter loads, instead of pulsing the stale text. Avoids the layout flash a bare spinner would cause and the confusing stale-but-active text. The opacity transition doubles as a fade-in for the incoming chapter. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: e0881e5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
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 |
| <div className="yv:sticky yv:top-1/2 yv:flex yv:-translate-y-1/2 yv:justify-center"> | ||
| <LoaderIcon | ||
| className="yv:size-8 yv:animate-spin yv:text-muted-foreground" |
There was a problem hiding this comment.
Sticky spinner invisible on long chapters
yv:top-1/2 resolves top: 50% against the sticky element's containing block — the absolute inset-0 overlay div — whose height equals the entire chapter text height. For any chapter taller than the viewport (e.g. Psalm 119, long Gospels), that threshold exceeds the viewport height, so position: sticky pins the spinner below the visible area immediately. Users see only the faded text with no visible loading indicator throughout the scroll.
yv:top-[50vh] fixes this — it resolves against the viewport height rather than the chapter height, keeping the spinner at the vertical midpoint of the visible area on chapters of any length.
| <div className="yv:sticky yv:top-1/2 yv:flex yv:-translate-y-1/2 yv:justify-center"> | |
| <LoaderIcon | |
| className="yv:size-8 yv:animate-spin yv:text-muted-foreground" | |
| <div className="yv:sticky yv:top-[50vh] yv:flex yv:-translate-y-1/2 yv:justify-center"> |
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/ui/src/components/verse.tsx
Line: 580-582
Comment:
**Sticky spinner invisible on long chapters**
`yv:top-1/2` resolves `top: 50%` against the sticky element's *containing block* — the `absolute inset-0` overlay div — whose height equals the entire chapter text height. For any chapter taller than the viewport (e.g. Psalm 119, long Gospels), that threshold exceeds the viewport height, so `position: sticky` pins the spinner below the visible area immediately. Users see only the faded text with no visible loading indicator throughout the scroll.
`yv:top-[50vh]` fixes this — it resolves against the viewport height rather than the chapter height, keeping the spinner at the vertical midpoint of the visible area on chapters of any length.
```suggestion
<div className="yv:sticky yv:top-[50vh] yv:flex yv:-translate-y-1/2 yv:justify-center">
```
How can I resolve this? If you propose a fix, please make it concise.
PLEASE WATCH VIDEO DEMO
Reworked the chapter-change loading state in
BibleTextView(packages/ui/src/components/verse.tsx). While the next chapter is fetching, the outgoing chapter's text now fades to 40% opacity in place behind a sticky, viewport-centered spinner, instead of pulsing the stale text. The opacity transition doubles as a fade-in for the incoming chapter.This avoids the two bad alternatives: a bare spinner (flashes the layout empty then back) and the previous pulsing stale text (reads as active/confusing while the heading already shows the new chapter).
Touched areas: stale-while-revalidate render path, loading overlay,
pointer-events/aria-busyplacement, updated refetch loading test selector, changeset.All 70 UI tests pass; typecheck and lint clean.
Completes YPE-2776
🤖 Generated with Claude Code
Greptile Summary
This PR replaces the
animate-pulsestale-text loading indicator inBibleTextViewwith a fade-to-40%-opacity overlay and a sticky viewport-centered spinner, avoiding both the confusing active-stale-text appearance and the flash-of-empty-content a bare spinner would cause.verse.tsx: The stale-while-revalidate render branch wraps the passage content in a transitioning opacity div (aria-busy,pointerEvents: none) and conditionally renders anabsolute inset-0overlay with a sticky spinner; the initial-load-with-no-content path is unchanged.verse.test.tsx: The pointer-events test selector is updated from[data-yv-sdk]to[aria-busy=\"true\"]to match the new DOM structure..changeset/\u2026: Patch changeset added for@youversion/platform-react-ui.Confidence Score: 3/5
The sticky spinner is invisible for any chapter taller than the viewport, defeating the overlay's main purpose on the chapters where it matters most.
The loading UX approach is well-structured, but
top-1/2resolves against the absolute overlay height (= full chapter text height) rather than the viewport. For long chapters like Psalm 119, this pins the spinner off-screen immediately, leaving users with only faded text and no visible loading indicator.packages/ui/src/components/verse.tsx — the sticky spinner positioning at line 580
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[BibleTextView render] --> B{currentLoading AND no passage?} B -- Yes --> C[Initial load spinner\nfull-screen centered] B -- No --> D{currentError?} D -- Yes --> E[Error message] D -- No --> F[Outer div data-yv-sdk relative] F --> G[Inner content div aria-busy transition-opacity] G --> H{currentLoading?} H -- Yes --> I[opacity-40 pointerEvents none] H -- No --> J[opacity-100 normal] F --> K{currentLoading?} K -- Yes --> L[Overlay div absolute inset-0 pointer-events-none] L --> M[Sticky spinner div sticky top-1/2] M --> N[LoaderIcon size-8 animate-spin] K -- No --> O[null no overlay]Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "YPE-2776 - feat(ui): clarify BibleReader..." | Re-trigger Greptile