diff --git a/app/src/components/FilePreview.js b/app/src/components/FilePreview.js
index a9580635..c6ed6e39 100644
--- a/app/src/components/FilePreview.js
+++ b/app/src/components/FilePreview.js
@@ -100,8 +100,8 @@ function getEpubViewerURL(previewFile) {
* A component rather than part of `getIframePreviewModal` because it reads the theme: the
* modal builders are plain functions called from an event handler, where hooks cannot run.
*/
-function IframePreview({url, gatePdf}) {
- const {mediaFilterEnabled} = React.useContext(ThemeContext);
+export function IframePreview({url, gatePdf}) {
+ const {isDark, mediaFilterEnabled} = React.useContext(ThemeContext);
/*
* `gatePdf` only for PDFs. Text and the EPUB viewer are documents of our own, which the
@@ -119,8 +119,12 @@ function IframePreview({url, gatePdf}) {
diff --git a/app/src/components/FilePreview.test.js b/app/src/components/FilePreview.test.js
index 573de789..24f90479 100644
--- a/app/src/components/FilePreview.test.js
+++ b/app/src/components/FilePreview.test.js
@@ -100,3 +100,45 @@ describe('preview gate remounting (source contract)', () => {
expect(rebuild.length).toBeGreaterThan(0);
});
});
+
+describe('IframePreview color scheme', () => {
+ /*
+ * The previewed file is a bare document with no styles of its own, so it renders with the
+ * browser's default stylesheet for whatever color-scheme the iframe element declares. If
+ * the scheme does not follow the theme, one combination is always unreadable: a dark page
+ * scheme with a white iframe renders the browser's light text on white.
+ */
+ const {render} = require('@testing-library/react');
+ const {ThemeContext} = require('../contexts/contexts');
+ const {IframePreview} = require('./FilePreview');
+
+ const renderWithTheme = (isDark) => render(
+
+
+
+ );
+
+ test('dark themes render the document dark with a dark background', () => {
+ const {container} = renderWithTheme(true);
+ const iframe = container.querySelector('iframe');
+ expect(iframe.style.colorScheme).toEqual('dark');
+ });
+
+ test('the dark background is the theme panel color', () => {
+ /*
+ * Read off the source because jsdom's CSSOM drops var() declarations entirely, so a
+ * rendered iframe in jsdom cannot show the background it gets in a real browser.
+ */
+ const fs = require('fs');
+ const path = require('path');
+ const source = fs.readFileSync(path.join(__dirname, 'FilePreview.js'), 'utf8');
+ expect(source).toContain(`backgroundColor: isDark ? 'var(--panel)' : '#ffffff'`);
+ });
+
+ test('the light theme renders the document black-on-white', () => {
+ const {container} = renderWithTheme(false);
+ const iframe = container.querySelector('iframe');
+ expect(iframe.style.colorScheme).toEqual('light');
+ expect(iframe.style.backgroundColor).toEqual('rgb(255, 255, 255)');
+ });
+});