Files
study-bible-project/src/components/ShortcutsHelp.jsx
T
nmemmertandClaude Sonnet 5.5 67645cf1df App quality: offline badge, per-note history, keyboard study mode, notes import
- Study cards say whether the Bible text works offline, with a button to save
  the missing book (notes are always kept on the device).
- Each note keeps its last 12 versions with Restore (History under each note).
- Keyboard-only study: 1/2/3 write in Observe/Interpret/Apply, C/W/X/P switch
  resource tabs, V compares, Esc leaves a note box; listed under "?".
- Export > Import notes: bring Word/Markdown/text notes into the matching
  chunks without overwriting anything; can mark them as not your own.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 13:01:11 -04:00

71 lines
3.2 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// The "?" cheat sheet: every keyboard shortcut for the page you are on, plus the ones that work everywhere.
import { useEffect, useRef } from 'react';
import { useApp } from '../context/AppContext.js';
import { themeVars } from './reader/readerThemes.js';
const GLOBAL = [
['⌘K / Ctrl K', 'Search and go to a passage'],
['?', 'Show this list'],
['Esc', 'Close whatever is open'],
];
const BY_PAGE = {
reader: [
['← →', 'Previous / next chapter'],
['/', 'Search this chapter or the whole Bible'],
['G', 'Pick a book and chapter'],
['B', 'Bookmark the selected verse'],
['C', 'Compare translations'],
['M', 'Map this chapter’s cross-references (needs IQ Bible)'],
['H', 'Your highlights'],
[',', 'Reading settings'],
['F', 'Hide or show the controls'],
],
study: [
['← →', 'Previous / next chunk'],
['1 2 3', 'Write in Observe / Interpret / Apply'],
['Esc', 'Leave a note box (then keys work again)'],
['C W X P', 'Commentary / Word study / Cross-refs / People & places'],
['V', 'Compare passages or translations'],
],
};
export default function ShortcutsHelp({ onClose }) {
const { readerTheme, currentPage } = useApp();
const closeRef = useRef(null);
useEffect(() => {
const from = document.activeElement;
closeRef.current?.focus();
const onKey = (e) => { if (e.key === 'Escape' || e.key === '?') { e.preventDefault(); e.stopPropagation(); onClose(); } };
document.addEventListener('keydown', onKey, true);
return () => { document.removeEventListener('keydown', onKey, true); if (from instanceof HTMLElement && document.contains(from)) from.focus({ preventScroll: true }); };
}, [onClose]);
const page = BY_PAGE[currentPage] ?? [];
const section = (title, rows) => (
<div className="mb-4 last:mb-0">
<h3 className="mb-1.5 text-[11px] uppercase tracking-wide text-[var(--r-sub)]">{title}</h3>
<dl className="space-y-1.5">
{rows.map(([keys, what]) => (
<div key={keys} className="flex items-center justify-between gap-4 text-sm">
<dt><kbd className="rounded-md border border-[var(--r-line)] bg-[var(--r-bg)] px-2 py-0.5 font-mono text-xs">{keys}</kbd></dt>
<dd className="text-right text-[var(--r-sub)]">{what}</dd>
</div>
))}
</dl>
</div>
);
return (
<div style={themeVars(readerTheme)} className="fixed inset-0 z-[90] flex items-center justify-center bg-black/40 px-3 font-sans" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
<div role="dialog" aria-modal="true" aria-label="Keyboard shortcuts" className="max-h-[80dvh] w-full max-w-sm overflow-y-auto rounded-2xl border border-[var(--r-line)] bg-[var(--r-bar)] p-5 text-[var(--r-text)] shadow-2xl">
<div className="mb-3 flex items-center justify-between">
<h2 className="text-base font-medium">Keyboard shortcuts</h2>
<button ref={closeRef} type="button" onClick={onClose} className="rounded-lg px-2 py-1 text-sm text-[var(--r-sub)] hover:bg-black/5">Close</button>
</div>
{page.length > 0 && section(currentPage === 'reader' ? 'In the Bible' : 'In this study', page)}
{section('Everywhere', GLOBAL)}
</div>
</div>
);
}