Skip to content

Commit 65fa1ed

Browse files
committed
fix(themes): address review feedback — contrast, stale CSS, syntax mode safety
1. Material light: foreground #90A4AE → #546E7A (Blue Grey 600) for readable UI text (~7:1 contrast on white). Primary-foreground #FAFAFA → #263238 for contrast on teal buttons. 2. DiffHunkPreview: add colorTheme to useEffect deps so unsafeCSS (bg/gutter injection) recomputes when themes change, preventing stale mixed-theme state in mounted tooltips during preview mode. 3. SHIKI_THEME_MAP: make mode-aware with null entries for modes lacking a shiki counterpart. resolveSyntaxTheme() returns undefined when the current mode has no match, so pierre falls back to its defaults rather than applying dark token colors on a light background (fixes Tokyo Night light).
1 parent cb9edd9 commit 65fa1ed

3 files changed

Lines changed: 39 additions & 33 deletions

File tree

packages/review-editor/components/DiffHunkPreview.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { FileDiff } from '@pierre/diffs/react';
33
import { getSingularPatch } from '@pierre/diffs';
44
import { useTheme } from '@plannotator/ui/components/ThemeProvider';
55
import { useReviewState } from '../dock/ReviewStateContext';
6-
import { SHIKI_THEME_MAP } from '../hooks/usePierreTheme';
6+
import { resolveSyntaxTheme } from '../hooks/usePierreTheme';
77

88
interface DiffHunkPreviewProps {
99
/** Raw diff hunk string (unified diff format). */
@@ -98,7 +98,7 @@ export const DiffHunkPreview: React.FC<DiffHunkPreviewProps> = ({
9898
});
9999
});
100100
return () => cancelAnimationFrame(rafId);
101-
}, [resolvedMode, state.fontFamily, state.fontSize]);
101+
}, [resolvedMode, colorTheme, state.fontFamily, state.fontSize]);
102102

103103
if (!fileDiff) {
104104
return (
@@ -119,7 +119,7 @@ export const DiffHunkPreview: React.FC<DiffHunkPreviewProps> = ({
119119
options={{
120120
themeType: pierreTheme.type,
121121
unsafeCSS: pierreTheme.css,
122-
...(SHIKI_THEME_MAP[colorTheme] && { theme: SHIKI_THEME_MAP[colorTheme] }),
122+
...(resolveSyntaxTheme(colorTheme, resolvedMode ?? 'dark') && { theme: resolveSyntaxTheme(colorTheme, resolvedMode ?? 'dark') }),
123123
diffStyle: 'unified',
124124
disableLineNumbers: true,
125125
overflow: 'wrap',

packages/review-editor/hooks/usePierreTheme.ts

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,50 @@
11
import { useState, useEffect } from 'react';
22
import { useTheme } from '@plannotator/ui/components/ThemeProvider';
33

4-
export const SHIKI_THEME_MAP: Record<string, { dark: string; light: string }> = {
5-
'andromeeda': { dark: 'andromeeda', light: 'andromeeda' },
6-
'aurora-x': { dark: 'aurora-x', light: 'aurora-x' },
7-
'ayu-dark': { dark: 'ayu-dark', light: 'ayu-dark' },
4+
export const SHIKI_THEME_MAP: Record<string, { dark: string | null; light: string | null }> = {
5+
'andromeeda': { dark: 'andromeeda', light: null },
6+
'aurora-x': { dark: 'aurora-x', light: null },
7+
'ayu-dark': { dark: 'ayu-dark', light: null },
88
'catppuccin': { dark: 'catppuccin-mocha', light: 'catppuccin-latte' },
99
'dark-plus': { dark: 'dark-plus', light: 'light-plus' },
10-
'dracula': { dark: 'dracula', light: 'dracula' },
10+
'dracula': { dark: 'dracula', light: null },
1111
'everforest': { dark: 'everforest-dark', light: 'everforest-light' },
1212
'everforest-hard': { dark: 'everforest-dark', light: 'everforest-light' },
1313
'everforest-soft': { dark: 'everforest-dark', light: 'everforest-light' },
1414
'github': { dark: 'github-dark', light: 'github-light' },
1515
'gruvbox': { dark: 'gruvbox-dark-medium', light: 'gruvbox-light-medium' },
16-
'houston': { dark: 'houston', light: 'houston' },
17-
'kanagawa-dragon': { dark: 'kanagawa-dragon', light: 'kanagawa-dragon' },
18-
'kanagawa-lotus': { dark: 'kanagawa-lotus', light: 'kanagawa-lotus' },
19-
'kanagawa-wave': { dark: 'kanagawa-wave', light: 'kanagawa-wave' },
20-
'laserwave': { dark: 'laserwave', light: 'laserwave' },
16+
'houston': { dark: 'houston', light: null },
17+
'kanagawa-dragon': { dark: 'kanagawa-dragon', light: null },
18+
'kanagawa-lotus': { dark: null, light: 'kanagawa-lotus' },
19+
'kanagawa-wave': { dark: 'kanagawa-wave', light: null },
20+
'laserwave': { dark: 'laserwave', light: null },
2121
'material': { dark: 'material-theme', light: 'material-theme-lighter' },
2222
'min': { dark: 'min-dark', light: 'min-light' },
23-
'monokai-pro': { dark: 'monokai', light: 'monokai' },
24-
'night-owl': { dark: 'night-owl', light: 'night-owl' },
25-
'nord': { dark: 'nord', light: 'nord' },
26-
'one-dark-pro': { dark: 'one-dark-pro', light: 'one-dark-pro' },
27-
'one-light': { dark: 'one-light', light: 'one-light' },
28-
'plastic': { dark: 'plastic', light: 'plastic' },
29-
'poimandres': { dark: 'poimandres', light: 'poimandres' },
30-
'red': { dark: 'red', light: 'red' },
23+
'monokai-pro': { dark: 'monokai', light: null },
24+
'night-owl': { dark: 'night-owl', light: null },
25+
'nord': { dark: 'nord', light: null },
26+
'one-dark-pro': { dark: 'one-dark-pro', light: null },
27+
'one-light': { dark: null, light: 'one-light' },
28+
'plastic': { dark: 'plastic', light: null },
29+
'poimandres': { dark: 'poimandres', light: null },
30+
'red': { dark: 'red', light: null },
3131
'rose-pine': { dark: 'rose-pine', light: 'rose-pine-dawn' },
3232
'slack': { dark: 'slack-dark', light: 'slack-ochin' },
33-
'snazzy-light': { dark: 'snazzy-light', light: 'snazzy-light' },
33+
'snazzy-light': { dark: null, light: 'snazzy-light' },
3434
'solarized': { dark: 'solarized-dark', light: 'solarized-light' },
35-
'synthwave-84': { dark: 'synthwave-84', light: 'synthwave-84' },
36-
'tokyo-night': { dark: 'tokyo-night', light: 'tokyo-night' },
37-
'vesper': { dark: 'vesper', light: 'vesper' },
35+
'synthwave-84': { dark: 'synthwave-84', light: null },
36+
'tokyo-night': { dark: 'tokyo-night', light: null },
37+
'vesper': { dark: 'vesper', light: null },
3838
'vitesse': { dark: 'vitesse-dark', light: 'vitesse-light' },
39-
'vitesse-black': { dark: 'vitesse-black', light: 'vitesse-black' },
39+
'vitesse-black': { dark: 'vitesse-black', light: null },
4040
};
4141

42+
export function resolveSyntaxTheme(colorTheme: string, mode: 'dark' | 'light'): { dark: string; light: string } | undefined {
43+
const map = SHIKI_THEME_MAP[colorTheme];
44+
if (!map || !map[mode]) return undefined;
45+
return { dark: map.dark || 'pierre-dark', light: map.light || 'pierre-light' };
46+
}
47+
4248
export interface PierreTheme {
4349
type: 'dark' | 'light';
4450
css: string;
@@ -55,8 +61,8 @@ export function usePierreTheme(options?: { fontFamily?: string; fontSize?: strin
5561
const styles = getComputedStyle(document.documentElement);
5662
const bg = styles.getPropertyValue('--background').trim();
5763
const fg = styles.getPropertyValue('--foreground').trim();
58-
if (!bg || !fg) return { type: resolvedMode ?? 'dark', css: '', syntaxTheme: SHIKI_THEME_MAP[colorTheme] };
59-
return { type: resolvedMode ?? 'dark', syntaxTheme: SHIKI_THEME_MAP[colorTheme], css: `
64+
if (!bg || !fg) return { type: resolvedMode ?? 'dark', css: '', syntaxTheme: resolveSyntaxTheme(colorTheme, resolvedMode ?? 'dark') };
65+
return { type: resolvedMode ?? 'dark', syntaxTheme: resolveSyntaxTheme(colorTheme, resolvedMode ?? 'dark'), css: `
6066
:host, [data-diff], [data-file], [data-diffs-header], [data-error-wrapper], [data-virtualizer-buffer] {
6167
--diffs-bg: ${bg} !important; --diffs-fg: ${fg} !important;
6268
--diffs-dark-bg: ${bg}; --diffs-light-bg: ${bg}; --diffs-dark: ${fg}; --diffs-light: ${fg};
@@ -82,7 +88,7 @@ export function usePierreTheme(options?: { fontFamily?: string; fontSize?: strin
8288

8389
setPierreTheme({
8490
type: resolvedMode,
85-
syntaxTheme: SHIKI_THEME_MAP[colorTheme],
91+
syntaxTheme: resolveSyntaxTheme(colorTheme, resolvedMode),
8692
css: `
8793
:host, [data-diff], [data-file], [data-diffs-header], [data-error-wrapper], [data-virtualizer-buffer] {
8894
--diffs-bg: ${bg} !important;

packages/ui/themes/material.css

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@
3434

3535
.theme-material.light {
3636
--background: #FAFAFA;
37-
--foreground: #90A4AE;
37+
--foreground: #546E7A;
3838
--card: #F0F4F5;
39-
--card-foreground: #90A4AE;
39+
--card-foreground: #546E7A;
4040
--popover: #FAFAFA;
41-
--popover-foreground: #90A4AE;
41+
--popover-foreground: #546E7A;
4242
--primary: #80CBC4;
43-
--primary-foreground: #FAFAFA;
43+
--primary-foreground: #263238;
4444
--secondary: #E8EDEF;
4545
--secondary-foreground: #758a95;
4646
--muted: #EEEEEE;

0 commit comments

Comments
 (0)