Skip to content

YPE-1219 - feat(ui): add language search to BibleVersionPicker#270

Merged
Dustin-Kelley merged 7 commits into
mainfrom
dk/YPE-1219-react-sdk-components-add-language-search-and-filtering-to-bible-version-picker
Jun 26, 2026
Merged

YPE-1219 - feat(ui): add language search to BibleVersionPicker#270
Dustin-Kelley merged 7 commits into
mainfrom
dk/YPE-1219-react-sdk-components-add-language-search-and-filtering-to-bible-version-picker

Conversation

@Dustin-Kelley

@Dustin-Kelley Dustin-Kelley commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add a bottom search input to the BibleVersionPicker language panel that globally filters available languages by id, language name, and display names
  • Show a no-results empty state when the query matches nothing, and hide Suggested/All tabs while searching
  • Clear language search when navigating back to versions, closing the popover, or selecting a language
  • Add en/es/fr i18n strings, unit tests, and a Storybook integration story
Screen.Recording.2026-06-24.at.9.24.38.AM.mov

Test plan

  • pnpm --filter @youversion/platform-react-ui test -- bible-version-picker.test.tsx
  • Storybook: LanguageSearch story — filter matches, empty state, tab hiding
  • Manual: open Bible version picker → language panel → search (e.g. "span") → verify filtered results
  • Manual: search with no matches → verify empty state copy
  • Manual: back to versions / close popover / select language → verify search clears

Made with Cursor

Greptile Summary

This PR adds a bottom-anchored search input to the BibleVersionPicker language panel that globally filters languages by id, name, and display names, with a loading spinner, a no-results empty state, and automatic clearing on back-navigation, popover close, or language selection.

  • BibleLanguagePickerContent gains a controlled Tabs component (preserving the selected tab across searches), a LanguageRow sub-component, and a useEffect that resets search when the open prop goes false for RN/Expo standalone consumers.
  • The Root context is extended with languageSearchQuery, filteredLanguages, isLoadingLanguages, closeLanguagePanel, and resetLanguageSearch; isLoadingLanguages gates the empty state so it doesn't flash while language data is fetching.
  • Six new unit tests cover the full search lifecycle; existing story selectors are migrated from getByPlaceholderText to role-based queries.

Confidence Score: 4/5

Safe to merge after resolving the duplicate i18n keys in en.json and adding the missing translations to es.json and fr.json.

The language search logic, state management, and reset lifecycle are correctly implemented and well-tested. The locale files have two issues: en.json now has two copies of noLanguageSearchResults and languageSearchAriaLabel (the base branch had them at lines 4–5 and this PR re-adds them at lines 46–47), and es.json/fr.json are missing all three new keys despite the PR description stating those translations were included.

packages/ui/src/i18n/locales/en.json (duplicate keys), packages/ui/src/i18n/locales/es.json and fr.json (missing new translation keys)

Important Files Changed

Filename Overview
packages/ui/src/components/bible-version-picker.tsx Core feature file — adds language search state, filtering logic, LanguageRow component, and search input UI; controlled Tabs preserves tab selection; loading/empty states handled correctly
packages/ui/src/i18n/locales/en.json Duplicate JSON keys introduced: noLanguageSearchResults and languageSearchAriaLabel already existed in the base branch at lines 4–5 and are re-added at lines 46–47 by this PR
packages/ui/src/i18n/locales/es.json Unchanged but missing the three new i18n keys (noLanguageSearchResults, languageSearchAriaLabel, versionSearchAriaLabel); PR description claims es/fr translations were added
packages/ui/src/i18n/locales/fr.json Unchanged but missing the three new i18n keys; same gap as es.json
packages/ui/src/components/bible-version-picker.test.tsx Comprehensive new tests for language search filtering, empty state, loading state, tab preservation, and clear-on-navigate; mock setup updated to support loading flags
packages/ui/src/components/bible-version-picker.stories.tsx New LanguageSearch integration story added; existing stories updated to use aria-label selectors instead of placeholder text
.changeset/bible-version-picker-language-search.md Minor changeset for @youversion/platform-react-ui; correctly categorised as a new feature

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant LanguagePanel as BibleLanguagePickerContent
    participant Root as Root (Context)
    participant Filter as filterLanguagesBySearch

    User->>LanguagePanel: Types in search input
    LanguagePanel->>Root: setLanguageSearchQuery(query)
    Root->>Filter: filterLanguagesBySearch(uniqueLanguages, query)
    Filter-->>Root: filteredLanguages[]
    Root-->>LanguagePanel: filteredLanguages via context

    alt isSearching
        alt isLoadingLanguages
            LanguagePanel-->>User: Show spinner
        else "filteredLanguages.length > 0"
            LanguagePanel-->>User: Show filtered list
        else
            LanguagePanel-->>User: Show empty state
        end
    else not searching
        LanguagePanel-->>User: Show Suggested / All tabs
    end

    User->>LanguagePanel: Selects a language
    LanguagePanel->>Root: setSelectedLanguageId + resetLanguageSearch
    LanguagePanel->>Root: "onRequestClose -> closeLanguagePanel"
    Root-->>User: Returns to version list, search cleared

    User->>LanguagePanel: Presses Back button
    LanguagePanel->>Root: closeLanguagePanel
    Note over Root: setLanguageSearchQuery + setIsLanguagesOpen(false)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant LanguagePanel as BibleLanguagePickerContent
    participant Root as Root (Context)
    participant Filter as filterLanguagesBySearch

    User->>LanguagePanel: Types in search input
    LanguagePanel->>Root: setLanguageSearchQuery(query)
    Root->>Filter: filterLanguagesBySearch(uniqueLanguages, query)
    Filter-->>Root: filteredLanguages[]
    Root-->>LanguagePanel: filteredLanguages via context

    alt isSearching
        alt isLoadingLanguages
            LanguagePanel-->>User: Show spinner
        else "filteredLanguages.length > 0"
            LanguagePanel-->>User: Show filtered list
        else
            LanguagePanel-->>User: Show empty state
        end
    else not searching
        LanguagePanel-->>User: Show Suggested / All tabs
    end

    User->>LanguagePanel: Selects a language
    LanguagePanel->>Root: setSelectedLanguageId + resetLanguageSearch
    LanguagePanel->>Root: "onRequestClose -> closeLanguagePanel"
    Root-->>User: Returns to version list, search cleared

    User->>LanguagePanel: Presses Back button
    LanguagePanel->>Root: closeLanguagePanel
    Note over Root: setLanguageSearchQuery + setIsLanguagesOpen(false)
Loading

Comments Outside Diff (1)

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

    P1 Reset standalone close

    BibleLanguagePickerContent accepts an open prop, but this component never observes open === false. Standalone SDK integrations that render this exported content directly can close and reopen the language panel with the previous languageSearchQuery still applied, so the panel reopens filtered or in the empty state instead of clearing on close.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: packages/ui/src/components/bible-version-picker.tsx
    Line: 824-848
    
    Comment:
    **Reset standalone close**
    
    `BibleLanguagePickerContent` accepts an `open` prop, but this component never observes `open === false`. Standalone SDK integrations that render this exported content directly can close and reopen the language panel with the previous `languageSearchQuery` still applied, so the panel reopens filtered or in the empty state instead of clearing on close.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code Fix in Cursor Fix in Codex

Reviews (6): Last reviewed commit: "fix(ui): reset language search on BibleL..." | Re-trigger Greptile

@Dustin-Kelley Dustin-Kelley changed the title feat(ui): add language search to BibleVersionPicker YPE - 1219 feat(ui): add language search to BibleVersionPicker Jun 24, 2026
@Dustin-Kelley Dustin-Kelley changed the title YPE - 1219 feat(ui): add language search to BibleVersionPicker YPE-1219 - feat(ui): add language search to BibleVersionPicker Jun 24, 2026
@changeset-bot

changeset-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 75ae60c

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

Comment thread packages/ui/src/i18n/locales/fr.json Outdated
@Dustin-Kelley Dustin-Kelley marked this pull request as ready for review June 24, 2026 16:36
@Dustin-Kelley Dustin-Kelley requested a review from camrun91 June 24, 2026 16:38

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa70deed3a

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/ui/src/components/bible-version-picker.tsx
Comment thread packages/ui/src/components/bible-version-picker.tsx
Comment thread packages/ui/src/components/bible-version-picker.tsx Outdated
Comment thread packages/ui/src/i18n/locales/en.json
@Dustin-Kelley Dustin-Kelley force-pushed the dk/YPE-1219-react-sdk-components-add-language-search-and-filtering-to-bible-version-picker branch from 3ae1d23 to 12b91f6 Compare June 24, 2026 19:08
Comment thread packages/ui/src/components/bible-version-picker.tsx
Comment thread packages/ui/src/i18n/locales/es.json
Comment thread packages/ui/src/i18n/locales/fr.json
@cameronapak

Copy link
Copy Markdown
Collaborator

Sorry for this. please fix storybook tests.

Copilot told me:

I'll retrieve the logs for the failing job and identify the issue.Now let me get the workflow file and the relevant story files to understand the issue better:## Solution for Failing Job 83279524227

The test failures are caused by ambiguous element queries when multiple search inputs exist on the page. The error occurs in 4 Storybook integration tests:

Root Cause: Multiple "Search" placeholders are rendered simultaneously (language search + version search), causing getByPlaceholderText('Search') to fail with "Found multiple elements with the placeholder text of: Search".

Fixes Required

1. In bible-card.stories.tsx (line 140) - WithVersionPicker story:

Change from using generic placeholder selector to scoping within the dialog:

// Before (line 140):
const searchInput = within(await screen.findByRole('dialog')).getByPlaceholderText('Search');

// After - use more specific selector or scope properly:
const dialog = await screen.findByRole('dialog');
const searchInputs = within(dialog).getAllByPlaceholderText('Search');
const searchInput = searchInputs[searchInputs.length - 1]; // Use the last/version search input

Or better yet, add a data-testid to the version search input in the component and use:

const searchInput = within(await screen.findByRole('dialog')).getByTestId('version-search-input');

2. In bible-version-picker.stories.tsx (lines 361, 460, 507) - Multiple stories:

Replace all instances of:

const searchInput = screen.getByPlaceholderText('Search');

With either:

// Option A: Use testid (requires adding testid to component)
const searchInput = screen.getByTestId('version-search-input');

// Option B: Use getAllByPlaceholderText and disambiguate
const searchInputs = screen.getAllByPlaceholderText('Search');
const searchInput = searchInputs.find(el => el.getAttribute('aria-label')?.includes('Search versions')) 
  || searchInputs[searchInputs.length - 1];

Recommended Implementation

The cleanest solution is to add data-testid attributes to search inputs in your component source files, then update the stories to use those testids instead of relying on placeholder text selectors.

Source files affected:

Dustin-Kelley and others added 3 commits June 25, 2026 14:57
Add a distinct aria-label for the Bible version search input so tests can
target it separately from the language search field when both are mounted.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cameronapak cameronapak left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@Dustin-Kelley

Copy link
Copy Markdown
Collaborator Author

@greptile review

@Dustin-Kelley Dustin-Kelley merged commit ed9eb23 into main Jun 26, 2026
6 checks passed
@Dustin-Kelley Dustin-Kelley deleted the dk/YPE-1219-react-sdk-components-add-language-search-and-filtering-to-bible-version-picker branch June 26, 2026 15:20
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.

3 participants