@@ -224,11 +224,44 @@ var htmlTemplate = `<!DOCTYPE html>
224224 --ld-purple: #405BFF;
225225 --ld-dark: #282828;
226226 --ld-light: #F5F5F5;
227+ --bg-primary: #F5F5F5;
228+ --bg-secondary: #FFFFFF;
229+ --text-primary: #282828;
230+ --text-secondary: #6C757D;
227231 --supported-green: #28A745;
228232 --deprecated-yellow: #FFC107;
229233 --removed-red: #DC3545;
230234 --not-supported-gray: #6C757D;
231235 --border-color: #DEE2E6;
236+ --table-header-bg: #282828;
237+ --table-header-text: #FFFFFF;
238+ --row-hover: #f8f9fa;
239+ }
240+
241+ @media (prefers-color-scheme: dark) {
242+ :root:not([data-theme="light"]) {
243+ --bg-primary: #1a1a1a;
244+ --bg-secondary: #2d2d2d;
245+ --text-primary: #e0e0e0;
246+ --text-secondary: #a0a0a0;
247+ --border-color: #404040;
248+ --table-header-bg: #1a1a1a;
249+ --table-header-text: #e0e0e0;
250+ --row-hover: #363636;
251+ --not-supported-gray: #808080;
252+ }
253+ }
254+
255+ [data-theme="dark"] {
256+ --bg-primary: #1a1a1a;
257+ --bg-secondary: #2d2d2d;
258+ --text-primary: #e0e0e0;
259+ --text-secondary: #a0a0a0;
260+ --border-color: #404040;
261+ --table-header-bg: #1a1a1a;
262+ --table-header-text: #e0e0e0;
263+ --row-hover: #363636;
264+ --not-supported-gray: #808080;
232265 }
233266
234267 * {
@@ -239,8 +272,43 @@ var htmlTemplate = `<!DOCTYPE html>
239272 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
240273 margin: 0;
241274 padding: 20px;
242- background-color: var(--ld-light);
243- color: var(--ld-dark);
275+ background-color: var(--bg-primary);
276+ color: var(--text-primary);
277+ transition: background-color 0.3s, color 0.3s;
278+ }
279+
280+ .header {
281+ display: flex;
282+ justify-content: space-between;
283+ align-items: center;
284+ margin-bottom: 10px;
285+ }
286+
287+ .header h1 {
288+ margin: 0;
289+ flex: 1;
290+ text-align: center;
291+ }
292+
293+ .theme-toggle {
294+ background: var(--bg-secondary);
295+ border: 1px solid var(--border-color);
296+ border-radius: 6px;
297+ padding: 8px 12px;
298+ cursor: pointer;
299+ font-size: 1.2em;
300+ transition: all 0.2s;
301+ display: flex;
302+ align-items: center;
303+ gap: 6px;
304+ }
305+
306+ .theme-toggle:hover {
307+ border-color: var(--ld-purple);
308+ }
309+
310+ .theme-toggle .icon {
311+ font-size: 1.1em;
244312 }
245313
246314 h1 {
@@ -251,20 +319,20 @@ var htmlTemplate = `<!DOCTYPE html>
251319
252320 .subtitle {
253321 text-align: center;
254- color: var(--not-supported-gray );
322+ color: var(--text-secondary );
255323 margin-bottom: 30px;
256324 }
257325
258326 section {
259- background: white ;
327+ background: var(--bg-secondary) ;
260328 border-radius: 8px;
261329 padding: 20px;
262330 margin-bottom: 30px;
263331 box-shadow: 0 2px 4px rgba(0,0,0,0.1);
264332 }
265333
266334 h2 {
267- color: var(--ld-dark );
335+ color: var(--text-primary );
268336 border-bottom: 2px solid var(--ld-purple);
269337 padding-bottom: 10px;
270338 margin-top: 0;
@@ -276,7 +344,7 @@ var htmlTemplate = `<!DOCTYPE html>
276344 gap: 10px;
277345 margin-bottom: 20px;
278346 padding: 15px;
279- background-color: var(--ld-light );
347+ background-color: var(--bg-primary );
280348 border-radius: 6px;
281349 }
282350
@@ -285,7 +353,7 @@ var htmlTemplate = `<!DOCTYPE html>
285353 align-items: center;
286354 gap: 5px;
287355 padding: 8px 12px;
288- background: white ;
356+ background: var(--bg-secondary) ;
289357 border: 1px solid var(--border-color);
290358 border-radius: 4px;
291359 cursor: pointer;
@@ -314,7 +382,7 @@ var htmlTemplate = `<!DOCTYPE html>
314382 .selection-info {
315383 width: 100%;
316384 font-size: 0.9em;
317- color: var(--not-supported-gray );
385+ color: var(--text-secondary );
318386 margin-top: 5px;
319387 }
320388
@@ -335,8 +403,8 @@ var htmlTemplate = `<!DOCTYPE html>
335403 }
336404
337405 th {
338- background-color: var(--ld-dark );
339- color: white ;
406+ background-color: var(--table-header-bg );
407+ color: var(--table-header-text) ;
340408 font-weight: 600;
341409 position: sticky;
342410 top: 0;
@@ -351,7 +419,7 @@ var htmlTemplate = `<!DOCTYPE html>
351419 }
352420
353421 tr:hover {
354- background-color: #f8f9fa ;
422+ background-color: var(--row-hover) ;
355423 }
356424
357425 .feature-name {
@@ -360,7 +428,7 @@ var htmlTemplate = `<!DOCTYPE html>
360428
361429 .feature-description {
362430 font-size: 0.85em;
363- color: var(--not-supported-gray );
431+ color: var(--text-secondary );
364432 margin-top: 4px;
365433 }
366434
@@ -407,7 +475,7 @@ var htmlTemplate = `<!DOCTYPE html>
407475 .no-selection {
408476 text-align: center;
409477 padding: 40px;
410- color: var(--not-supported-gray );
478+ color: var(--text-secondary );
411479 }
412480
413481 @media (max-width: 768px) {
@@ -424,11 +492,26 @@ var htmlTemplate = `<!DOCTYPE html>
424492 padding: 8px 10px;
425493 font-size: 13px;
426494 }
495+
496+ .header h1 {
497+ font-size: 1.3em;
498+ }
499+
500+ .theme-toggle span:not(.icon) {
501+ display: none;
502+ }
427503 }
428504 </style>
429505</head>
430506<body>
431- <h1>LaunchDarkly SDK Feature Comparison</h1>
507+ <div class="header">
508+ <div style="width: 100px;"></div>
509+ <h1>LaunchDarkly SDK Feature Comparison</h1>
510+ <button class="theme-toggle" id="theme-toggle" title="Toggle dark mode">
511+ <span class="icon">🌙</span>
512+ <span>Dark</span>
513+ </button>
514+ </div>
432515 <p class="subtitle">Select up to 3 SDKs in each section to compare their features</p>
433516
434517 <section id="client-side">
@@ -563,16 +646,8 @@ var htmlTemplate = `<!DOCTYPE html>
563646 thead.innerHTML += ` + "`" + `<th class="sdk-col">${sdk.name}</th>` + "`" + `;
564647 });
565648
566- // Collect all features from selected SDKs
567- const featuresSet = new Set();
568- sdks.forEach(sdk => {
569- if (sdkData[sdk.id]) {
570- Object.keys(sdkData[sdk.id]).forEach(f => featuresSet.add(f));
571- }
572- });
573-
574- // Sort features alphabetically by display name
575- const features = Array.from(featuresSet).sort((a, b) => {
649+ // Show all features from featureInfo
650+ const features = Object.keys(featureInfo).sort((a, b) => {
576651 const nameA = featureInfo[a]?.name || a;
577652 const nameB = featureInfo[b]?.name || b;
578653 return nameA.localeCompare(nameB);
@@ -623,6 +698,59 @@ var htmlTemplate = `<!DOCTYPE html>
623698 html += '</span>';
624699 return html;
625700 }
701+
702+ // Theme toggle functionality
703+ const themeToggle = document.getElementById('theme-toggle');
704+ const html = document.documentElement;
705+
706+ function updateToggleButton(isDark) {
707+ const icon = themeToggle.querySelector('.icon');
708+ const text = themeToggle.querySelector('span:not(.icon)');
709+ if (isDark) {
710+ icon.textContent = '☀️';
711+ text.textContent = 'Light';
712+ } else {
713+ icon.textContent = '🌙';
714+ text.textContent = 'Dark';
715+ }
716+ }
717+
718+ function getSystemTheme() {
719+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
720+ }
721+
722+ function getCurrentTheme() {
723+ const stored = localStorage.getItem('theme');
724+ if (stored) return stored;
725+ return getSystemTheme();
726+ }
727+
728+ function setTheme(theme) {
729+ if (theme === 'dark') {
730+ html.setAttribute('data-theme', 'dark');
731+ } else {
732+ html.setAttribute('data-theme', 'light');
733+ }
734+ localStorage.setItem('theme', theme);
735+ updateToggleButton(theme === 'dark');
736+ }
737+
738+ // Initialize theme
739+ const initialTheme = getCurrentTheme();
740+ setTheme(initialTheme);
741+
742+ // Toggle handler
743+ themeToggle.addEventListener('click', () => {
744+ const current = html.getAttribute('data-theme') || getSystemTheme();
745+ setTheme(current === 'dark' ? 'light' : 'dark');
746+ });
747+
748+ // Listen for system theme changes
749+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
750+ if (!localStorage.getItem('theme')) {
751+ setTheme(e.matches ? 'dark' : 'light');
752+ }
753+ });
626754 </script>
627755</body>
628756</html>
0 commit comments