Skip to content

Commit dcc1ad6

Browse files
Enhance dark theme support across various components and improve color contrast for better accessibility
1 parent 43c5533 commit dcc1ad6

File tree

8 files changed

+403
-146
lines changed

8 files changed

+403
-146
lines changed

modules/gui/src/cpp/NelsonColors.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,25 @@ namespace Nelson {
1515
QColor
1616
getWarningColor()
1717
{
18-
return QColor(QColor(255, 175, 0));
18+
return isDarkPalette() ? QColor(QStringLiteral("#b78620")) : QColor(QColor(255, 175, 0));
1919
}
2020
//===================================================================================
2121
QColor
2222
getInputColor()
2323
{
24-
return isDarkPalette() ? QColor(Qt::cyan) : QColor(Qt::blue);
24+
return isDarkPalette() ? QColor(QStringLiteral("#007ACC")) : QColor(Qt::blue);
2525
}
2626
//===================================================================================
2727
QColor
2828
getErrorColor()
2929
{
30-
return { Qt::red };
30+
return isDarkPalette() ? QColor(QStringLiteral("#f44747")) : QColor(Qt::red);
3131
}
3232
//===================================================================================
3333
QColor
3434
getOutputColor()
3535
{
36-
return isDarkPalette() ? QColor(Qt::white) : QColor(Qt::black);
36+
return isDarkPalette() ? QColor(QStringLiteral("#D4D4D4")) : QColor(Qt::black);
3737
}
3838
//===================================================================================
3939
}

modules/help_tools/resources/highlight.css

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,5 +114,115 @@ code.hljs {
114114
.hljs-punctuation,
115115
.hljs-tag {
116116
/* purposely ignored */
117-
117+
/* keep rule non-empty so linters don't flag it; inherit default color */
118+
color: inherit;
119+
}
120+
121+
/* Dark theme overrides: ensure readable colors when user prefers dark color scheme */
122+
@media (prefers-color-scheme: dark) {
123+
/* background and default text */
124+
.hljs {
125+
color: #cbd5e1; /* light gray-blue */
126+
background: #0b1220; /* near black-blue */
127+
}
128+
129+
/* keywords, types, and important tokens */
130+
.hljs-doctag,
131+
.hljs-keyword,
132+
.hljs-meta .hljs-keyword,
133+
.hljs-template-tag,
134+
.hljs-template-variable,
135+
.hljs-type,
136+
.hljs-variable.language_ {
137+
color: #ff7b72; /* warm red for contrast */
138+
}
139+
140+
.hljs-title,
141+
.hljs-title.class_,
142+
.hljs-title.class_.inherited__,
143+
.hljs-title.function_ {
144+
color: #c4b5fd; /* soft purple */
145+
}
146+
147+
.hljs-attr,
148+
.hljs-attribute,
149+
.hljs-literal,
150+
.hljs-meta,
151+
.hljs-number,
152+
.hljs-operator,
153+
.hljs-variable,
154+
.hljs-selector-attr,
155+
.hljs-selector-class,
156+
.hljs-selector-id {
157+
color: #93c5fd; /* light blue */
158+
}
159+
160+
.hljs-regexp,
161+
.hljs-string,
162+
.hljs-meta .hljs-string {
163+
color: #9ae6b4; /* greenish for strings */
164+
}
165+
166+
.hljs-built_in,
167+
.hljs-symbol {
168+
color: #f6bd61; /* amber-ish */
169+
}
170+
171+
.hljs-comment,
172+
.hljs-code,
173+
.hljs-formula {
174+
color: #7c8798; /* muted comment color */
175+
}
176+
177+
.hljs-name,
178+
.hljs-quote,
179+
.hljs-selector-tag,
180+
.hljs-selector-pseudo {
181+
color: #86efac; /* mint-ish */
182+
}
183+
184+
.hljs-subst {
185+
color: #cbd5e1;
186+
}
187+
188+
.hljs-section {
189+
color: #93c5fd;
190+
font-weight: bold;
191+
}
192+
193+
.hljs-bullet {
194+
color: #fbbf24;
195+
}
196+
197+
.hljs-emphasis {
198+
color: #cbd5e1;
199+
font-style: italic;
200+
}
201+
202+
.hljs-strong {
203+
color: #cbd5e1;
204+
font-weight: bold;
205+
}
206+
207+
.hljs-addition {
208+
color: #a7f3d0;
209+
background-color: rgba(16,185,129,0.06);
210+
}
211+
212+
.hljs-deletion {
213+
color: #fecaca;
214+
background-color: rgba(239,68,68,0.06);
215+
}
216+
217+
/* Ensure code blocks and inline code have adequate contrast and padding */
218+
pre code.hljs {
219+
background: transparent;
220+
color: inherit;
221+
}
222+
223+
code.hljs {
224+
background: rgba(255,255,255,0.02);
225+
padding: 3px 6px;
226+
border-radius: 4px;
227+
}
118228
}

modules/help_tools/resources/nelson_help.js

Lines changed: 83 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,21 @@
5050
if (window.MathJax && window.MathJax.tex) return;
5151
window.MathJax = {
5252
tex: {
53-
inlineMath: [['$','$'], ['\\(','\\)']],
54-
displayMath: [['$$','$$'], ['\\[','\\]']],
53+
inlineMath: [
54+
["$", "$"],
55+
["\\(", "\\)"],
56+
],
57+
displayMath: [
58+
["$$", "$$"],
59+
["\\[", "\\]"],
60+
],
5561
processEscapes: true,
56-
processEnvironments: true
62+
processEnvironments: true,
5763
},
5864
options: {
5965
// avoid processing inside <pre> / <code> etc.
60-
skipHtmlTags: ['script','noscript','style','textarea','pre']
61-
}
66+
skipHtmlTags: ["script", "noscript", "style", "textarea", "pre"],
67+
},
6268
};
6369
} catch (e) {
6470
/* ignore */
@@ -69,14 +75,23 @@
6975
function loadMathJax() {
7076
try {
7177
// If MathJax v3 already present, typeset now
72-
if (window.MathJax && typeof window.MathJax.typesetPromise === 'function') {
73-
window.MathJax.typesetPromise().catch(function(){/*ignore*/});
78+
if (
79+
window.MathJax &&
80+
typeof window.MathJax.typesetPromise === "function"
81+
) {
82+
window.MathJax.typesetPromise().catch(function () {
83+
/*ignore*/
84+
});
7485
// ensure math rendered (fallback if needed)
7586
ensureMathRendered();
7687
return;
7788
}
7889
// If MathJax v2 present, request a typeset using v2 API and return
79-
if (window.MathJax && window.MathJax.Hub && typeof window.MathJax.Hub.Queue === 'function') {
90+
if (
91+
window.MathJax &&
92+
window.MathJax.Hub &&
93+
typeof window.MathJax.Hub.Queue === "function"
94+
) {
8095
window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub]);
8196
// ensure math rendered (fallback if needed)
8297
ensureMathRendered();
@@ -90,24 +105,44 @@
90105

91106
function onLoad() {
92107
try {
93-
if (window.MathJax && typeof window.MathJax.typesetPromise === "function") {
94-
window.MathJax.typesetPromise().catch(function(){/*ignore*/}).then(function(){ ensureMathRendered(); });
95-
} else if (window.MathJax && window.MathJax.Hub && typeof window.MathJax.Hub.Queue === "function") {
108+
if (
109+
window.MathJax &&
110+
typeof window.MathJax.typesetPromise === "function"
111+
) {
112+
window.MathJax.typesetPromise()
113+
.catch(function () {
114+
/*ignore*/
115+
})
116+
.then(function () {
117+
ensureMathRendered();
118+
});
119+
} else if (
120+
window.MathJax &&
121+
window.MathJax.Hub &&
122+
typeof window.MathJax.Hub.Queue === "function"
123+
) {
96124
window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub]);
97125
// small delay then check
98126
setTimeout(ensureMathRendered, 50);
99127
} else {
100128
// in case MathJax not available, still try fallback after short delay
101129
setTimeout(ensureMathRendered, 50);
102130
}
103-
} catch (_) { /* ignore */ }
131+
} catch (_) {
132+
/* ignore */
133+
}
104134
}
105135

106136
// Try CDN first (avoids file:/// resolution of sub-resources), fall back to local if CDN fails.
107-
createAndAppendScript(cdn, { crossorigin: "anonymous" }, onLoad, function () {
108-
// CDN failed -> try local copy
109-
createAndAppendScript(local, null, onLoad);
110-
});
137+
createAndAppendScript(
138+
cdn,
139+
{ crossorigin: "anonymous" },
140+
onLoad,
141+
function () {
142+
// CDN failed -> try local copy
143+
createAndAppendScript(local, null, onLoad);
144+
},
145+
);
111146
} catch (e) {
112147
/* ignore */
113148
}
@@ -118,39 +153,61 @@
118153
function ensureMathRendered() {
119154
try {
120155
// If MathJax v3 present, typeset now and return
121-
if (window.MathJax && typeof window.MathJax.typesetPromise === "function") {
156+
if (
157+
window.MathJax &&
158+
typeof window.MathJax.typesetPromise === "function"
159+
) {
122160
// typesetPromise will render math in the page; call it anyway
123-
window.MathJax.typesetPromise().catch(function(){/*ignore*/});
161+
window.MathJax.typesetPromise().catch(function () {
162+
/*ignore*/
163+
});
124164
return;
125165
}
126166
// If MathJax v2 present, queue a typeset
127-
if (window.MathJax && window.MathJax.Hub && typeof window.MathJax.Hub.Queue === "function") {
167+
if (
168+
window.MathJax &&
169+
window.MathJax.Hub &&
170+
typeof window.MathJax.Hub.Queue === "function"
171+
) {
128172
window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub]);
129173
return;
130174
}
131175

132176
// No MathJax available yet: still attempt to convert <script type="math/tex"> to $$...$$
133-
var scripts = Array.prototype.slice.call(document.querySelectorAll('script[type^="math/tex"]'));
177+
var scripts = Array.prototype.slice.call(
178+
document.querySelectorAll('script[type^="math/tex"]'),
179+
);
134180
if (!scripts || scripts.length === 0) return;
135181
var replaced = false;
136182
scripts.forEach(function (s) {
137183
try {
138184
// skip if already replaced
139-
if (s.getAttribute && s.getAttribute("data-math-processed") === "1") return;
185+
if (s.getAttribute && s.getAttribute("data-math-processed") === "1")
186+
return;
140187
var tex = s.textContent || s.innerText || "";
141188
if (!tex) return;
142189
var span = document.createElement("span");
143190
// display-mode math: use $$...$$
144191
span.textContent = "$$" + tex + "$$";
145192
s.parentNode.replaceChild(span, s);
146193
replaced = true;
147-
} catch (_) { /* ignore */ }
194+
} catch (_) {
195+
/* ignore */
196+
}
148197
});
149198
// If we replaced content and MathJax loads later it will find $$...$$; try to typeset now too
150-
if (replaced && window.MathJax && typeof window.MathJax.typesetPromise === "function") {
151-
window.MathJax.typesetPromise().catch(function(){/*ignore*/});
199+
if (
200+
replaced &&
201+
window.MathJax &&
202+
typeof window.MathJax.typesetPromise === "function"
203+
) {
204+
window.MathJax.typesetPromise().catch(function () {
205+
/*ignore*/
206+
});
152207
}
153-
} catch (_) { /* ignore */ }
208+
} catch (_) {
209+
/* ignore */
210+
}
154211
}
155212

156213
// Try to load local highlight.js, fallback to CDN. When loaded, run highlight and also attach DOMContentLoaded safeguard.
@@ -379,5 +436,5 @@
379436
loadHighlightJS();
380437
} catch (_) {}
381438

382-
// End IIFE
439+
// End IIFE
383440
})();

modules/help_tools/resources/nelson_html.xslt

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,25 @@
1515

1616
<xsl:template match="/">
1717
<!-- Nelson Documentation XSLT Stylesheet -->
18-
<html lang="en">
18+
<html>
19+
<xsl:attribute name="lang">
20+
<xsl:choose>
21+
<!-- en_US or zh_CN style -->
22+
<xsl:when test="contains(xmldoc/language, '_')">
23+
<xsl:value-of select="substring-before(xmldoc/language, '_')"/>
24+
</xsl:when>
25+
<!-- en-US style -->
26+
<xsl:when test="contains(xmldoc/language, '-')">
27+
<xsl:value-of select="substring-before(xmldoc/language, '-')"/>
28+
</xsl:when>
29+
<!-- bare language code like "en" or "fr" -->
30+
<xsl:when test="normalize-space(xmldoc/language)">
31+
<xsl:value-of select="xmldoc/language"/>
32+
</xsl:when>
33+
<!-- default -->
34+
<xsl:otherwise>en</xsl:otherwise>
35+
</xsl:choose>
36+
</xsl:attribute>
1937
<head>
2038
<title>
2139
<xsl:choose>
@@ -31,6 +49,19 @@
3149
<link rel="stylesheet" href="highlight.css"/>
3250
<link rel="stylesheet" href="nelson_common.css"/>
3351
<script src="nelson_help.js"></script>
52+
53+
<!-- Add dark/light prefers-color-scheme rules to make chapter descriptions readable on both themes -->
54+
<style>
55+
@media (prefers-color-scheme: dark) {
56+
/* target both class names used in different XSLT outputs */
57+
.chapter-description, .chapter-desc { color: #e6eef8 !important; }
58+
.chapter-description p, .chapter-desc p { color: inherit !important; }
59+
}
60+
@media (prefers-color-scheme: light) {
61+
.chapter-description, .chapter-desc { color: #444 !important; }
62+
.chapter-description p, .chapter-desc p { color: inherit !important; }
63+
}
64+
</style>
3465
</head>
3566
<body>
3667
<!-- Help Summary Button at top left -->
@@ -201,7 +232,8 @@
201232
</div>
202233
</xsl:when>
203234
<xsl:when test="name() = 'chapter_description'">
204-
<div class="subtitle" style="padding-left:32px;">
235+
<!-- add specific class for targeted styling -->
236+
<div class="subtitle chapter-description" style="padding-left:32px;">
205237
<xsl:choose>
206238
<xsl:when test="p">
207239
<xsl:for-each select="p">

0 commit comments

Comments
 (0)