Skip to content

Comments

YPE-1204: Fix verse error states + display reference#165

Open
jaredhightower-youversion wants to merge 2 commits intomainfrom
jh/YPE-1204-verse-not-loading-error-state
Open

YPE-1204: Fix verse error states + display reference#165
jaredhightower-youversion wants to merge 2 commits intomainfrom
jh/YPE-1204-verse-not-loading-error-state

Conversation

@jaredhightower-youversion
Copy link
Collaborator

Summary

Problem

When using passage?.reference directly in BibleCard, the reference header showed nothing while the API was loading or if the request failed. Users saw a blank space where the reference (e.g. "JOHN 3:16 NIV") should be.

The error state in BibleTextView also displayed a generic "We have run into an error..." message styled as Bible text, which was confusing and didn't match design specs.

Solution

Core (@youversion/platform-core)

  • Added formatUsfmForDisplay utility that converts raw USFM strings (e.g. "JHN.3.16") into human-readable references (e.g. "JOHN 3:16")
  • Supports book+chapter+verse, chapter-only, and book-only formats
  • Exported UsfmBookCode and UsfmReference types for type-safe USFM handling with IDE autocomplete
  • Added unit tests covering all format variations

UI (@youversion/platform-react-ui)

  • BibleCard: Uses displayReference fallback pattern — shows server reference when available, falls back to client-formatted USFM during loading/error so the header is always visible
  • BibleTextView: Replaced generic error string with a dedicated VerseUnavailableMessage component featuring an ExclamationCircle icon matching the Figma design
  • Added ExclamationCircle icon component

How it works

// Before: nothing shown during loading or error
{passage?.reference ? <h2>{passage.reference}</h2> : null}

// After: always shows a reference
const displayReference =
  passage?.reference ?? (reference ? formatUsfmForDisplay(reference) : null);
{displayReference ? <h2>{displayReference}</h2> : null}

@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.

@changeset-bot
Copy link

changeset-bot bot commented Feb 21, 2026

⚠️ No Changeset found

Latest commit: 980d393

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 21, 2026

Greptile Summary

Improved user experience by ensuring Bible references are always visible and error states are clear and accessible.

Core changes:

  • Added formatUsfmForDisplay utility in @youversion/platform-core to convert USFM codes (e.g., "JHN.3.16") to human-readable format ("JOHN 3:16")
  • Includes comprehensive book name mappings for the Protestant canon with proper TypeScript types
  • Unit tests cover all format variations (book+chapter+verse, chapter-only, book-only, verse ranges)

UI improvements:

  • BibleCard now shows a formatted reference during loading/error states instead of blank space
  • BibleTextView displays a properly styled error component with icon instead of confusing fake Bible text
  • New VerseUnavailableMessage component with accessibility attributes (role="alert", aria-live="polite")
  • Added ExclamationCircle icon following established component patterns

Confidence Score: 5/5

  • This PR is safe to merge with no issues found
  • Clean implementation with comprehensive test coverage, proper TypeScript types, follows project conventions, maintains package boundaries (core → ui), includes accessibility improvements, and solves the stated UX problems without introducing risks
  • No files require special attention

Important Files Changed

Filename Overview
packages/core/src/utils/reference.ts Added formatUsfmForDisplay utility with comprehensive USFM book mapping and proper type safety
packages/core/src/tests/reference.test.ts Comprehensive test coverage for all USFM format variations including edge cases
packages/ui/src/components/bible-card.tsx Implemented fallback pattern using formatUsfmForDisplay to ensure reference is always visible during loading/error states
packages/ui/src/components/verse.tsx Replaced generic error HTML with dedicated VerseUnavailableMessage component with proper accessibility attributes

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[BibleCard Component] --> B{passage?.reference available?}
    B -->|Yes| C[Display server reference]
    B -->|No| D{reference prop exists?}
    D -->|Yes| E[formatUsfmForDisplay reference]
    D -->|No| F[Display nothing]
    E --> G[Show formatted USFM]
    C --> H[Render header with reference]
    G --> H
    
    I[BibleTextView Component] --> J{API State?}
    J -->|Loading| K[Show Loading...]
    J -->|Error| L[VerseUnavailableMessage]
    J -->|Success| M[Render Bible HTML]
    L --> N[ExclamationCircle Icon + Error Text]
    
    O[formatUsfmForDisplay] --> P[Split USFM by dots]
    P --> Q{Has chapter & verse?}
    Q -->|Yes| R[Format: BOOK C:V]
    Q -->|No| S{Has chapter only?}
    S -->|Yes| T[Format: BOOK C]
    S -->|No| U[Format: BOOK]
Loading

Last reviewed commit: 980d393

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.

6 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@cameronapak
Copy link
Collaborator

CleanShot 2026-02-23 at 10 31 50@2x

Looks beautiful.

@cameronapak
Copy link
Collaborator

Still reviewing but I like what I see

Copy link
Collaborator

Choose a reason for hiding this comment

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

task: @jaredhightower-youversion util is really cool, and at the same time I think we do not need it 😔.

It appears its existence was created to solve the issue of the BibleCard not showing the reference when loading the Bible reference and text. It makes sense to want to have something there so that when the data loads, then new text doesn't just appear out of thin air, causing the component to have some layout shifting.

I think it's better in this case to consider one of two options:

  1. Use a Skeleton component while the Bible reference text is loading
  2. Or, use a Loading spinner while the Bible reference text is loading

Copy link
Collaborator Author

@jaredhightower-youversion jaredhightower-youversion Feb 23, 2026

Choose a reason for hiding this comment

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

question: If we use a skeleton component or a loading spinner and the network request fails, we wouldn't display a reference, right? Or is the intended behavior to keep the skeleton or spinner visible for reference when the verse is in a failed state?

The original intention for this util was to still display the reference even when the verse enters a failed state. This was also in the designs Tim provided. I guess another question is, do we already have another way to handle this within the SDK?

https://www.figma.com/design/os4RfK9yYqpms9FIIDhs12/YVP---Reader-SDK-Designs-v1?node-id=3419-11299&t=1htJ0ZfLF3BxvdV0-0

With Util

Screenshot 2026-02-23 at 11 17 15 AM

Without Util

Screenshot 2026-02-23 at 11 26 45 AM
    {passage?.reference ? (
          <h2 className="yv:font-bold yv:tracking-widest yv:text-xs yv:uppercase yv:text-foreground">
            {passage.reference} {version?.localized_abbreviation}
          </h2>
        ) : null}

Copy link
Collaborator

Choose a reason for hiding this comment

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

Great question, man. Sorry for the delay.

The error state of the readable reference is a real concern. Tim's designs clearly show a Bible reference there, but...

I should've been more clear. My comment was specifically about the loading state, not the error state

I think we're actually dealing with two separate problems:

  1. Loading state: what to show while the API request is in-flight
  2. Error state: what to show when the request fails entirely

For loading, I'd still lean toward a skeleton or spinner rather than the util, since the formatted USFM util returns English-only text and won't scale as we support more languages in our copy (soon)

For the error state, I looked at how the Swift SDK handles this. They use structured reference data (BibleReference with separate bookUSFM, chapter, verseStart, verseEnd) and get localized book names from the API via BibleVersion.displayTitle(for:), so there is no hardcoded English mapping for Bible reference. But the more important/intriguing thing is, their error state also doesn't show a reference if the version data failed to load. So it's the same gap on both platforms

That communicates to me the right fix isn't a client-side English book name map, but rather a design decision that needs to be processed with Tim Watson

What do you think about scoping this PR to the loading spinner while the API is in-flight + the verse unavailbale copy & icon, and we can then split the error-state reference display into its own ticket? And, let's say we get an error on the verse loading in the BibleCard, then you can render an empty div to prevent layout shifting. That way your work isn't blocked

Thoughts, @jaredhightower-youversion?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't mind removing the util, I just wanted to make sure that we're building to the design specs. Also, most of the work for the error state was done in this PR. Did you want me to remove that work and focus only on the loading-state rendering, or should we keep the changes for the error state in the PR (see ticket details here)?

With everything mentioned above, a clear next step action item would be as follows:

  • Seek clarification from Tim Watson regarding the error state for references when a verse is in a failed state.
  • Remove the reference uitl.
  • Prevent layout shift for failed verse.
  • Create a follow-up ticket for the loading state if we decide to keep error state changes in this PR.

@cameronapak, let me know what you think about this.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thank you for processing. I think the error state is the main thing. So everything else feels secondary. Would you agree?

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