Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions docs/.sphinx/_static/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,78 @@ p code.literal {
.highlight .o {
color: #BB5400;
}

/* Hoverxref tooltip dark mode support
The hoverxref extension uses Tippy.js which renders tooltips with light backgrounds by default.
Tippy appends tooltips directly to body, so we use a .dark-mode class added by JavaScript
(see hoverxref-dark-mode.js) rather than relying on theme context selectors. */

/* Light mode tooltip styles (default) */
.tippy-box[data-theme~='material'] {
background-color: #fff;
color: #111;
border: 1px solid #e0e0e0;
}

.tippy-box[data-theme~='material'] .tippy-content {
background-color: #fff;
color: #111;
}

.tippy-box[data-theme~='material'][data-placement^='top'] > .tippy-arrow::before {
border-top-color: #e0e0e0;
}

.tippy-box[data-theme~='material'][data-placement^='bottom'] > .tippy-arrow::before {
border-bottom-color: #e0e0e0;
}

.tippy-box[data-theme~='material'][data-placement^='left'] > .tippy-arrow::before {
border-left-color: #e0e0e0;
}

.tippy-box[data-theme~='material'][data-placement^='right'] > .tippy-arrow::before {
border-right-color: #e0e0e0;
}

/* Dark mode tooltip styles - applied via .dark-mode class by JavaScript */
.tippy-box[data-theme~='material'].dark-mode {
background-color: #2b2b2b;
color: #f7f7f7;
border: 1px solid #555;
}

.tippy-box[data-theme~='material'].dark-mode .tippy-content {
background-color: #2b2b2b;
color: #f7f7f7;
}

.tippy-box[data-theme~='material'].dark-mode[data-placement^='top'] > .tippy-arrow::before {
border-top-color: #555;
}

.tippy-box[data-theme~='material'].dark-mode[data-placement^='bottom'] > .tippy-arrow::before {
border-bottom-color: #555;
}

.tippy-box[data-theme~='material'].dark-mode[data-placement^='left'] > .tippy-arrow::before {
border-left-color: #555;
}

.tippy-box[data-theme~='material'].dark-mode[data-placement^='right'] > .tippy-arrow::before {
border-right-color: #555;
}

/* Style links within dark mode tooltips */
.tippy-box[data-theme~='material'].dark-mode a {
color: #58a6ff;
}

/* Style code blocks within dark mode tooltips */
.tippy-box[data-theme~='material'].dark-mode code {
background-color: #3b3b3b;
color: #e0e0e0;
border: 1px solid #555;
padding: 0.1em 0.3em;
border-radius: 3px;
}
156 changes: 156 additions & 0 deletions docs/.sphinx/_static/js/hoverxref-dark-mode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/**
* Hoverxref Dark Mode Support
*
* This script ensures that hoverxref tooltips (powered by Tippy.js)
* adapt to the current theme (light/dark mode).
*
* Tippy.js appends tooltip elements directly to the body, outside the
* themed content area, so we need to dynamically update their styling
* based on the current theme.
*/

(function() {
'use strict';

/**
* Get the current theme from the body's data-theme attribute
* @returns {string} 'light', 'dark', or 'auto'
*/
function getCurrentTheme() {
return document.body.getAttribute('data-theme') || 'auto';
}

/**
* Determine if dark mode should be active
* @returns {boolean}
*/
function isDarkMode() {
const theme = getCurrentTheme();
if (theme === 'dark') {
return true;
} else if (theme === 'light') {
return false;
} else {
// Theme is 'auto', check system preference
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
}
}

/**
* Update all visible tooltips to match the current theme
*/
function updateTooltipThemes() {
const tooltips = document.querySelectorAll('.tippy-box');
const darkMode = isDarkMode();

tooltips.forEach(function(tooltip) {
if (darkMode) {
tooltip.classList.add('dark-mode');
} else {
tooltip.classList.remove('dark-mode');
}
});
}

/**
* Set up a MutationObserver to watch for new tooltips being added to the DOM
*/
function observeTooltips() {
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
// Check if the added node is a tooltip or contains tooltips
if (node.nodeType === 1) { // Element node
if (node.classList && node.classList.contains('tippy-box')) {
// A tooltip was added
if (isDarkMode()) {
node.classList.add('dark-mode');
}
} else if (node.querySelectorAll) {
// Check for tooltips within the added node
const tooltips = node.querySelectorAll('.tippy-box');
if (tooltips.length > 0 && isDarkMode()) {
tooltips.forEach(function(tooltip) {
tooltip.classList.add('dark-mode');
});
}
}
}
});
});
});

// Observe the body for tooltip additions
observer.observe(document.body, {
childList: true,
subtree: true
});
}

/**
* Watch for theme changes on the body element
*/
function observeThemeChanges() {
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === 'attributes' && mutation.attributeName === 'data-theme') {
updateTooltipThemes();
}
});
});

observer.observe(document.body, {
attributes: true,
attributeFilter: ['data-theme']
});
}

/**
* Watch for system color scheme preference changes
*/
function observeSystemThemeChanges() {
if (window.matchMedia) {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');

// Modern browsers
if (mediaQuery.addEventListener) {
mediaQuery.addEventListener('change', function() {
// Only update if theme is set to 'auto'
if (getCurrentTheme() === 'auto') {
updateTooltipThemes();
}
});
} else if (mediaQuery.addListener) {
// Fallback for older browsers
mediaQuery.addListener(function() {
if (getCurrentTheme() === 'auto') {
updateTooltipThemes();
}
});
}
}
}

/**
* Initialize the dark mode support
*/
function init() {
// Wait for DOM to be ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
observeTooltips();
observeThemeChanges();
observeSystemThemeChanges();
updateTooltipThemes();
});
} else {
observeTooltips();
observeThemeChanges();
observeSystemThemeChanges();
updateTooltipThemes();
}
}

// Start the script
init();
})();
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
"js/header-nav.js",
"js/github_issue_links.js",
"js/bundle.js",
"js/hoverxref-dark-mode.js",
]

source_suffix = {
Expand Down