Skip to content

Commit e60ea55

Browse files
committed
Add color handling for dark mode
1 parent 18c9ec4 commit e60ea55

File tree

11 files changed

+234
-69
lines changed

11 files changed

+234
-69
lines changed

ts/a11y/complexity/collapse.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ export class Collapse {
599599
),
600600
},
601601
[
602-
factory.create('mtext', { mathcolor: 'blue', ...variant }, [
602+
factory.create('mtext', variant, [
603603
(factory.create('text') as TextNode).setText(marker),
604604
]),
605605
]

ts/a11y/explorer.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,21 @@ export function ExplorerMathDocumentMixin<
418418
display: 'inline-flex',
419419
'align-items': 'center',
420420
},
421+
'@media (prefers-color-scheme: dark) /* explorer */': {
422+
'mjx-help > svg': {
423+
stroke: '#E0E0E0',
424+
},
425+
'mjx-help > svg > circle': {
426+
fill: '#404040',
427+
},
428+
'mjx-help > svg > circle:nth-child(2)': {
429+
fill: 'rgba(132, 132, 255, .3)',
430+
},
431+
'mjx-help:hover > svg > circle:nth-child(2)': {
432+
stroke: '#AAAAAA',
433+
fill: '#404040',
434+
},
435+
}
421436
};
422437

423438
/**

ts/a11y/explorer/Highlighter.ts

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,9 @@
2121
interface NamedColor {
2222
color: string;
2323
alpha?: number;
24+
type?: string;
2425
}
2526

26-
interface ChannelColor {
27-
red: number;
28-
green: number;
29-
blue: number;
30-
alpha?: number;
31-
}
32-
33-
const namedColors: { [key: string]: ChannelColor } = {
34-
red: { red: 255, green: 0, blue: 0 },
35-
green: { red: 0, green: 255, blue: 0 },
36-
blue: { red: 0, green: 0, blue: 255 },
37-
yellow: { red: 255, green: 255, blue: 0 },
38-
cyan: { red: 0, green: 255, blue: 255 },
39-
magenta: { red: 255, green: 0, blue: 255 },
40-
white: { red: 255, green: 255, blue: 255 },
41-
black: { red: 0, green: 0, blue: 0 },
42-
};
43-
4427
/**
4528
* Turns a named color into a channel color.
4629
*
@@ -49,30 +32,22 @@ const namedColors: { [key: string]: ChannelColor } = {
4932
* @returns {string} The channel color.
5033
*/
5134
function getColorString(color: NamedColor, deflt: NamedColor): string {
52-
const channel = namedColors[color.color] || namedColors[deflt.color];
53-
channel.alpha = color.alpha ?? deflt.alpha;
54-
return rgba(channel);
55-
}
56-
57-
/**
58-
* RGBa string version of the channel color.
59-
*
60-
* @param {ChannelColor} color The channel color.
61-
* @returns {string} The color in RGBa format.
62-
*/
63-
function rgba(color: ChannelColor): string {
64-
return `rgba(${color.red},${color.green},${color.blue},${color.alpha ?? 1})`;
35+
const type = deflt.type;
36+
const name = color.color ?? deflt.color;
37+
const opacity = color.alpha ?? deflt.alpha;
38+
const alpha = opacity === 1 ? 1 : `var(--mjx-${type}-alpha)`;
39+
return `rgba(var(--mjx-${type}-${name}), ${alpha})`;
6540
}
6641

6742
/**
6843
* The default background color if a none existing color is provided.
6944
*/
70-
const DEFAULT_BACKGROUND: NamedColor = { color: 'blue', alpha: 1 };
45+
const DEFAULT_BACKGROUND: NamedColor = { color: 'blue', alpha: 1, type: 'bg' };
7146

7247
/**
7348
* The default color if a none existing color is provided.
7449
*/
75-
const DEFAULT_FOREGROUND: NamedColor = { color: 'black', alpha: 1 };
50+
const DEFAULT_FOREGROUND: NamedColor = { color: 'black', alpha: 1, type: 'fg' };
7651

7752
export interface Highlighter {
7853
/**

ts/a11y/explorer/Region.ts

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,6 @@ export abstract class AbstractRegion<T> implements Region<T> {
7373
*/
7474
protected static className: string;
7575

76-
/**
77-
* True if the style has already been added to the document.
78-
*
79-
* @type {boolean}
80-
*/
81-
protected static styleAdded: boolean = false;
82-
8376
/**
8477
* The CSS style that needs to be added for this type of region.
8578
*
@@ -117,20 +110,24 @@ export abstract class AbstractRegion<T> implements Region<T> {
117110
this.AddStyles();
118111
}
119112

113+
/**
114+
* @returns {string} The stylesheet ID
115+
*/
116+
public static get sheetId(): string {
117+
return 'MJX-' + this.name + '-styles';
118+
}
119+
120120
/**
121121
* @override
122122
*/
123123
public AddStyles() {
124-
if (this.CLASS.styleAdded) {
124+
const id = this.CLASS.sheetId;
125+
if (!this.CLASS.style || this.document.adaptor.head().querySelector('#' + id)) {
125126
return;
126127
}
127-
// TODO: should that be added to document.documentStyleSheet()?
128-
const node = this.document.adaptor.node('style');
128+
const node = this.document.adaptor.node('style', {id});
129129
node.innerHTML = this.CLASS.style.cssText;
130-
this.document.adaptor
131-
.head(this.document.adaptor.document)
132-
.appendChild(node);
133-
this.CLASS.styleAdded = true;
130+
this.document.adaptor.head().appendChild(node);
134131
}
135132

136133
/**
@@ -177,7 +174,7 @@ export abstract class AbstractRegion<T> implements Region<T> {
177174
*/
178175
public Hide() {
179176
if (!this.div) return;
180-
this.div.parentNode.removeChild(this.div);
177+
this.div.remove();
181178
this.div = null;
182179
this.inner = null;
183180
}
@@ -335,6 +332,13 @@ export class ToolTip extends StringRegion {
335332
'border-radius': 'inherit',
336333
padding: '0 2px',
337334
},
335+
'@media (prefers-color-scheme: dark)': {
336+
['.' + ToolTip.className]: {
337+
'background-color': '#222025',
338+
'box-shadow': '0px 5px 20px #000',
339+
border: '1px solid #7C7C7C',
340+
},
341+
},
338342
});
339343
}
340344

@@ -348,6 +352,43 @@ export class LiveRegion extends StringRegion {
348352
* @override
349353
*/
350354
protected static style: StyleJsonSheet = new StyleJsonSheet({
355+
':root': {
356+
'--mjx-fg-red': '255, 0, 0',
357+
'--mjx-fg-green': '0, 255, 0',
358+
'--mjx-fg-blue': '0, 0, 255',
359+
'--mjx-fg-yellow': '255, 255, 0',
360+
'--mjx-fg-cyan': '0, 255, 255',
361+
'--mjx-fg-magenta': '255, 0, 255',
362+
'--mjx-fg-white': '255, 255, 255',
363+
'--mjx-fg-black': '0, 0, 0',
364+
'--mjx-bg-red': '255, 0, 0',
365+
'--mjx-bg-green': '0, 255, 0',
366+
'--mjx-bg-blue': '0, 0, 255',
367+
'--mjx-bg-yellow': '255, 255, 0',
368+
'--mjx-bg-cyan': '0, 255, 255',
369+
'--mjx-bg-magenta': '255, 0, 255',
370+
'--mjx-bg-white': '255, 255, 255',
371+
'--mjx-bg-black': '0, 0, 0',
372+
'--mjx-live-bg-color': 'white',
373+
'--mjx-live-shadow-color': '#888',
374+
'--mjx-live-border-color': '#CCCCCC',
375+
'--mjx-bg-alpha': 0.2,
376+
'--mjx-fg-alpha': 1,
377+
},
378+
'@media (prefers-color-scheme: dark)': {
379+
':root': {
380+
'--mjx-bg-blue': '132, 132, 255',
381+
'--mjx-bg-white': '0, 0, 0',
382+
'--mjx-bg-black': '255, 255, 255',
383+
'--mjx-fg-white': '0, 0, 0',
384+
'--mjx-fg-black': '255, 255, 255',
385+
'--mjx-live-bg-color': '#222025',
386+
'--mjx-live-shadow-color': 'black',
387+
'--mjx-live-border-color': '#7C7C7C',
388+
'--mjx-bg-alpha': 0.3,
389+
'--mjx-fg-alpha': 1,
390+
},
391+
},
351392
['.' + LiveRegion.className]: {
352393
position: 'absolute',
353394
top: 0,
@@ -360,20 +401,36 @@ export class LiveRegion extends StringRegion {
360401
left: 0,
361402
right: 0,
362403
margin: '0 auto',
363-
'background-color': 'white',
364-
'box-shadow': '0px 5px 20px #888',
365-
border: '2px solid #CCCCCC',
404+
'background-color': 'var(--mjx-live-bg-color)',
405+
'box-shadow': '0px 5px 20px var(--mjx-live-shadow-color)',
406+
border: '2px solid var(--mjx-live-border-color)',
366407
},
367408
['.' + LiveRegion.className + '_Show']: {
368409
display: 'block',
369410
},
370411
});
412+
413+
/**
414+
* @param {string} type The type of alpha to set (fg or bg)
415+
* @param {number} alpha The alpha value to use for the background
416+
* @param {Document} document The document whose CSS styles are to be adjusted
417+
*/
418+
public static setAlpha(type: string, alpha: number, document: Document) {
419+
const style = document.head.querySelector('#' + this.sheetId) as HTMLStyleElement;
420+
if (style) {
421+
const name = `--mjx-${type}-alpha`;
422+
(style.sheet.cssRules[0] as any).style.setProperty(name, alpha);
423+
(style.sheet.cssRules[1] as any).cssRules[0].style.setProperty(name, alpha ** 0.7071);
424+
}
425+
}
371426
}
372427

373428
/**
374429
* Region class that enables auto voicing of content via SSML markup.
375430
*/
376431
export class SpeechRegion extends LiveRegion {
432+
protected static style: StyleJsonSheet = null;
433+
377434
/**
378435
* Flag to activate auto voicing.
379436
*/
@@ -583,6 +640,13 @@ export class HoverRegion extends AbstractRegion<HTMLElement> {
583640
['.' + HoverRegion.className + ' > div']: {
584641
overflow: 'hidden',
585642
},
643+
'@media (prefers-color-scheme: dark)': {
644+
['.' + HoverRegion.className]: {
645+
'background-color': '#222025',
646+
'box-shadow': '0px 5px 20px #000',
647+
border: '1px solid #7C7C7C',
648+
},
649+
},
586650
});
587651

588652
/**

ts/output/chtml.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,15 @@ export class CHTML<N, T, D> extends CommonOutputJax<
151151

152152
'mjx-container [inline-breaks]': { display: 'inline' },
153153

154+
'mjx-container .mjx-selected': {
155+
outline: '2px solid black',
156+
},
157+
'@media (prefers-color-scheme: dark)': {
158+
'mjx-container .mjx-selected': {
159+
outline: '2px solid #C8C8C8',
160+
},
161+
},
162+
154163
//
155164
// These don't have Wrapper subclasses, so add their styles here
156165
//

ts/output/chtml/Wrappers/maction.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,25 @@ export const ChtmlMaction = (function <N, T, D>(): ChtmlMactionClass<N, T, D> {
188188
'background-color': '#F8F8F8',
189189
color: 'black',
190190
},
191+
'mjx-maction[data-collapsible][toggle="1"]': {
192+
color: '#55F',
193+
},
194+
195+
'@media (prefers-color-scheme: dark) /* chtml maction */': {
196+
'mjx-tool > mjx-tip': {
197+
border: '1px solid #888',
198+
'background-color': '#303030',
199+
color: '#E0E0E0',
200+
'box-shadow': '2px 2px 5px #000',
201+
},
202+
'mjx-status': {
203+
'background-color': '#303030',
204+
color: '#E0E0E0',
205+
},
206+
'mjx-maction[data-collapsible][toggle="1"]': {
207+
color: '#88F',
208+
},
209+
},
191210
};
192211

193212
/**

ts/output/svg.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,14 @@ export class SVG<N, T, D> extends CommonOutputJax<
114114
stroke: 'black',
115115
'stroke-width': '80px',
116116
},
117+
'@media (prefers-color-scheme: dark)': {
118+
[[
119+
'rect[data-sre-highlighter-added]:has(+ .mjx-selected)',
120+
'rect[data-sre-highlighter-bbox].mjx-selected',
121+
].join(', ')]: {
122+
stroke: '#C8C8C8',
123+
},
124+
},
117125
};
118126

119127
/**

ts/output/svg/Wrappers/maction.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,24 @@ export const SvgMaction = (function <N, T, D>(): SvgMactionClass<N, T, D> {
187187
'background-color': '#F8F8F8',
188188
color: 'black',
189189
},
190+
'g[data-mml-node="maction"][data-collapsible][data-toggle="1"]': {
191+
fill: '#55F',
192+
},
193+
194+
'@media (prefers-color-scheme: dark) /* svg maction */': {
195+
'mjx-tool > mjx-tip': {
196+
'background-color': '#303030',
197+
color: '#E0E0E0',
198+
'box-shadow': '2px 2px 5px #000',
199+
},
200+
'mjx-status': {
201+
'background-color': '#303030',
202+
color: '#E0E0E0',
203+
},
204+
'g[data-mml-node="maction"][data-collapsible][data-toggle="1"]': {
205+
fill: '#88F',
206+
},
207+
},
190208
};
191209

192210
/**

0 commit comments

Comments
 (0)