diff --git a/.changeset/bible-card-footnote-press.md b/.changeset/bible-card-footnote-press.md
new file mode 100644
index 00000000..941b5d17
--- /dev/null
+++ b/.changeset/bible-card-footnote-press.md
@@ -0,0 +1,4 @@
+---
+"@youversion/platform-react-ui": minor
+---
+Add optional `onFootnotePress` callback to `BibleCard` for custom footnote handling (same pattern as `BibleReader`).
diff --git a/packages/ui/src/components/bible-card.test.tsx b/packages/ui/src/components/bible-card.test.tsx
index abc86d42..ca147137 100644
--- a/packages/ui/src/components/bible-card.test.tsx
+++ b/packages/ui/src/components/bible-card.test.tsx
@@ -2,8 +2,10 @@
* @vitest-environment jsdom
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
-import { render, act, within } from '@testing-library/react';
+import { render, act, within, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
import { BibleCard } from './bible-card';
+import type { FootnoteData } from './verse';
import { usePassage, useVersion, useTheme } from '@youversion/platform-react-hooks';
import type { BiblePassage, BibleVersion } from '@youversion/platform-core';
@@ -119,3 +121,50 @@ describe('BibleCard - Delayed spinner', () => {
);
});
});
+
+describe('BibleCard - onFootnotePress callback', () => {
+ const mockPassageWithFootnote: BiblePassage = {
+ id: 'JHN.1',
+ content: `
5The light shines1:5 Or understood.
`,
+ reference: 'JHN.1',
+ };
+
+ beforeEach(() => {
+ vi.mocked(useTheme).mockReturnValue('light');
+ vi.mocked(useVersion).mockReturnValue({
+ version: mockVersion,
+ loading: false,
+ error: null,
+ refetch: vi.fn(),
+ });
+ vi.mocked(usePassage).mockReturnValue({
+ passage: mockPassageWithFootnote,
+ loading: false,
+ error: null,
+ refetch: vi.fn(),
+ });
+ });
+
+ it('should call onFootnotePress when provided via BibleCard', async () => {
+ const onFootnotePress = vi.fn();
+
+ const { container } = render(
+ ,
+ );
+
+ const button = await waitFor(() => {
+ const btn = container.querySelector('[data-verse-footnote="5"] button');
+ expect(btn).not.toBeNull();
+ return btn as HTMLButtonElement;
+ });
+
+ await userEvent.click(button);
+
+ expect(onFootnotePress).toHaveBeenCalledTimes(1);
+ const data = onFootnotePress.mock.calls[0]![0] as FootnoteData;
+ expect(data.verseNum).toBe('5');
+ expect(data.reference).toBe('JHN.1');
+ expect(data.notes).toHaveLength(1);
+ expect(data.notes[0]).toContain('Or understood');
+ });
+});
diff --git a/packages/ui/src/components/bible-card.tsx b/packages/ui/src/components/bible-card.tsx
index 9d5dde6c..a2a52f50 100644
--- a/packages/ui/src/components/bible-card.tsx
+++ b/packages/ui/src/components/bible-card.tsx
@@ -1,6 +1,6 @@
import { usePassage, useVersion, useTheme } from '@youversion/platform-react-hooks';
import { DEFAULT_LICENSE_FREE_BIBLE_VERSION } from '@youversion/platform-core';
-import { BibleTextView } from './verse';
+import { BibleTextView, type FootnoteData } from './verse';
import { BibleAppLogoLockup } from './bible-app-logo-lockup';
import { BibleVersionPicker, type BibleVersionPickerPressData } from './bible-version-picker';
import { Button } from './ui/button';
@@ -37,6 +37,7 @@ export type BibleCardProps = {
background?: 'light' | 'dark';
showVersionPicker?: boolean;
onVersionPickerPress?: (data: BibleVersionPickerPressData) => void;
+ onFootnotePress?: (data: FootnoteData) => void;
};
function BibleCardHeaderError(): React.ReactNode {
@@ -127,6 +128,7 @@ export function BibleCard({
background,
showVersionPicker = false,
onVersionPickerPress,
+ onFootnotePress,
}: BibleCardProps): React.ReactNode {
// Controlled only when both versionId + onVersionChange are provided.
// versionId alone seeds uncontrolled state, preserving backwards compatibility
@@ -198,6 +200,7 @@ export function BibleCard({
loading: passageLoading,
error: passageError,
}}
+ onFootnotePress={onFootnotePress}
/>