diff --git a/__tests__/component/Viewer.spec.ts b/__tests__/component/Viewer.spec.ts index b4c364f..02c5ee9 100644 --- a/__tests__/component/Viewer.spec.ts +++ b/__tests__/component/Viewer.spec.ts @@ -119,17 +119,31 @@ describe('Viewer.open()', () => { expect(modalProps().show).toBe(true) }) - it.each([ - ['light', true], - ['dark', false], - ['default', false], - ] as const)('gives the modal a light backdrop only for a %s themed handler', async (theme, lightBackdrop) => { - const handler = makeHandler({ id: theme, tagName: `oca-viewer-${theme}`, theme, enabled: () => true }) - const { vm, wrapper, modalProps } = mountViewer([handler]) - const f1 = makeFile() - await vm.open([f1], f1) - await wrapper.vm.$nextTick() - expect(modalProps().lightBackdrop).toBe(lightBackdrop) + describe('under the user\'s theme', () => { + afterEach(() => document.body.style.removeProperty('--background-invert-if-dark')) + + // The theme the user runs, the one a handler asks for, then whether the + // backdrop is light and whether it takes the theme's colours + it.each([ + ['light', 'light', true, false], + ['light', 'dark', false, false], + ['light', 'default', true, true], + ['light', undefined, false, false], + ['dark', 'light', true, false], + ['dark', 'dark', false, false], + ['dark', 'default', false, true], + ['dark', undefined, false, false], + ] as const)('a %s theme gives a %s themed handler a light backdrop: %s, the theme\'s colours: %s', async (userTheme, theme, lightBackdrop, followsTheme) => { + document.body.style.setProperty('--background-invert-if-dark', userTheme === 'dark' ? 'invert(100%)' : 'no') + const id = theme ?? 'unset' + const handler = makeHandler({ id, tagName: `oca-viewer-${id}`, theme, enabled: () => true }) + const { vm, wrapper, modalProps } = mountViewer([handler]) + const f1 = makeFile() + await vm.open([f1], f1) + await wrapper.vm.$nextTick() + expect(modalProps().lightBackdrop).toBe(lightBackdrop) + expect(wrapper.find('.nc-modal-stub').classes('viewer__modal--default')).toBe(followsTheme) + }) }) }) diff --git a/__tests__/component/mountViewer.ts b/__tests__/component/mountViewer.ts index 69f7efd..840f17f 100644 --- a/__tests__/component/mountViewer.ts +++ b/__tests__/component/mountViewer.ts @@ -17,9 +17,9 @@ import { registerTestHandlers } from '../factories.ts' * Minimal NcModal stub. * * It renders the default slot and the `#actions` slot so we can assert on the - * handler custom-element markup and drive the header actions. The style is - * kept, as the real modal applies it: that is how the viewer makes room for - * the sidebar. Navigation is + * handler custom-element markup and drive the header actions. The style and + * classes are kept, as the real modal applies them: that is how the viewer + * makes room for the sidebar and themes itself. Navigation is * driven from tests through `findComponent(NcModalStub).vm.$emit('next'|'previous'|'close')`. * The relevant props (`name`, `show`, `hasNext`, `hasPrevious`, `isComparing` * related flags) are declared so they can be read back via `.props()`. @@ -45,6 +45,7 @@ export const NcModalStub = defineComponent({
{ // What WCAG asks of normal text expect(contrast).toBeGreaterThanOrEqual(4.5) }) + + // The dark palette was set on the whole modal, so it reached into what a + // handler shows: a document in Text came out white on black under a + // light theme, and printed grey + test('leaves the colours of what a handler shows to the theme', async ({ page }) => { + const viewer = new ViewerPage(page) + await viewer.open('photo.jpg') + await viewer.waitForOpen() + + const text = (selector: string) => page.locator(selector).first().evaluate((element) => getComputedStyle(element).getPropertyValue('--color-main-text').trim()) + expect(await text('.viewer__modal .modal-header')).toBe('#ffffff') + expect(await text('.viewer__modal oca-viewer-image')).not.toBe('#ffffff') + }) }) diff --git a/lib/handlers.ts b/lib/handlers.ts index f6c4265..c4aa044 100644 --- a/lib/handlers.ts +++ b/lib/handlers.ts @@ -94,7 +94,8 @@ export interface IHandler { onInit?: () => Promise /** - * Viewer modal theme (one of 'dark', 'light', 'default') + * Viewer modal theme: 'dark' (the default), 'light', or 'default' to + * follow the user's theme */ theme?: 'dark' | 'light' | 'default' diff --git a/lib/views/Viewer.vue b/lib/views/Viewer.vue index d376ddc..cd0cb11 100644 --- a/lib/views/Viewer.vue +++ b/lib/views/Viewer.vue @@ -25,6 +25,7 @@ :slideshowPaused="slideshowPaused" :spreadNavigation="true" :style="{ width: isSidebarShown ? `${sidebarPosition}px` : null }" + :class="{ 'viewer__modal--default': followsTheme }" class="viewer__modal" size="full" @close="close" @@ -147,6 +148,7 @@