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
@@ -0,0 +1,12 @@
|
||||
// Swiping sideways on the reading page turns the chapter. It shouldn't when the finger is on something that has its
|
||||
// own sideways gesture: a sheet, a form field, or a row that scrolls sideways.
|
||||
const OWN_GESTURE = 'input, textarea, select, [role="dialog"], [role="slider"], [data-no-swipe]';
|
||||
|
||||
export function swipeAllowedFrom(target) {
|
||||
if (!target?.closest) return true;
|
||||
if (target.closest(OWN_GESTURE)) return false;
|
||||
for (let el = target; el && el !== document.body; el = el.parentElement) {
|
||||
if (el.scrollWidth > el.clientWidth + 1 && /(auto|scroll)/.test(getComputedStyle(el).overflowX)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { afterEach, expect, test } from 'vitest';
|
||||
import { swipeAllowedFrom } from './swipe.js';
|
||||
|
||||
afterEach(() => { document.body.innerHTML = ''; });
|
||||
const mount = (html) => { document.body.innerHTML = html; return document.body.firstElementChild; };
|
||||
|
||||
test('swiping on plain text is allowed', () => {
|
||||
const root = mount('<div><p id="t">verse</p></div>');
|
||||
expect(swipeAllowedFrom(root.querySelector('#t'))).toBe(true);
|
||||
expect(swipeAllowedFrom(null)).toBe(true);
|
||||
});
|
||||
|
||||
test('sheets, fields and sliders keep their own sideways gestures', () => {
|
||||
const root = mount('<div><div role="dialog"><button id="a">x</button></div><input id="b"><div data-no-swipe><span id="c"></span></div></div>');
|
||||
expect(swipeAllowedFrom(root.querySelector('#a'))).toBe(false);
|
||||
expect(swipeAllowedFrom(root.querySelector('#b'))).toBe(false);
|
||||
expect(swipeAllowedFrom(root.querySelector('#c'))).toBe(false);
|
||||
});
|
||||
|
||||
test('a row that scrolls sideways is left alone', () => {
|
||||
const root = mount('<div id="row" style="overflow-x:auto"><span id="s"></span></div>');
|
||||
const row = root;
|
||||
Object.defineProperty(row, 'scrollWidth', { value: 500, configurable: true });
|
||||
Object.defineProperty(row, 'clientWidth', { value: 200, configurable: true });
|
||||
expect(swipeAllowedFrom(row.querySelector('#s'))).toBe(false);
|
||||
});
|
||||
Reference in new issue
Block a user