Skip to content

PT-3662, PT-3744, partially PT-3661#1949

Open
Sebastian-ubs wants to merge 23 commits intomainfrom
PT-3661_PT-3662
Open

PT-3662, PT-3744, partially PT-3661#1949
Sebastian-ubs wants to merge 23 commits intomainfrom
PT-3661_PT-3662

Conversation

@Sebastian-ubs
Copy link
Copy Markdown
Contributor

@Sebastian-ubs Sebastian-ubs commented Dec 10, 2025

Now depends on #1952

This PR changes the result card click behavior to match Interaction design

  • single click or space/enter on the card = select item
  • double click or click/space/enter on the button = change reference, focus editor + select text

This PR fixes / helps for the following work items

  • fixes PT-3662 → scripture reference as button
    (this also mitigates PT-3412 → no unexpected focus change on single click)
  • fixes PT-3661 → result styling (partially) - not just cutting off text
  • fixes PT-3744 → truncate find result
image image image

This change is Reviewable


Open with Devin

@Sebastian-ubs Sebastian-ubs changed the title 3662: scr ref button, partially 3661: result styling PT-3662: scr ref button, partially PT-3661: result styling Dec 10, 2025
@Sebastian-ubs Sebastian-ubs changed the title PT-3662: scr ref button, partially PT-3661: result styling PT-3662, PT-3744, partially PT-3661 Dec 10, 2025
Copy link
Copy Markdown
Member

@tjcouch-sil tjcouch-sil left a comment

Choose a reason for hiding this comment

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

If they are still relevant after changes made, please fix the TypeDoc warnings (identified in your top-level message as "build warnings"). We expect there to be none (and may be soon requiring there to be none).

@tjcouch-sil reviewed 11 of 17 files at r1, all commit messages.
Reviewable status: 11 of 17 files reviewed, 7 unresolved discussions (waiting on @Sebastian-ubs)


lib/platform-bible-react/src/utils/dir-helper.util.ts line 18 at r1 (raw file):

  if (!hasLocalStorage()) return 'ltr';

  try {

try/catch around the contents of readDirection and persistDirection as they were written before sounds good to avoid blowing things up, but I think we should still warn with the error message that comes from accessing localStorage.getItem when localStorage is not defined. I don't think we should check for if window is defined and only use window.localStorage, though, because localStorage should be available in this context as far as I know. It seems this is a bandage that covers a problem rather than fixing it.

I'd rather see this continue to warn (or at least log in some way) when it fails and have a work item to look into it rather than to have it silently fail and we are confused as to why something isn't matching the direction properly later on when we start looking more closely at RTL.

All the same goes for the code in the storybook theme provider file, but I don't care about that one very much.


lib/platform-bible-react/src/components/basics/scripture-reference-button.component.tsx line 10 at r1 (raw file):

export type ScrRefBtnProps = {
  startRef: ScrRef;

Can we use SerializedVerseRef instead of this new ScrRef? We have pretty much unified around SerializedVerseRef in all our dealings with verse/Scripture references. I would like to avoid adding a new type that muddies the waters.

Presumably, at some point, we will make some class that formats Verse Refs in a project-aware way. Once we have that, it would be best to have SerializedVerseRef here anyway so we can pass that into the formatter.


lib/platform-bible-react/src/components/basics/scripture-reference-button.component.tsx line 14 at r1 (raw file):

  text?: string;
  className?: string;
  onClick?: (e: unknown) => void;

onClick's type should be MouseEventHandler<T> | undefined


lib/platform-bible-react/src/components/basics/scripture-reference-button.component.tsx line 15 at r1 (raw file):

  className?: string;
  onClick?: (e: unknown) => void;
  remainderTextLength?: number;

This is not self-explanatory. If this code stays around, please add TSDoc. Also, I would recommend probably renaming it. It doesn't seem like it from the variable name, but I believe I see this number applies to how many words at the start and the end of the text to keep, but I generally expect characters when I see "text length".


lib/platform-bible-react/src/components/basics/scripture-reference-button.component.tsx line 18 at r1 (raw file):

};

function trimMiddleWordsWithRemovedCount(sentence: string, x: number): string {

The function name is not very clear to me; might I recommend something like truncateStringByOmittingMiddleWords, replaceMiddleWordsWithEllipsis, shortenStringOmitMiddleWords, or something. "Trim" brings cutting off the ends to mind like the built-in trim functions, and "with removed count" made me think you were returning how many words you were taking out from the middle.

These parameter names do not make sense. Please adjust. And maybe should this stuff go in string utils in PBU?


lib/platform-bible-react/src/components/basics/scripture-reference-button.component.tsx line 32 at r1 (raw file):

}

function ScrRefButton({

Honestly I really don't think this makes sense as a generic component to be exported from PBR. It's used one time, which is only inside PBR. It doesn't really make clear sense from the outside how the different pieces are combined to create the button (for example, I was expecting this button simply to display a SerializedVerseRef or a range of them, but then I saw there was also text. It's not intuitive what text is for. I'd recommend at least not exporting this from PBR for now so we have more time to figure out what a more natural API would be for such a component.

I also recommend either to in-line this in ResultsCard or to make it more self-explanatory in some way. It doesn't really make sense to me to combine the functionality of a button that is intended to display a range of verse references with the functionality of a button that is intended to display some text that should be truncated in some very particular way in some situations. For example, should the check result text really be truncated when it gets past 14 words? I wouldn't expect so. Maybe can these two different sets of functionality be split into two different components? Maybe you pass in the truncated one into the button via children? Or maybe make a VerseRefDisplay component that just handles displaying the verse ref in some way, then you can put these two together under a normal button? Or maybe that's breaking it into too small of pieces to be worth doing, so maybe in-lining is the right call. I dunno what exactly the best solution is, but this button seems very strange.


lib/platform-bible-react/src/components/basics/scripture-reference-button.component.tsx line 50 at r1 (raw file):

        aria-label="Submit reference change"
        onClick={(e) => {
          e.stopPropagation(); // Stops bubbling to outer div

I'd argue it's better to just directly call onClick as it is passed in rather than to stop propagation here since this a standard HTML event. If someone wants to stop propagation, they can by running it on the event that is passed in as the first parameter.

Copy link
Copy Markdown
Member

@tjcouch-sil tjcouch-sil left a comment

Choose a reason for hiding this comment

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

Thanks for tackling all this stuff! The lists look nicer.

For the sake of my own curiosity, do you know how double clicking works on keyboard? Maybe it doesn't and you have to think of other ways to do double clicking actions on keyboard; just curious.

Reviewable status: 11 of 17 files reviewed, 7 unresolved discussions (waiting on @Sebastian-ubs)

Copy link
Copy Markdown
Contributor

@rolfheij-sil rolfheij-sil left a comment

Choose a reason for hiding this comment

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

@rolfheij-sil reviewed 15 of 17 files at r1, all commit messages.
Reviewable status: 16 of 17 files reviewed, 11 unresolved discussions (waiting on @Sebastian-ubs)


lib/platform-bible-react/src/index.ts line 212 at r1 (raw file):

} from './components/shadcn-ui/tooltip';
export type { Scope } from './components/utils/scripture.util';
export { default as ScrRefButton } from './components/basics/scripture-reference-button.component';

Can you move this to the basics exports section?
So alphabetically it should go between these items:

export { default as ResultsCard } from './components/basics/results-card.component';
export { default as SearchBar } from './components/basics/search-bar.component';

While you're at it, would you mind moving this export to that section too?

export {
  VerticalTabs,
  VerticalTabsList,
  VerticalTabsContent,
  VerticalTabsTrigger,
} from './components/basics/tabs-vertical';

extensions/src/platform-scripture/src/checks/checks-side-panel/check-card.component.tsx line 81 at r1 (raw file):

  handleDenyCheck: (result: CheckRunResult) => Promise<boolean>;
  /** Scripture reference as link */
  scrRef: ScrRefBtnProps;

I think scrRef functions as a somewhat protected keyword in our codebase I think. We will exclusively using to actually store scripture references using the SerialzedVerseRef type. It's confusing that it's now used from a set of props that contains some scripture references.

Moreover, it's interesting that we're nesting props inside props here. (ScrRefBtnProps inside of CheckCardProps). That might be a code smell.


lib/platform-bible-react/src/components/basics/results-card.component.tsx line 61 at r1 (raw file):

    // eslint-disable-next-line no-type-assertion/no-type-assertion
    const activeEl = document.activeElement as HTMLElement;
    const isButtonFocused = activeEl?.closest('button') || activeEl?.tagName === 'BUTTON';

What are you trying to achieve here? This will return true if any button is focused right, not specifically a button inside the card, right?
Can't we handle this with a useRef to make ik more reliable and specific?


lib/platform-bible-react/src/components/basics/results-card.component.tsx line 80 at r1 (raw file):

      onMouseDown={(e) => {
        // cancel double‑click text selection
        if (e.detail > 1) e.preventDefault();

Why add the if statement? Or why add the onMouseDown at all? Won't the default already be to do nothing when on mouse down if we don't provide a handler?

Copy link
Copy Markdown
Contributor Author

@Sebastian-ubs Sebastian-ubs left a comment

Choose a reason for hiding this comment

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

Reviewable status: 2 of 18 files reviewed, 11 unresolved discussions (waiting on @rolfheij-sil and @tjcouch-sil)


extensions/src/platform-scripture/src/checks/checks-side-panel/check-card.component.tsx line 81 at r1 (raw file):

Previously, rolfheij-sil (Rolf Heij) wrote…

I think scrRef functions as a somewhat protected keyword in our codebase I think. We will exclusively using to actually store scripture references using the SerialzedVerseRef type. It's confusing that it's now used from a set of props that contains some scripture references.

Moreover, it's interesting that we're nesting props inside props here. (ScrRefBtnProps inside of CheckCardProps). That might be a code smell.

Done updated ref to use SerializedVerseRef
Nesting props imho is actually a good thing to keep the interface clear, but we may argue about it :-)


lib/platform-bible-react/src/index.ts line 212 at r1 (raw file):

Previously, rolfheij-sil (Rolf Heij) wrote…

Can you move this to the basics exports section?
So alphabetically it should go between these items:

export { default as ResultsCard } from './components/basics/results-card.component';
export { default as SearchBar } from './components/basics/search-bar.component';

While you're at it, would you mind moving this export to that section too?

export {
  VerticalTabs,
  VerticalTabsList,
  VerticalTabsContent,
  VerticalTabsTrigger,
} from './components/basics/tabs-vertical';

Done.


lib/platform-bible-react/src/components/basics/results-card.component.tsx line 80 at r1 (raw file):

Previously, rolfheij-sil (Rolf Heij) wrote…

Why add the if statement? Or why add the onMouseDown at all? Won't the default already be to do nothing when on mouse down if we don't provide a handler?

This is to prevent double click on the card ('s text) to make a text selection. Otherwise the Electron default for double clicking is to always do a text selection of the word under the cursor. I had looked for a solution to this earlier for Home and plan to also apply it there.


lib/platform-bible-react/src/components/basics/scripture-reference-button.component.tsx line 10 at r1 (raw file):

Previously, tjcouch-sil (TJ Couch) wrote…

Can we use SerializedVerseRef instead of this new ScrRef? We have pretty much unified around SerializedVerseRef in all our dealings with verse/Scripture references. I would like to avoid adding a new type that muddies the waters.

Presumably, at some point, we will make some class that formats Verse Refs in a project-aware way. Once we have that, it would be best to have SerializedVerseRef here anyway so we can pass that into the formatter.

Done.


lib/platform-bible-react/src/components/basics/scripture-reference-button.component.tsx line 14 at r1 (raw file):

Previously, tjcouch-sil (TJ Couch) wrote…

onClick's type should be MouseEventHandler<T> | undefined

Done.


lib/platform-bible-react/src/components/basics/scripture-reference-button.component.tsx line 15 at r1 (raw file):

Previously, tjcouch-sil (TJ Couch) wrote…

This is not self-explanatory. If this code stays around, please add TSDoc. Also, I would recommend probably renaming it. It doesn't seem like it from the variable name, but I believe I see this number applies to how many words at the start and the end of the text to keep, but I generally expect characters when I see "text length".

Done.


lib/platform-bible-react/src/components/basics/scripture-reference-button.component.tsx line 18 at r1 (raw file):

Previously, tjcouch-sil (TJ Couch) wrote…

The function name is not very clear to me; might I recommend something like truncateStringByOmittingMiddleWords, replaceMiddleWordsWithEllipsis, shortenStringOmitMiddleWords, or something. "Trim" brings cutting off the ends to mind like the built-in trim functions, and "with removed count" made me think you were returning how many words you were taking out from the middle.

These parameter names do not make sense. Please adjust. And maybe should this stuff go in string utils in PBU?

Done. Moved into pbu in #1952


lib/platform-bible-react/src/components/basics/scripture-reference-button.component.tsx line 32 at r1 (raw file):

Previously, tjcouch-sil (TJ Couch) wrote…

Honestly I really don't think this makes sense as a generic component to be exported from PBR. It's used one time, which is only inside PBR. It doesn't really make clear sense from the outside how the different pieces are combined to create the button (for example, I was expecting this button simply to display a SerializedVerseRef or a range of them, but then I saw there was also text. It's not intuitive what text is for. I'd recommend at least not exporting this from PBR for now so we have more time to figure out what a more natural API would be for such a component.

I also recommend either to in-line this in ResultsCard or to make it more self-explanatory in some way. It doesn't really make sense to me to combine the functionality of a button that is intended to display a range of verse references with the functionality of a button that is intended to display some text that should be truncated in some very particular way in some situations. For example, should the check result text really be truncated when it gets past 14 words? I wouldn't expect so. Maybe can these two different sets of functionality be split into two different components? Maybe you pass in the truncated one into the button via children? Or maybe make a VerseRefDisplay component that just handles displaying the verse ref in some way, then you can put these two together under a normal button? Or maybe that's breaking it into too small of pieces to be worth doing, so maybe in-lining is the right call. I dunno what exactly the best solution is, but this button seems very strange.

Intention is that there should be choices if to use the whole text as link or only the scrRef.
I've changed it a bit, added documentation and removed export.
Moved formatting ref and ref range into #1952


lib/platform-bible-react/src/components/basics/scripture-reference-button.component.tsx line 50 at r1 (raw file):

Previously, tjcouch-sil (TJ Couch) wrote…

I'd argue it's better to just directly call onClick as it is passed in rather than to stop propagation here since this a standard HTML event. If someone wants to stop propagation, they can by running it on the event that is passed in as the first parameter.

Done.


lib/platform-bible-react/src/utils/dir-helper.util.ts line 18 at r1 (raw file):

Previously, tjcouch-sil (TJ Couch) wrote…

try/catch around the contents of readDirection and persistDirection as they were written before sounds good to avoid blowing things up, but I think we should still warn with the error message that comes from accessing localStorage.getItem when localStorage is not defined. I don't think we should check for if window is defined and only use window.localStorage, though, because localStorage should be available in this context as far as I know. It seems this is a bandage that covers a problem rather than fixing it.

I'd rather see this continue to warn (or at least log in some way) when it fails and have a work item to look into it rather than to have it silently fail and we are confused as to why something isn't matching the direction properly later on when we start looking more closely at RTL.

All the same goes for the code in the storybook theme provider file, but I don't care about that one very much.

Done.

Copy link
Copy Markdown
Contributor Author

@Sebastian-ubs Sebastian-ubs left a comment

Choose a reason for hiding this comment

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

The result card has two ways to select:
A) double click the card
B) click on the link → this is the keyboard way of doing it

Reviewable status: 2 of 18 files reviewed, 11 unresolved discussions (waiting on @rolfheij-sil and @tjcouch-sil)

Copy link
Copy Markdown
Contributor Author

@Sebastian-ubs Sebastian-ubs left a comment

Choose a reason for hiding this comment

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

sorry, this was not very clear. Let me explain again:

  • There are two ways to select a Card: single click or focus + enter / space key
  • There are 3 ways to execute the double click operation (which navigates to the scripture reference location, focuses the editor and highlights text): double click the card or single click the reference button or focus + enter / space key on the reference button

Reviewable status: 2 of 18 files reviewed, 11 unresolved discussions (waiting on @rolfheij-sil and @tjcouch-sil)

Copy link
Copy Markdown
Contributor Author

@Sebastian-ubs Sebastian-ubs left a comment

Choose a reason for hiding this comment

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

Reviewable status: 2 of 18 files reviewed, 11 unresolved discussions (waiting on @rolfheij-sil and @tjcouch-sil)


lib/platform-bible-react/src/components/basics/results-card.component.tsx line 61 at r1 (raw file):

Previously, rolfheij-sil (Rolf Heij) wrote…

What are you trying to achieve here? This will return true if any button is focused right, not specifically a button inside the card, right?
Can't we handle this with a useRef to make ik more reliable and specific?

Done. That was the result of vibe coding, but using ref is better, I agree.

rolfheij-sil
rolfheij-sil previously approved these changes Dec 12, 2025
Copy link
Copy Markdown
Contributor

@rolfheij-sil rolfheij-sil 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 digging into the codebase, Sebastian!

@rolfheij-sil reviewed 8 of 16 files at r2, 1 of 1 files at r3, 7 of 7 files at r4, all commit messages.
Reviewable status: all files reviewed, 7 unresolved discussions (waiting on @tjcouch-sil)


lib/platform-bible-react/src/index.ts line 212 at r1 (raw file):

Previously, Sebastian-ubs wrote…

Done.

Thanks!


lib/platform-bible-react/src/components/basics/results-card.component.tsx line 80 at r1 (raw file):

Previously, Sebastian-ubs wrote…

This is to prevent double click on the card ('s text) to make a text selection. Otherwise the Electron default for double clicking is to always do a text selection of the word under the cursor. I had looked for a solution to this earlier for Home and plan to also apply it there.

Interesting fix, thanks for the research!

Copy link
Copy Markdown
Contributor Author

@Sebastian-ubs Sebastian-ubs left a comment

Choose a reason for hiding this comment

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

@Sebastian-ubs made 1 comment.
Reviewable status: 9 of 23 files reviewed, 8 unresolved discussions (waiting on @rolfheij-sil and @tjcouch-sil).


lib/platform-bible-react/src/components/basics/linked-scr-ref-display.component.tsx line 68 at r5 (raw file):

          {endRef
            ? formatScrRefRange(startRef, endRef, scrRefFormattingProps)
            : formatScrRef(

@tjcouch-sil this is, where I wanted to use the previously exportedformatScrRefWithOptionalParts from #1952

Now the current result is: ranges are formatted omitting parts, single references are formatted with still displaying optional parts.
E.g. could have a reference formatted as "GEN 1:-1" next to a reference range formatted as "GEN 1 - 2"
However until the optional parts are always provided and valid, this is a theoretical scenario.

Also using formatScrRefWithOptionalParts or formatScrRefWithOptions would allow to just pass in the options object without decomposing it here.

Copy link
Copy Markdown
Contributor Author

@Sebastian-ubs Sebastian-ubs left a comment

Choose a reason for hiding this comment

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

@Sebastian-ubs made 1 comment.
Reviewable status: 9 of 23 files reviewed, 8 unresolved discussions (waiting on @rolfheij-sil and @tjcouch-sil).


lib/platform-bible-react/src/components/basics/linked-scr-ref-display.component.tsx line 68 at r5 (raw file):

Previously, Sebastian-ubs wrote…

@tjcouch-sil this is, where I wanted to use the previously exportedformatScrRefWithOptionalParts from #1952

Now the current result is: ranges are formatted omitting parts, single references are formatted with still displaying optional parts.
E.g. could have a reference formatted as "GEN 1:-1" next to a reference range formatted as "GEN 1 - 2"
However until the optional parts are always provided and valid, this is a theoretical scenario.

Also using formatScrRefWithOptionalParts or formatScrRefWithOptions would allow to just pass in the options object without decomposing it here.

As formatScrRefRange currently ignores a endRef that is similar to startRef, we could also mitigate this, by passing in startRef twice, if endRef is not defined, which would work, but also looks strange when calling it here like this. Could be better with a comment, but feels more like a work around.

@Sebastian-ubs
Copy link
Copy Markdown
Contributor Author

Unfortunately I am not able to finish this task now. Very likely getLocalizedBookName should go to platform-bible-utils or the whole lookup and passing around be done differently or thought-to-be-common functionality be put back into doing it local only. Would love to do some pair programming about this next year to get it cleaned in a useful way.

Note: ux has requested a little change, that hitting "enter" or "space" on a already selected card would execute the double click action.

@Sebastian-ubs Sebastian-ubs marked this pull request as draft December 19, 2025 13:41
@Sebastian-ubs Sebastian-ubs marked this pull request as ready for review February 13, 2026 16:38
@Sebastian-ubs
Copy link
Copy Markdown
Contributor Author

Sebastian-ubs commented Mar 2, 2026

  • dev please review the code
  • ux please review / test if the behavior is as expected (i.e. currently users can select a card which will then not navigate, which might seem unexpected and need a small change to make this more obvious as the intended behavior)

Copy link
Copy Markdown
Collaborator

@jolierabideau jolierabideau left a comment

Choose a reason for hiding this comment

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

@jolierabideau reviewed 18 files and all commit messages, made 4 comments, and resolved 1 discussion.
Reviewable status: all files reviewed, 12 unresolved discussions (waiting on Sebastian-ubs and tjcouch-sil).


lib/platform-bible-react/src/components/basics/linked-scr-ref-display.component.tsx line 41 at r10 (raw file):

    </span>
  );
}

Devin is also reporting a potential bug here with a missing 'scripture-font' CSS class that I am not sure is relevant https://app.devin.ai/review/paranext/paranext-core/pull/1949#bug-BUG_pr-review-job-2d3e26268a9b412b817c7ebc23e2e08f_0002

Code quote:

function scripturePartDisplay(scriptureTextPart?: string, className?: string) {
  if (!scriptureTextPart) return undefined;
  return (
    <span
      className={cn(
        'tw-h-fit tw-truncate tw-whitespace-normal tw-text-start tw-text-xs tw-font-medium',
        className,
      )}
    >
      {scriptureTextPart ?? ''}
    </span>
  );
}

lib/platform-bible-react/src/components/basics/results-card.component.tsx line 68 at r10 (raw file):

      onSelect?.();
    }
  };

Devin flagged this and reported that keyboard users cannot trigger the double-click action because it only calls onSelect on Enter/Space. I am not sure the correct way to handle double click or if this is relevant since there is a linked scr ref. https://app.devin.ai/review/paranext/paranext-core/pull/1949#analysis-ANALYSIS_pr-review-job-af5e69735de3493f8f39b1c1516000ec_0003

Code quote:

  const handleKeyDown = (event: React.KeyboardEvent) => {
    if (document.activeElement !== resultCardDivRef?.current) return;
    if (event.key === 'Enter' || event.key === ' ') {
      event.preventDefault();
      onSelect?.();
    }
  };

lib/platform-bible-react/src/components/basics/results-card.component.tsx line 112 at r10 (raw file):

                onSelect(); // make sure select is called first
                onDoubleClick?.();
              }}

I am not sure why it isn't showing as a comment here but Devin reported a bug in this section that seems relevant https://app.devin.ai/review/paranext/paranext-core/pull/1949#bug-BUG_pr-review-job-af5e69735de3493f8f39b1c1516000ec_0001

Code quote:

              onClick={(e) => {
                e?.stopPropagation(); // stop bubbling to ResultCard to prevent unnecessary additional select call
                onSelect(); // make sure select is called first
                onDoubleClick?.();
              }}

lib/platform-bible-react/src/components/basics/results-card.component.tsx line 111 at r10 (raw file):

                e?.stopPropagation(); // stop bubbling to ResultCard to prevent unnecessary additional select call
                onSelect(); // make sure select is called first
                onDoubleClick?.();

Devin flagged this and I agree it is slightly confusing, renaming the onDoubleClick function to onNavigate or something else could be helpful. https://app.devin.ai/review/paranext/paranext-core/pull/1949#analysis-ANALYSIS_pr-review-job-cff3c910bbd04382a18d42646218a34f_0002

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 2 new potential issues.

View 12 additional findings in Devin Review.

Open in Devin Review

Comment on lines +29 to +41
function scripturePartDisplay(scriptureTextPart?: string, className?: string) {
if (!scriptureTextPart) return undefined;
return (
<span
className={cn(
'tw-h-fit tw-truncate tw-whitespace-normal tw-text-start tw-text-xs tw-font-medium',
className,
)}
>
{scriptureTextPart ?? ''}
</span>
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 scripture-font CSS class dropped from scripture text in card headers

Previously, both CheckCard and SearchResult rendered scripture text with the scripture-font CSS class (e.g., <span className="scripture-font">{checkResult.itemText}</span> and <span className="scripture-font">{searchResult.text ?? ''}</span>). After this refactoring, these texts are passed as scriptureTextPart to LinkedScrRefDisplay via the linkedScrRef prop on ResultsCard. The scripturePartDisplay function in linked-scr-ref-display.component.tsx:29-41 renders the text without scripture-font. Additionally, ResultsCard at line 122 hardcodes a className on LinkedScrRefDisplay and does not forward linkedScrRef.className, so there is no way for callers to inject the scripture-font class through the current API. This is a visual regression that affects proper rendering of scripture text, particularly for non-Latin scripts (RTL, complex scripts) that depend on the scripture font.

Prompt for agents
The LinkedScrRefDisplay component needs a way to apply a scripture-specific font class (scripture-font) to the scriptureTextPart. There are two things to fix:

1. In lib/platform-bible-react/src/components/basics/linked-scr-ref-display.component.tsx, add a new optional prop (e.g., scriptureTextClassName) to LinkedScrRefDisplayProps that gets passed to the scripturePartDisplay function and merged with existing classes on the scripture text span.

2. In lib/platform-bible-react/src/components/basics/results-card.component.tsx around line 112-123, forward the new prop from linkedScrRef to LinkedScrRefDisplay so callers can pass it through.

3. In extensions/src/platform-scripture/src/checks/checks-side-panel/check-card.component.tsx line 214, add scriptureTextClassName: 'scripture-font' to the linkedScrRef prop.

4. In extensions/src/platform-scripture/src/find/search-result.component.tsx around line 243-259, add scriptureTextClassName: 'scripture-font' to the linkedScrRef useMemo return value.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +117 to +121
onClick={(e) => {
e?.stopPropagation(); // stop bubbling to ResultCard to prevent unnecessary additional select call
onSelect(); // make sure select is called first
onDoubleClick?.();
}}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 LinkedScrRefDisplay onClick in ResultsCard triggers onDoubleClick on every single click

In ResultsCard, the LinkedScrRefDisplay button's onClick handler at lines 117-121 unconditionally calls onDoubleClick?.() on every single click. This means clicking the scripture reference link inside any ResultsCard always triggers the navigation behavior (documented as the double-click action). While this may be intentionally designed as a "navigate to reference" link, the result is that onDoubleClick fires on single click of the link but requires an actual double-click on other parts of the card. This inconsistency can cause unexpected navigation — for example, in the Find panel, handleFocusedResultChange is called (which steals focus to the editor in find mode via papi.window.setFocus at find.web-view.tsx:877), even though the user only single-clicked.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sebastian-ubs and others added 23 commits April 2, 2026 17:41
…ays in ResultsCard

The `badges() ?? undefined` pattern never produced `undefined` because
arrays are always truthy. Build badges with conditional pushes instead,
and change ResultsCard badges prop to ReactNode so `badges &&` guards
correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stop dblclick event propagation on the LinkedScrRefDisplay button so
double-clicking the scripture reference behaves the same as single-clicking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move getLocalizedBookName and formatScrRefWithOptionalParts to pbu
- apply review comments to fix reference
…, and rebuild

- Add key prop to CheckStateBadge in check-card badges array (Devin review fix)
- Add @ts-expect-error for insertMarker calls removed in editor v0.8.14
- Rebuild platform-bible-react dist

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove unused MoreHorizontal import in results-card, remove stale
@ts-expect-error directives in PlatformToolbar, and rebuild
platform-bible-utils and platform-bible-react dist outputs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Resolved conflict in results-card additionalContent prop naming and
rebuilt platform-bible-utils, platform-bible-react, and paranext-core.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The rebase incorrectly kept the isSelected guard on additionalContent
in ResultsCard, hiding the preview text from PT-3896. Removed the guard
so preview text shows for all visible results via IntersectionObserver.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Sebastian-ubs
Copy link
Copy Markdown
Contributor Author

rebased onto latest main

I need to address review feedback when I am back next week

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.

4 participants