Reader: Highlights button in the top bar

A highlighter button beside Bookmarks opens your highlights (by colour);
Bookmarks now opens the bookmarks. Each shows in the accent colour when you
have some. "H" opens the highlights.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-01 16:34:02 -04:00
1 parent 22f9700798
commit a9ca647d5a
6 files changed
+45 -9

No files matched your search

+7 -3
View File
@@ -102,7 +102,7 @@ export default function ReaderPage() {
const parallelChapter = useParallelChapter(parallelId, readerBookAbbrev, readerChapter);
const parallelSource = READER_TRANSLATIONS.find((t) => t.id === parallelId);
const [sheet, setSheet] = useState(null); // null | 'nav' | 'settings' | 'search' | 'bookmarks' | 'audio'
const [sheet, setSheet] = useState(null); // null | 'nav' | 'settings' | 'search' | 'bookmarks' | 'highlights' | 'audio'
const [chromeVisible, setChromeVisible] = useState(true);
const [readerDrawMode, setReaderDrawMode] = useState(false);
const [selectionPicker, setSelectionPicker] = useState(null);
@@ -275,6 +275,7 @@ export default function ReaderPage() {
else if (e.key === 'g' || e.key === 'G') { e.preventDefault(); openSheet('nav'); }
else if (e.key === ',') { e.preventDefault(); openSheet('settings'); }
else if (e.key === 'c' || e.key === 'C') { e.preventDefault(); openSheet('compare'); }
else if (e.key === 'h' || e.key === 'H') { e.preventDefault(); openSheet('highlights'); }
else if (e.key === 'f' || e.key === 'F') setChromeVisible((v) => !v);
else if ((e.key === 'b' || e.key === 'B') && selectedKey) {
readerBookmarks[selectedKey] ? removeBookmark(selectedKey, readerBookmarks[selectedKey]) : toggleReaderBookmark(selectedKey);
@@ -420,7 +421,9 @@ export default function ReaderPage() {
onOpenNavigator={() => openSheet('nav')}
onSearch={() => openSheet('search')}
onBookmarks={() => openSheet('bookmarks')}
bookmarkCount={bookmarkEntries.length + highlightEntries.length}
bookmarkCount={bookmarkEntries.length}
onHighlights={() => openSheet('highlights')}
highlightCount={highlightEntries.length}
onCompare={() => openSheet('compare')} compareActive={!!parallelId}
onSettings={() => openSheet('settings')}
onDoneDrawing={readerDrawMode ? () => setReaderDrawMode(false) : undefined}
@@ -596,7 +599,8 @@ export default function ReaderPage() {
onJump={jump}
/>
<MarksSheet
open={sheet === 'bookmarks'} onClose={closeSheet}
open={sheet === 'bookmarks' || sheet === 'highlights'} onClose={closeSheet}
initialTab={sheet === 'bookmarks' ? 'bookmarks' : 'highlights'}
bookmarks={bookmarkEntries} highlights={highlightEntries}
colorLabels={readerColorLabels ?? {}} onSetLabel={setReaderColorLabel}
onJump={jump}
+25
View File
@@ -117,6 +117,31 @@ test('tapping a verse colour again takes it off, and Clear removes them all (wit
Object.assign(ctx, saved);
});
test('a Highlights button sits in the top bar and opens the highlights; Bookmarks opens the bookmarks', () => {
const saved = { ...ctx };
Object.assign(ctx, {
readerTextHighlights: [{ id: 'h1', book: 'JHN', chapter: 3, verse: 2, startOffset: 0, endOffset: 4, color: '#bbf7d0', text: 'This' }],
readerBookmarks: { 'JHN-3-1': '#fef08a' },
});
render(<ReaderPage />);
const highlights = screen.getByLabelText('Highlights');
expect(highlights.nextElementSibling).toBe(screen.getByLabelText('Bookmarks')); // beside the bookmarks button
fireEvent.click(highlights);
expect(screen.getByRole('tab', { name: /highlights \(1\)/i })).toHaveAttribute('aria-selected', 'true');
expect(screen.getByText(/“This”/)).toBeTruthy();
fireEvent.click(screen.getByLabelText('Close'));
fireEvent.click(screen.getByLabelText('Bookmarks'));
expect(screen.getByRole('tab', { name: /bookmarks \(1\)/i })).toHaveAttribute('aria-selected', 'true');
expect(screen.getByText('John 3:1')).toBeTruthy();
Object.assign(ctx, saved);
});
test('the H key opens the highlights', () => {
render(<ReaderPage />);
fireEvent.keyDown(window, { key: 'h' });
expect(screen.getByRole('dialog', { name: /bookmarks & highlights/i })).toBeTruthy();
});
test('tapping a verse selects it', () => {
render(<ReaderPage />);
fireEvent.click(screen.getByText(/This man came to Jesus/));