mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 10:51:36 -04:00
files: readable text previews in dark themes (#697)
* files: readable text previews in dark themes A same-origin text document inherits the page's color-scheme, so dark themes rendered the browser's default light text on the preview's forced white background. Force a light color-scheme on the preview iframe so text is always black on white. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * files: text previews follow the theme Instead of pinning the preview iframe to a light scheme, follow the theme: dark, night, and amber render the document light-on-dark against the theme's panel color; light stays black-on-white. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
f1270b4e6c
commit
9b8ebdc9b3
2 changed files with 50 additions and 4 deletions
|
|
@ -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}) {
|
|||
<iframe title='textModal' src={url}
|
||||
style={{
|
||||
height: '100%', width: '100%', border: 'none',
|
||||
// Use white to avoid iframe displaying with dark-theme.
|
||||
backgroundColor: '#ffffff',
|
||||
// A same-origin document has no styles of its own; it renders with the
|
||||
// browser's default stylesheet for whatever color-scheme this element
|
||||
// declares. Pin the scheme to the theme so text is light-on-dark under
|
||||
// the dark themes and black-on-white under light, never white-on-white.
|
||||
backgroundColor: isDark ? 'var(--panel)' : '#ffffff',
|
||||
colorScheme: isDark ? 'dark' : 'light',
|
||||
}}/>
|
||||
</div>
|
||||
</MediaGate>
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
<ThemeContext.Provider value={{isDark, mediaFilterEnabled: false}}>
|
||||
<IframePreview url='/media/config/wrolpi.yaml'/>
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
|
||||
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)');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue