Skip to content

YPE-2257 - Add Bible version picker composition APIs for later use in Expo DOM#228

Open
cameronapak wants to merge 3 commits intomainfrom
codex/version-picker-composition
Open

YPE-2257 - Add Bible version picker composition APIs for later use in Expo DOM#228
cameronapak wants to merge 3 commits intomainfrom
codex/version-picker-composition

Conversation

@cameronapak
Copy link
Copy Markdown
Collaborator

@cameronapak cameronapak commented May 6, 2026

https://lifechurch.atlassian.net/browse/YPE-2257

CleanShot.2026-05-06.at.13.43.54.mp4

Summary

Adds advanced composition surfaces for the Bible version picker so the React Native Expo SDK can reuse Web SDK picker content inside Expo DOM/native presentation.

Changes

  • Adds controlled language state to BibleVersionPicker.Root via languageId, defaultLanguageId, and onLanguageChange.
  • Adds BibleVersionPickerLanguageTrigger for reusable Web SDK language trigger UI.
  • Extracts BibleLanguagePickerContent as body-only language picker content for SDK/native sheet composition.
  • Adds open handling to picker content so pre-warmed DOM surfaces can clear transient search state on close.
  • Adds a minor changeset for the new UI composition APIs.
  • Expands picker tests for callback mode, controlled language state, close reset behavior, and standalone content.

Validation

  • pnpm --filter @youversion/platform-react-ui test -- bible-version-picker
  • pnpm --filter @youversion/platform-react-ui test -- bible-chapter-picker
  • pnpm --filter @youversion/platform-react-ui typecheck
  • pnpm --filter @youversion/platform-react-ui build
  • pre-commit lint-staged hook passed during commit

Greptile Summary

This PR adds composition surfaces for the Bible version picker so Expo DOM/native sheets can reuse the existing Web SDK picker UI. It introduces controlled language state, BibleVersionPickerLanguageTrigger, and BibleLanguagePickerContent as standalone exported components, and refactors Content to serve both popover and standalone scenarios via a runtime branch.

  • Controlled language state is wired through useControllableState on Root, with languageId, defaultLanguageId, and onLanguageChange props; onVersionPickerPress bypasses the Popover wrapper so Expo can open a native sheet instead.
  • BibleVersionPickerLanguageTrigger and BibleLanguagePickerContent are extracted from Content into individually exportable components, each reading shared state from context.
  • Content refactor adds an open prop for pre-warmed DOM reset and splits into popover vs. standalone render paths based on whether onVersionPickerPress, open, or onRequestClose are present.

Confidence Score: 5/5

Safe to merge; all changes are additive composition APIs with good test coverage, and the one visual regression is minor and easily patched.

The refactor is well-scoped: new exports are additive, the Root branching logic is straightforward, and controlled state is handled by the existing useControllableState primitive. The only concrete defect found — missing transition classes on the popover-mode animation wrappers — causes panels to snap rather than blend but has no effect on correctness or state management.

The animation wrapper divs inside the popover branch of Content in bible-version-picker.tsx are missing transition-all duration-300.

Important Files Changed

Filename Overview
packages/ui/src/components/bible-version-picker.tsx Extracts language trigger and language content into standalone exported components; adds controlled language state and onVersionPickerPress to Root; refactors Content into popover/standalone branches. Animation transition classes are missing from the popover-mode wrapper divs, causing snap instead of smooth blend.
packages/ui/src/components/bible-version-picker.test.tsx Adds thorough tests for onVersionPickerPress callback mode, controlled languageId, open-prop reset behavior, and standalone BibleLanguagePickerContent/BibleVersionPickerLanguageTrigger.
packages/ui/src/components/index.ts Exports the two new composition components and their prop types; no issues.
packages/ui/src/components/bible-version-picker.stories.tsx Wraps assertion in waitFor to handle async rendering and removes a spurious extra click; straightforward fix.
.changeset/extract-version-picker-content.md Minor changeset entry for the new composition APIs; correctly categorised as minor.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    Root["BibleVersionPicker.Root\n(versionId, languageId, onVersionPickerPress, ...)"]
    Root -->|onVersionPickerPress set| CtxOnly["Context.Provider\n(no Popover wrapper)"]
    Root -->|no onVersionPickerPress| PopoverWrap["Context.Provider\n+ Popover wrapper"]

    CtxOnly --> Trigger["BibleVersionPicker.Trigger\n→ calls onVersionPickerPress on click"]
    CtxOnly --> LangTrigger["BibleVersionPickerLanguageTrigger\n→ sets isLanguagesOpen via context"]
    CtxOnly --> StandaloneContent["BibleVersionPicker.Content\n(open, onRequestClose)\n→ standalone div"]
    CtxOnly --> LangContent["BibleLanguagePickerContent\n(open, onRequestClose)\n→ standalone div"]

    PopoverWrap --> PopoverTrigger["BibleVersionPicker.Trigger\n→ PopoverTrigger"]
    PopoverWrap --> PopoverContent["BibleVersionPicker.Content\n(no props)\n→ PopoverContent\n  ├─ Content (onRequestClose)\n  └─ LanguagePanel (onRequestClose)"]
Loading

Comments Outside Diff (1)

  1. packages/ui/src/components/bible-version-picker.tsx, line 853-870 (link)

    P2 BibleLanguagePickerContent does not reset its tab state when open transitions to false

    Content has a useEffect that calls setSearchQuery('') and setIsLanguagesOpen(false) when open flips to false, ensuring pre-warmed surfaces return to a clean state on close. BibleLanguagePickerContent accepts the same open prop but only writes it to a data-open attribute — it has no equivalent cleanup effect. In Expo pre-warmed DOM scenarios, a user who navigated to the "All" tab would see it still selected on reopen.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: packages/ui/src/components/bible-version-picker.tsx
    Line: 853-870
    
    Comment:
    **`BibleLanguagePickerContent` does not reset its tab state when `open` transitions to `false`**
    
    `Content` has a `useEffect` that calls `setSearchQuery('')` and `setIsLanguagesOpen(false)` when `open` flips to `false`, ensuring pre-warmed surfaces return to a clean state on close. `BibleLanguagePickerContent` accepts the same `open` prop but only writes it to a `data-open` attribute — it has no equivalent cleanup effect. In Expo pre-warmed DOM scenarios, a user who navigated to the "All" tab would see it still selected on reopen.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code Fix in Cursor

  2. packages/ui/src/components/bible-version-picker.tsx, line 674-681 (link)

    P2 Unused second grid column in standalone Content search bar

    The wrapper div uses grid-cols-[1fr_auto] with a gap, but only the <InputGroup> is rendered inside it — the auto column is always empty in standalone mode. The [1fr_auto] template collapses harmlessly but is dead CSS.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: packages/ui/src/components/bible-version-picker.tsx
    Line: 674-681
    
    Comment:
    **Unused second grid column in standalone `Content` search bar**
    
    The wrapper `div` uses `grid-cols-[1fr_auto]` with a gap, but only the `<InputGroup>` is rendered inside it — the `auto` column is always empty in standalone mode. The `[1fr_auto]` template collapses harmlessly but is dead CSS.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code Fix in Cursor

Fix All in Claude Code Fix All in Cursor

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/ui/src/components/bible-version-picker.tsx:563-578
The wrapper divs that apply the `opacity`/`blur`/`scale` animation classes have no `transition-all duration-300` of their own. The transition classes live on the inner `Content` div (the standalone return path), which is a different element from the one whose classes are actually changing — so CSS will not animate the transition and the version/language panels will snap instead of blend in popover mode. Adding the transition utilities directly to these wrappers restores the original smooth animation.

```suggestion
        <div
          className={`yv:h-full yv:min-h-0 yv:transition-all yv:duration-300 yv:rounded-2xl yv:origin-center ${
            isLanguagesOpen
              ? 'yv:opacity-0 yv:pointer-events-none yv:blur-sm yv:scale-95'
              : 'yv:opacity-100 yv:pointer-events-auto yv:blur-none yv:scale-100'
          }`}
        >
          <Content onRequestClose={() => setIsPopoverOpen(false)} />
        </div>
        <div
          className={`yv:h-full yv:absolute yv:inset-0 yv:transition-all yv:duration-300 yv:rounded-2xl yv:origin-center ${
            isLanguagesOpen
              ? 'yv:opacity-100 yv:pointer-events-auto yv:blur-none yv:scale-100'
              : 'yv:opacity-0 yv:pointer-events-none yv:blur-sm yv:scale-95'
          }`}
        >
```

Reviews (3): Last reviewed commit: "fix(ui): preserve language trigger defau..." | Re-trigger Greptile

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 6, 2026

🦋 Changeset detected

Latest commit: 6123478

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 Minor
vite-react Patch
@youversion/platform-core Minor
@youversion/platform-react-hooks Minor

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 cameronapak force-pushed the codex/version-picker-composition branch from 60aa5b3 to 736cee7 Compare May 6, 2026 18:42
@cameronapak cameronapak force-pushed the codex/version-picker-composition branch from 736cee7 to 56aac3e Compare May 6, 2026 18:51
@cameronapak cameronapak marked this pull request as ready for review May 6, 2026 18:56
Comment thread packages/ui/src/components/bible-version-picker.tsx
@cameronapak cameronapak changed the title [codex] Add Bible version picker composition APIs Add Bible version picker composition APIs for later use in Expo DOM May 6, 2026
@cameronapak cameronapak changed the title Add Bible version picker composition APIs for later use in Expo DOM YPE-2257 - Add Bible version picker composition APIs for later use in Expo DOM May 6, 2026
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.

1 participant