Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .changeset/slick-worlds-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
'@youversion/platform-react-ui': minor
'@youversion/platform-core': minor
'@youversion/platform-react-hooks': minor
---

feat(ui): add dark mode theme support to BibleTextView and BibleReader

- Add theme prop (light/dark) to BibleTextView for text theme control
- Implement theme inheritance from YouVersionProvider via useTheme hook
- Add data-yv-sdk and data-yv-theme attributes for CSS styling
- Pass theme prop from BibleReader to BibleTextView
- Add yv:bg-background wrapper to all BibleTextView Storybook stories
- Rename prop from 'background' to 'theme' for semantic clarity
2 changes: 2 additions & 0 deletions packages/ui/src/components/bible-reader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ function Content() {
currentFontFamily,
lineHeight,
showVerseNumbers,
background,
} = useBibleReaderContext();
const { books } = useBooks(versionId);
const { version } = useVersion(versionId);
Expand Down Expand Up @@ -185,6 +186,7 @@ function Content() {
</h1>

<BibleTextView
theme={background}
reference={usfmReference}
versionId={versionId}
fontFamily={currentFontFamily}
Expand Down
35 changes: 35 additions & 0 deletions packages/ui/src/components/verse.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ const meta = {
},
tags: ['autodocs'],
argTypes: {
theme: {
table: {
disable: true,
},
},
reference: {
control: 'text',
description: 'USFM reference (e.g., "JHN.3.16", "JHN.3.16-17", "JHN.3")',
Expand Down Expand Up @@ -226,3 +231,33 @@ export const FootnoteInteraction: Story = {
});
},
};

export const DarkMode: Story = {
args: {
reference: 'JHN.3.16',
versionId: 111,
renderNotes: true,
theme: 'dark',
},
argTypes: {
// The `theme` control is disabled across all of the Bible verse text
// components, stories, except the dark mode one.
theme: {
table: {
disable: false,
},
},
},
render: (args) => (
<section className="yv:flex yv:flex-col yv:gap-4 yv:max-w-lg">
<p className="yv:text-muted-foreground yv:font-sm">
Important: The background and padding for this Story was added manually to showcase the text
being influenced by the theme prop for the BibleTextView component. Otherwise, the text on a
light theme would be white on white (aka unreadable)
</p>
<div className="yv:[&>div]:bg-background yv:[&>div]:p-4 yv:[&>div]:rounded-[8px]">
<BibleTextView {...args} />
</div>
</section>
),
};
56 changes: 33 additions & 23 deletions packages/ui/src/components/verse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useEffect, forwardRef, useState, useRef, type ReactNode } from 'react';
import { createRoot, type Root } from 'react-dom/client';
import DOMPurify from 'isomorphic-dompurify';
import { usePassage } from '@youversion/platform-react-hooks';
import { usePassage, useTheme } from '@youversion/platform-react-hooks';
import { Popover, PopoverContent, PopoverTrigger, PopoverClose } from '@/components/ui/popover';
import { Button } from './ui/button';
import { Footnote } from './icons/footnote';
Expand Down Expand Up @@ -416,6 +416,7 @@ export type BibleTextViewProps = {
versionId: number;
showVerseNumbers?: boolean;
renderNotes?: boolean;
theme?: 'light' | 'dark';
};

/**
Expand All @@ -429,49 +430,58 @@ export const BibleTextView = ({
versionId,
showVerseNumbers,
renderNotes,
theme,
}: BibleTextViewProps): React.ReactElement => {
const { passage, loading, error } = usePassage({
versionId,
usfm: reference,
include_headings: true,
include_notes: true,
});
const providerTheme = useTheme();
const currentTheme = theme || providerTheme;

if (loading) {
return (
<Verse.Html
html={'<span>Loading...</span>'}
fontFamily={fontFamily}
fontSize={fontSize}
lineHeight={lineHeight}
showVerseNumbers={showVerseNumbers}
renderNotes={renderNotes}
/>
<div data-yv-sdk data-yv-theme={currentTheme}>
<Verse.Html
html={'<span>Loading...</span>'}
fontFamily={fontFamily}
fontSize={fontSize}
lineHeight={lineHeight}
showVerseNumbers={showVerseNumbers}
renderNotes={renderNotes}
/>
</div>
);
}

if (error) {
return (
<div data-yv-sdk data-yv-theme={currentTheme}>
<Verse.Html
html={'<span class="wj">We have run into an error...</span>'}
fontFamily={fontFamily}
fontSize={fontSize}
lineHeight={lineHeight}
showVerseNumbers={showVerseNumbers}
renderNotes={renderNotes}
/>
</div>
);
}

return (
<div data-yv-sdk data-yv-theme={currentTheme}>
<Verse.Html
html={'<span class="wj">We have run into an error...</span>'}
html={passage?.content || ''}
fontFamily={fontFamily}
fontSize={fontSize}
lineHeight={lineHeight}
showVerseNumbers={showVerseNumbers}
renderNotes={renderNotes}
reference={passage?.reference}
/>
);
}

return (
<Verse.Html
html={passage?.content || ''}
fontFamily={fontFamily}
fontSize={fontSize}
lineHeight={lineHeight}
showVerseNumbers={showVerseNumbers}
renderNotes={renderNotes}
reference={passage?.reference}
/>
</div>
);
};