fix(reader): stop footer progress info painting a stray focus ring (#4397) (#4418)

The always-on page-info footer (`.progressinfo`) is a decorative
`role='presentation'` element, but it carried `tabIndex={-1}`, which made
it focusable. On Android, long-pressing the footer focused the div and the
WebView painted its default focus ring (`outline: auto`). Because the
element is pinned `absolute bottom-0` at book-view width, the ring rendered
as a content-column-wide line across the bottom of every page and persisted
until focus cleared.

Remove the `tabIndex` so the decorative element can no longer receive
focus. The `onClick` (tap-to-cycle progress mode / dismiss popup) still
fires regardless of tabindex, nothing focuses it programmatically, and the
translated `aria-label` keeps it exposed to screen readers unchanged.

Closes #4397

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Huang Xin
2026-06-02 22:08:41 +08:00
committed by GitHub
parent 7283a8ac21
commit 4abbc0254c
2 changed files with 23 additions and 1 deletions
@@ -178,3 +178,26 @@ describe('ProgressBar — fixed-layout remaining pages', () => {
);
});
});
describe('ProgressBar — decorative footer is not focusable', () => {
it('does not make the progress info container focusable (no stray focus ring)', () => {
// The footer info is a decorative role="presentation" element. A negative
// tabindex made it focusable, so long-pressing it on Android focused the
// div and the WebView painted its default focus ring as a persistent line
// across the bottom of the page (issue #4397). A decorative element must
// not be focusable so it can never receive a focus ring.
currentViewSettings = {
...baseSettings,
progressInfoMode: 'all',
} as ViewSettings;
currentProgress = makeProgress(2, 5);
currentBookData = { isFixedLayout: false };
currentRenderer = { page: 1, pages: 4 };
const { container } = renderProgressBar();
const progressInfo = container.querySelector('.progressinfo');
expect(progressInfo).not.toBeNull();
expect(progressInfo!.hasAttribute('tabindex')).toBe(false);
});
});
@@ -188,7 +188,6 @@ const ProgressBar: React.FC<ProgressBarProps> = ({
return (
<div
role='presentation'
tabIndex={-1}
className={clsx(
'progressinfo absolute bottom-0 flex items-center justify-between font-sans',
isEink ? 'text-sm font-normal' : 'text-neutral-content text-xs font-extralight',