Make the app work better on iPhone and iPad
Build and Push Docker Image / build-and-push (push) Successful in 7m32s
Build and Push Docker Image / build-and-push (push) Successful in 7m32s
- Text fields are at least 16px on touch screens (stops iOS zooming on focus) - Chapter swipe ignores sheets, fields, sliders, sideways-scrolling rows and text selection - vh -> dvh for sheets, palette and dialogs - Bigger tap targets for small links, chips and the logo; no double-tap delay - No tap flash or landscape text inflation Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bdb04cdedc
commit
d29a66f984
12 files changed
+99
-14
No files matched your search
@@ -94,7 +94,7 @@ export default function CommandPalette({ onClose }) {
|
||||
if (authUser === null && !authServerDown) return null; // the sign-in screen has nothing to search
|
||||
let lastGroup = null;
|
||||
return (
|
||||
<div style={themeVars(readerTheme)} className="fixed inset-0 z-[90] flex items-start justify-center bg-black/40 px-3 pt-[12vh] font-sans" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
|
||||
<div style={themeVars(readerTheme)} className="fixed inset-0 z-[90] flex items-start justify-center bg-black/40 px-3 pt-[12dvh] font-sans" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
|
||||
<div role="dialog" aria-modal="true" aria-label="Search and go to" className="w-full max-w-xl overflow-hidden rounded-2xl border border-[var(--r-line)] bg-[var(--r-bar)] text-[var(--r-text)] shadow-2xl">
|
||||
<div className="flex items-center gap-2 border-b border-[var(--r-line)] px-4 py-3">
|
||||
<span className="text-[var(--r-sub)]"><SearchIcon /></span>
|
||||
@@ -107,7 +107,7 @@ export default function CommandPalette({ onClose }) {
|
||||
/>
|
||||
<kbd className="hidden rounded border border-[var(--r-line)] px-1.5 py-0.5 text-[10px] text-[var(--r-sub)] sm:block">esc</kbd>
|
||||
</div>
|
||||
<ul id="palette-list" role="listbox" ref={listRef} className="max-h-[50vh] overflow-y-auto p-2">
|
||||
<ul id="palette-list" role="listbox" ref={listRef} className="max-h-[50dvh] overflow-y-auto p-2">
|
||||
{items.length === 0 && <li className="px-3 py-6 text-center text-sm text-[var(--r-sub)]">Nothing found. Try a book and chapter, like “romans 8”.</li>}
|
||||
{items.map((item, i) => {
|
||||
const header = item.group !== lastGroup ? item.group : null;
|
||||
|
||||
@@ -106,14 +106,14 @@ export default function PresentMode({ title, subtitle = '', mode, script = '', t
|
||||
</div>
|
||||
|
||||
{mode === 'script' ? (
|
||||
<div ref={scroller} className="min-h-0 flex-1 overflow-y-auto px-[6vw] py-[8vh]" style={{ scrollBehavior: 'auto' }}>
|
||||
<div ref={scroller} className="min-h-0 flex-1 overflow-y-auto px-[6vw] py-[8dvh]" style={{ scrollBehavior: 'auto' }}>
|
||||
{script.trim()
|
||||
? <div className="mx-auto max-w-[46em] whitespace-pre-wrap font-serif" style={{ fontSize, lineHeight: 1.5 }}>{script}<div style={{ height: '50vh' }} aria-hidden="true" /></div>
|
||||
? <div className="mx-auto max-w-[46em] whitespace-pre-wrap font-serif" style={{ fontSize, lineHeight: 1.5 }}>{script}<div style={{ height: '50dvh' }} aria-hidden="true" /></div>
|
||||
: <p className="mt-20 text-center text-lg opacity-70">There’s no script to present yet. Write one on the Script page.</p>}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex min-h-0 flex-1 flex-col">
|
||||
<div className="min-h-0 flex-1 overflow-y-auto px-[6vw] py-[6vh]">
|
||||
<div className="min-h-0 flex-1 overflow-y-auto px-[6vw] py-[6dvh]">
|
||||
{step ? (
|
||||
<div className="mx-auto max-w-[46em] font-serif" style={{ fontSize, lineHeight: 1.4 }}>
|
||||
<p className="font-sans text-[0.4em] uppercase tracking-[0.16em] opacity-60">{step.kind ? `${step.kind} · ` : ''}Point {index + 1} of {steps.length}{step.minutes ? ` · ${step.minutes} min` : ''}</p>
|
||||
|
||||
@@ -53,7 +53,7 @@ export default function ShortcutsHelp({ onClose }) {
|
||||
|
||||
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-[80vh] 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 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>
|
||||
|
||||
@@ -44,7 +44,7 @@ function ActiveBody({ plan, progress, onClose, actions }) {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="max-h-[38vh] overflow-y-auto rounded-xl border border-[var(--r-line)]">
|
||||
<div className="max-h-[38dvh] overflow-y-auto rounded-xl border border-[var(--r-line)]">
|
||||
{schedule.map((refs, i) => {
|
||||
const done = progress.completedDays.includes(i);
|
||||
return (
|
||||
|
||||
@@ -46,7 +46,7 @@ export default function Sheet({ open, onClose, title, label, headerRight, modal
|
||||
aria-modal={modal ? 'true' : undefined}
|
||||
aria-label={typeof title === 'string' ? title : label}
|
||||
tabIndex={-1}
|
||||
className={`fixed inset-x-0 bottom-0 z-50 flex max-h-[72vh] flex-col rounded-t-2xl focus:outline-none border-t border-[var(--r-line)] bg-[var(--r-bar)] text-[var(--r-text)] font-sans ${
|
||||
className={`fixed inset-x-0 bottom-0 z-50 flex max-h-[72dvh] flex-col rounded-t-2xl focus:outline-none border-t border-[var(--r-line)] bg-[var(--r-bar)] text-[var(--r-text)] font-sans ${
|
||||
pane ? 'lg:inset-x-auto lg:bottom-0 lg:right-0 lg:top-12 lg:max-h-none lg:w-[var(--reader-pane,24rem)] lg:rounded-none lg:border-l lg:border-t-0' : 'sm:left-1/2 sm:right-auto sm:w-[36rem] sm:-translate-x-1/2'
|
||||
}`}
|
||||
>
|
||||
|
||||
@@ -70,7 +70,7 @@ export default function PageShell({ title, onBack, actions, active = null, maxWi
|
||||
<a href="#content" className="skip-link">Skip to content</a>
|
||||
<header className="safe-top sticky top-0 z-30 border-b border-[var(--r-line)] bg-[var(--r-bar)]">
|
||||
<div className={`mx-auto flex h-12 ${maxWidth} items-center gap-2 px-3 sm:gap-4 sm:px-4`}>
|
||||
<button type="button" onClick={goHome} className="flex shrink-0 items-center gap-2" aria-label="Bible Study home">
|
||||
<button type="button" onClick={goHome} className="-m-2 flex shrink-0 items-center gap-2 p-2" aria-label="Bible Study home">
|
||||
<img src="/logo.svg" alt="" className="h-6 w-6" />
|
||||
<span className="hidden text-sm font-medium sm:inline">Bible Study</span>
|
||||
</button>
|
||||
|
||||
@@ -16,7 +16,7 @@ export default function SuggestWordsSheet({ wordStudy }) {
|
||||
<button type="button" onClick={() => setSuggestSelection(new Set())} className="text-[var(--r-accent)] hover:underline">Select none</button>
|
||||
<span className="ml-auto text-[var(--r-sub)]">{n} selected</span>
|
||||
</div>
|
||||
<ul className="max-h-[40vh] divide-y divide-[var(--r-line)] overflow-y-auto rounded-xl border border-[var(--r-line)] px-3">
|
||||
<ul className="max-h-[40dvh] divide-y divide-[var(--r-line)] overflow-y-auto rounded-xl border border-[var(--r-line)] px-3">
|
||||
{suggestModal.words.map((w) => (
|
||||
<li key={w.strongKey}>
|
||||
<label className="flex cursor-pointer items-center gap-3 py-2.5">
|
||||
|
||||
Reference in new issue
Block a user