From 6bdcc3c2144f841510f405a1360ae39a2edfd850 Mon Sep 17 00:00:00 2001 From: Frederic Cabassut Date: Mon, 7 Sep 2026 19:08:19 +0200 Subject: [PATCH] fix(theme): map all prose colour variables to theme tokens for dark mode The typography plugin gives each prose element its own --tw-prose-* variable with a hardcoded grey default. Only body, headings, links and code were remapped to parchment tokens, so bold text (and quotes, kbd, bullets, counters, hr and table borders) kept their light-mode greys in dark mode. Bold rendered near-black on the dark surface. Map every variable to a theme token so [data-theme="dark"] flips them all, and add an e2e scenario asserting bold text in the card preview and editor computes to --text in dark mode. Fixes #86 Co-Authored-By: Claude Fable 5.1 --- src/app.css | 19 +++++++++++++++++-- tests/e2e/dark-mode.spec.ts | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/app.css b/src/app.css index 69e0366..034c861 100644 --- a/src/app.css +++ b/src/app.css @@ -88,14 +88,29 @@ body::before { to { transform: translateY(0); } } -/* Prose overrides for parchment theme */ +/* Prose overrides for parchment theme. + The typography plugin gives every element type its own --tw-prose-* variable, + each defaulting to a fixed grey. Anything not remapped here stays that grey in + dark mode (bold text was near-black on ink — see issue #86), so map them all. */ .prose { --tw-prose-body: var(--text); --tw-prose-headings: var(--text); + --tw-prose-lead: var(--text-muted); --tw-prose-links: var(--primary); + --tw-prose-bold: var(--text); + --tw-prose-counters: var(--text-muted); + --tw-prose-bullets: var(--text-muted); + --tw-prose-hr: var(--border-subtle); + --tw-prose-quotes: var(--text); + --tw-prose-quote-borders: var(--border-subtle); + --tw-prose-captions: var(--text-muted); + --tw-prose-kbd: var(--text); + --tw-prose-kbd-shadows: color-mix(in oklab, var(--text) 10%, transparent); --tw-prose-code: var(--text); - --tw-prose-pre-bg: var(--bg-surface); --tw-prose-pre-code: var(--text); + --tw-prose-pre-bg: var(--bg-surface); + --tw-prose-th-borders: var(--border-subtle); + --tw-prose-td-borders: var(--border-subtle); } .prose :where(code):not(:where([class~="not-prose"] *)) { diff --git a/tests/e2e/dark-mode.spec.ts b/tests/e2e/dark-mode.spec.ts index 2fd005a..e247f74 100644 --- a/tests/e2e/dark-mode.spec.ts +++ b/tests/e2e/dark-mode.spec.ts @@ -1,4 +1,4 @@ -import { test, expect, createNote } from './helpers/fixtures.js'; +import { test, expect, createNote, noteCard } from './helpers/fixtures.js'; test.describe.serial('Dark mode', () => { test('Scenario: Theme toggle persists selection across page reload', async ({ @@ -110,4 +110,38 @@ test.describe.serial('Dark mode', () => { await page.getByTestId('close-editor-btn').click(); }); + + test('Scenario: Bold text in notes uses the theme text colour in dark mode', async ({ + authenticatedPage: page + }) => { + // Given a note with bold content exists + await page.goto('/'); + await page.waitForLoadState('networkidle'); + await createNote(page, 'Bold Contrast Note', 'Plain then **bold words** here'); + + // And dark theme is active + await page.goto('/settings/preferences'); + await page.waitForLoadState('networkidle'); + await page.getByTestId('pref-theme-dark').click(); + await expect(page.locator('html')).toHaveAttribute('data-theme', 'dark'); + + // When viewing the note on the notes page + await page.goto('/'); + await page.waitForLoadState('networkidle'); + const preview = noteCard(page, 'Bold Contrast Note').getByTestId('note-content-preview'); + const boldInCard = preview.locator('strong'); + await expect(boldInCard).toHaveText('bold words'); + + // Then the bold text is rendered in the dark theme's text colour (--text = #ece3d3), + // not the typography plugin's hardcoded near-black + await expect(boldInCard).toHaveCSS('color', 'rgb(236, 227, 211)'); + + // And the same holds inside the editor + await noteCard(page, 'Bold Contrast Note').click(); + const boldInEditor = page.getByTestId('tiptap-editor').locator('.tiptap strong'); + await expect(boldInEditor).toHaveText('bold words'); + await expect(boldInEditor).toHaveCSS('color', 'rgb(236, 227, 211)'); + + await page.getByTestId('close-editor-btn').click(); + }); });