Skip to content

Commit 0129457

Browse files
authored
[Tests] Adds Dark mode to xtro test report (#23750)
Adds a Vibe Coded 🤖 (Yay Copilot) dark mode to xtro test report so I do not keep being blinded every time I open a report in my all dark themed environment 😎 # Dark <img width="1274" height="514" alt="image" src="https://github.com/user-attachments/assets/61252a79-cd1e-405c-aad8-08c5325070e7" /> # Light <img width="1270" height="513" alt="image" src="https://github.com/user-attachments/assets/2203f4fb-473b-4122-a1d8-e49d128364cb" />
1 parent 99eaf5f commit 0129457

File tree

1 file changed

+92
-2
lines changed

1 file changed

+92
-2
lines changed

tests/xtro-sharpie/xtro-report/Reporter.cs

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,98 @@ public static int Main (string [] args)
8989
var indexPath = Path.Combine (ReportFolder, "index.html");
9090
var log = new StreamWriter (indexPath);
9191

92-
log.WriteLine ("<html><head><title>Extrospection results</title></head>");
93-
log.WriteLine ("<body><h1>Extrospection results</h1>");
92+
#region "Setup HTML Header and styles"
93+
log.WriteLine ("<html><head><title>Extrospection results</title>"
94+
+ @"<style>
95+
:root {
96+
--bg: #fff;
97+
--fg: #222;
98+
--green: #008100;
99+
--green-light: #90EE90;
100+
--red: #FF0200;
101+
--red-light: #FA8072;
102+
--yellow: #FFA502;
103+
--yellow-light: #FFDAB9;
104+
--grey: #e0e0e0;
105+
--switch-bg: #ccc;
106+
--switch-knob: #fff;
107+
}
108+
body.dark {
109+
--bg: #181a1b;
110+
--fg: #f1f1f1;
111+
--green: #388e3c;
112+
--green-light: #23422a;
113+
--red: #e57373;
114+
--red-light: #3a2323;
115+
--yellow: #ffd54f;
116+
--yellow-light: #4a3a1a;
117+
--grey: #23272a;
118+
--switch-bg: #555 !important;
119+
--switch-knob: #f1f1f1 !important;
120+
}
121+
body { background: var(--bg); color: var(--fg); transition: background 0.2s, color 0.2s; }
122+
.switch-container { position: absolute; top: 16px; right: 24px; z-index: 10; }
123+
.switch-label { cursor: pointer; font-size: 1em; user-select: none; color: var(--fg); }
124+
.switch-input { display: none; }
125+
.switch-slider { display: inline-block; width: 44px; height: 24px; background: var(--switch-bg) !important; border-radius: 12px; position: relative; vertical-align: middle; transition: background 0.2s; border: 1px solid #888; }
126+
.switch-slider:before { content: ''; position: absolute; left: 3px; top: 3px; width: 18px; height: 18px; background: var(--switch-knob) !important; border-radius: 50%; transition: left 0.2s, background 0.2s; box-shadow: 0 1px 3px #0002; border: 1px solid #888; }
127+
.switch-input:not(:checked) + .switch-slider { background: var(--switch-bg) !important; }
128+
.switch-input:checked + .switch-slider { background: #444 !important; }
129+
.switch-input:checked + .switch-slider:before { left: 23px; background: #222 !important; }
130+
.switch-label span { margin-left: 8px; }
131+
table { background: var(--bg); color: var(--fg); }
132+
td, th { color: var(--fg); }
133+
td[bgcolor='lightgreen'], th[bgcolor='lightgreen'] { background: var(--green-light) !important; color: var(--fg); }
134+
td[bgcolor='green'], th[bgcolor='green'] { background: var(--green) !important; color: #222; }
135+
td[bgcolor='red'], th[bgcolor='red'] { background: var(--red) !important; color: #222; }
136+
body.dark td[bgcolor='green'], body.dark th[bgcolor='green'] { color: #fff; }
137+
body.dark td[bgcolor='red'], body.dark th[bgcolor='red'] { color: #fff; }
138+
td[bgcolor='salmon'], th[bgcolor='salmon'] { background: var(--red-light) !important; color: var(--fg); }
139+
td[bgcolor='orange'], th[bgcolor='orange'] { background: var(--yellow) !important; color: #222; }
140+
td[bgcolor='peachpuff'], th[bgcolor='peachpuff'] { background: var(--yellow-light) !important; color: var(--fg); }
141+
td[bgcolor='lightgrey'], th[bgcolor='lightgrey'] { background: var(--grey) !important; color: var(--fg); }
142+
</style>"
143+
+ @"<script>
144+
function setMode(dark, user) {
145+
document.body.classList.toggle('dark', dark);
146+
if (user) {
147+
document.documentElement.classList.add('xtro-user');
148+
localStorage.setItem('xtro-dark', dark ? '1' : '0');
149+
}
150+
updateSwitch();
151+
}
152+
function updateSwitch() {
153+
var input = document.getElementById('xtro-dark-switch');
154+
if (!input) return;
155+
// checked state should match body.dark class
156+
input.checked = document.body.classList.contains('dark');
157+
}
158+
window.addEventListener('DOMContentLoaded', function() {
159+
var userPref = localStorage.getItem('xtro-dark');
160+
var dark = false;
161+
if (userPref === '1') dark = true;
162+
else if (userPref === '0') dark = false;
163+
else dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
164+
setMode(dark, false);
165+
var input = document.getElementById('xtro-dark-switch');
166+
if (input) input.addEventListener('change', function() { setMode(this.checked, true); });
167+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {
168+
if (!localStorage.getItem('xtro-dark')) {
169+
setMode(e.matches, false);
170+
}
171+
});
172+
});
173+
</script>"
174+
+ "</head>");
175+
log.WriteLine ("<body>"
176+
+ "<div class='switch-container'>"
177+
+ "<label class='switch-label'>"
178+
+ "<input type='checkbox' class='switch-input' id='xtro-dark-switch'>"
179+
+ "<span class='switch-slider'></span>"
180+
+ "<span>Dark Mode</span>"
181+
+ "</label></div>"
182+
+ "<h1>Extrospection results</h1>");
183+
#endregion "Setup HTML Header and styles"
94184

95185
log.WriteLine ("<table border='0' cellpadding='4' cellspacing='0'>");
96186

0 commit comments

Comments
 (0)