Skip to content

Commit f99aa9b

Browse files
staredclaude
andcommitted
Fix hover and click interactions for aligned equations
Fixed two critical issues with interactive terms in equations using \begin{aligned}: 1. Click handling for duplicate terms: Changed clicked state tracking from termClass to actual element reference, so clicking different occurrences of the same term (e.g., multiple instances of "divergence" in Maxwell) works correctly instead of toggling off. 2. Hover events blocked by KaTeX structure: KaTeX's alignment elements (.vlist, .mtable, etc.) were overlaying term elements with pointer-events:auto, blocking mouse events. Solution: Set pointer-events:none on all KaTeX structural elements while keeping pointer-events:auto on term elements to ensure they receive hover/click events. Also added z-index stacking context to prevent description overlay. All equations including Maxwell's 4th line now fully interactive. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent a76a6ce commit f99aa9b

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

src/main.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ function renderEquation() {
9090
trust: true, // Enable \htmlClass
9191
throwOnError: false,
9292
});
93+
94+
// Set pointer-events: none on KaTeX structural elements so they don't block term hover
95+
// But keep term elements interactive
96+
equationContainer.querySelectorAll('.katex *').forEach((el) => {
97+
const classList = (el as HTMLElement).classList;
98+
const hasTermClass = Array.from(classList).some(c => c.startsWith('term-'));
99+
if (hasTermClass) {
100+
(el as HTMLElement).style.pointerEvents = 'auto';
101+
} else {
102+
(el as HTMLElement).style.pointerEvents = 'none';
103+
}
104+
});
93105
}
94106

95107
function renderDescription() {
@@ -103,7 +115,7 @@ function setupHoverEffects() {
103115
const hoverDiv = document.getElementById('hover-explanation');
104116
if (!hoverDiv || !parsedContent) return;
105117

106-
let clicked: { termClass: string; definition: string } | null = null;
118+
let clicked: { element: HTMLElement; termClass: string; definition: string } | null = null;
107119

108120
const updateTerms = (termClass: string, classList: string, action: 'add' | 'remove') => {
109121
document.querySelectorAll(`.${termClass}`).forEach((el) => el.classList[action](classList));
@@ -124,14 +136,14 @@ function setupHoverEffects() {
124136
(element as HTMLElement).style.cursor = 'pointer';
125137

126138
element.addEventListener('click', () => {
127-
if (clicked?.termClass === termClass) {
139+
if (clicked?.element === element) {
128140
updateTerms(termClass, 'term-clicked', 'remove');
129141
clicked = null;
130142
hoverDiv.classList.remove('visible');
131143
} else {
132144
if (clicked) updateTerms(clicked.termClass, 'term-clicked', 'remove');
133145
updateTerms(termClass, 'term-clicked', 'add');
134-
clicked = { termClass, definition };
146+
clicked = { element: element as HTMLElement, termClass, definition };
135147
showDefinition(definition);
136148
}
137149
});

src/style.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ h1 {
4343
display: flex;
4444
justify-content: center;
4545
align-items: center;
46+
position: relative;
47+
z-index: 10;
4648
}
4749

4850
#equation-container .katex {
@@ -54,6 +56,11 @@ h1 {
5456
transition: opacity 0.2s ease;
5557
}
5658

59+
/* Ensure child elements don't block hover events */
60+
[class*="term-"] * {
61+
pointer-events: none !important;
62+
}
63+
5764
/* Hover effects - generic for all term classes */
5865
[class*="term-"]:hover,
5966
.term-active {
@@ -120,6 +127,8 @@ h1 {
120127
margin-bottom: 1rem;
121128
font-size: 1rem;
122129
line-height: 1.6;
130+
position: relative;
131+
z-index: 1;
123132
}
124133

125134
.static-description p {

0 commit comments

Comments
 (0)