aghilTQ commited on
Commit
1940bcc
ยท
verified ยท
1 Parent(s): 31d1319

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +178 -19
src/streamlit_app.py CHANGED
@@ -39,32 +39,62 @@ st.markdown("""
39
 
40
  .word-highlight {
41
  display: inline-block;
42
- padding: 0 4px;
43
- margin: 0 2px;
44
  border-radius: 4px;
45
- transition: all 0.2s ease;
46
  cursor: pointer;
 
 
 
 
 
 
 
47
  }
48
 
49
  .pronunciation-word {
50
  display: inline-block;
51
- padding: 0 4px;
52
- margin: 0 2px;
53
  border-radius: 4px;
54
- transition: all 0.2s ease;
55
  cursor: pointer;
56
  font-family: 'Courier New', monospace;
57
  letter-spacing: 1px;
 
 
58
  }
59
 
60
- .color-1 { background-color: rgba(110, 142, 251, 0.15); color: #6e8efb; }
61
- .color-2 { background-color: rgba(167, 119, 227, 0.15); color: #a777e3; }
62
- .color-3 { background-color: rgba(79, 172, 254, 0.15); color: #4facfe; }
63
- .color-4 { background-color: rgba(0, 242, 254, 0.15); color: #00f2fe; }
64
- .color-5 { background-color: rgba(67, 233, 123, 0.15); color: #43e97b; }
65
- .color-6 { background-color: rgba(56, 249, 215, 0.15); color: #38f9d7; }
66
- .color-7 { background-color: rgba(250, 112, 154, 0.15); color: #fa709a; }
67
- .color-8 { background-color: rgba(177, 151, 9, 0.15); color: #b19709; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
  .pronunciation-separator {
70
  color: #a777e3;
@@ -91,7 +121,8 @@ st.markdown("""
91
 
92
  .results-text {
93
  font-size: 1.1rem;
94
- line-height: 1.6;
 
95
  }
96
 
97
  .sample-buttons {
@@ -141,7 +172,73 @@ st.markdown("""
141
  text-transform: uppercase;
142
  letter-spacing: 1px;
143
  }
 
 
 
 
 
144
  </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  """, unsafe_allow_html=True)
146
 
147
  class PronunciationAnalyzer:
@@ -266,7 +363,7 @@ def render_highlighted_text(word_syllables: List[Tuple[str, List[str]]], analyze
266
  for word, syllables in word_syllables:
267
  if any(c.isalnum() for c in word):
268
  color_class = analyzer.color_classes[word_index % len(analyzer.color_classes)]
269
- html_parts.append(f'<span class="word-highlight {color_class}">{word}</span>')
270
  word_index += 1
271
  else:
272
  html_parts.append(word)
@@ -288,7 +385,7 @@ def render_pronunciation(word_syllables: List[Tuple[str, List[str]]], analyzer:
288
 
289
  # Join syllables with dots
290
  syllable_text = '<span class="pronunciation-separator">ยท</span>'.join(syllables)
291
- html_parts.append(f'<span class="pronunciation-word {color_class}">{syllable_text}</span>')
292
  word_index += 1
293
  else:
294
  html_parts.append(f'<span class="pronunciation-word">{word}</span>')
@@ -398,12 +495,74 @@ def main():
398
  # Original text with highlights
399
  st.markdown("### ๐Ÿ“– Original Text")
400
  original_html = render_highlighted_text(word_syllables, analyzer)
401
- st.markdown(f'<div class="analysis-card"><div class="results-text">{original_html}</div></div>', unsafe_allow_html=True)
402
 
403
  # Pronunciation breakdown
404
  st.markdown("### ๐Ÿ”ค Pronunciation Breakdown")
405
  pronunciation_html = render_pronunciation(word_syllables, analyzer)
406
- st.markdown(f'<div class="analysis-card"><div class="results-text">{pronunciation_html}</div></div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
 
408
  # Word-by-word breakdown
409
  st.markdown("### ๐Ÿ“ Word-by-Word Analysis")
 
39
 
40
  .word-highlight {
41
  display: inline-block;
42
+ padding: 2px 4px;
43
+ margin: 0 1px;
44
  border-radius: 4px;
45
+ transition: all 0.3s ease;
46
  cursor: pointer;
47
+ color: #666;
48
+ background-color: transparent;
49
+ }
50
+
51
+ .word-highlight:hover {
52
+ transform: translateY(-1px);
53
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
54
  }
55
 
56
  .pronunciation-word {
57
  display: inline-block;
58
+ padding: 2px 4px;
59
+ margin: 0 1px;
60
  border-radius: 4px;
61
+ transition: all 0.3s ease;
62
  cursor: pointer;
63
  font-family: 'Courier New', monospace;
64
  letter-spacing: 1px;
65
+ color: #666;
66
+ background-color: transparent;
67
  }
68
 
69
+ .pronunciation-word:hover {
70
+ transform: translateY(-1px);
71
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
72
+ }
73
+
74
+ /* Active states when hovered/linked */
75
+ .word-active {
76
+ background-color: rgba(110, 142, 251, 0.2) !important;
77
+ color: #6e8efb !important;
78
+ transform: translateY(-1px);
79
+ box-shadow: 0 2px 12px rgba(110, 142, 251, 0.3);
80
+ }
81
+
82
+ .pronunciation-active {
83
+ background-color: rgba(110, 142, 251, 0.2) !important;
84
+ color: #6e8efb !important;
85
+ transform: translateY(-1px);
86
+ box-shadow: 0 2px 12px rgba(110, 142, 251, 0.3);
87
+ }
88
+
89
+ /* Color classes - only used for subtle borders */
90
+ .color-1 { border-left: 3px solid #6e8efb; }
91
+ .color-2 { border-left: 3px solid #a777e3; }
92
+ .color-3 { border-left: 3px solid #4facfe; }
93
+ .color-4 { border-left: 3px solid #00f2fe; }
94
+ .color-5 { border-left: 3px solid #43e97b; }
95
+ .color-6 { border-left: 3px solid #38f9d7; }
96
+ .color-7 { border-left: 3px solid #fa709a; }
97
+ .color-8 { border-left: 3px solid #b19709; }
98
 
99
  .pronunciation-separator {
100
  color: #a777e3;
 
121
 
122
  .results-text {
123
  font-size: 1.1rem;
124
+ line-height: 1.8;
125
+ color: #666;
126
  }
127
 
128
  .sample-buttons {
 
172
  text-transform: uppercase;
173
  letter-spacing: 1px;
174
  }
175
+
176
+ /* Interactive hover JavaScript */
177
+ .hover-container {
178
+ position: relative;
179
+ }
180
  </style>
181
+
182
+ <script>
183
+ function addHoverInteraction() {
184
+ // Add event listeners for word-syllable linking
185
+ setTimeout(() => {
186
+ const words = document.querySelectorAll('.word-highlight');
187
+ const pronunciations = document.querySelectorAll('.pronunciation-word');
188
+
189
+ // Clear any existing listeners
190
+ words.forEach(word => {
191
+ word.replaceWith(word.cloneNode(true));
192
+ });
193
+ pronunciations.forEach(pron => {
194
+ pron.replaceWith(pron.cloneNode(true));
195
+ });
196
+
197
+ // Re-select after cloning
198
+ const newWords = document.querySelectorAll('.word-highlight');
199
+ const newPronunciations = document.querySelectorAll('.pronunciation-word');
200
+
201
+ newWords.forEach((word, index) => {
202
+ word.addEventListener('mouseenter', () => {
203
+ // Highlight corresponding pronunciation
204
+ word.classList.add('word-active');
205
+ if (newPronunciations[index]) {
206
+ newPronunciations[index].classList.add('pronunciation-active');
207
+ }
208
+ });
209
+
210
+ word.addEventListener('mouseleave', () => {
211
+ // Remove highlights
212
+ word.classList.remove('word-active');
213
+ if (newPronunciations[index]) {
214
+ newPronunciations[index].classList.remove('pronunciation-active');
215
+ }
216
+ });
217
+ });
218
+
219
+ newPronunciations.forEach((pron, index) => {
220
+ pron.addEventListener('mouseenter', () => {
221
+ // Highlight corresponding word
222
+ pron.classList.add('pronunciation-active');
223
+ if (newWords[index]) {
224
+ newWords[index].classList.add('word-active');
225
+ }
226
+ });
227
+
228
+ pron.addEventListener('mouseleave', () => {
229
+ // Remove highlights
230
+ pron.classList.remove('pronunciation-active');
231
+ if (newWords[index]) {
232
+ newWords[index].classList.remove('word-active');
233
+ }
234
+ });
235
+ });
236
+ }, 100);
237
+ }
238
+
239
+ // Run the interaction setup when page loads
240
+ document.addEventListener('DOMContentLoaded', addHoverInteraction);
241
+ </script>
242
  """, unsafe_allow_html=True)
243
 
244
  class PronunciationAnalyzer:
 
363
  for word, syllables in word_syllables:
364
  if any(c.isalnum() for c in word):
365
  color_class = analyzer.color_classes[word_index % len(analyzer.color_classes)]
366
+ html_parts.append(f'<span class="word-highlight {color_class}" data-word-index="{word_index}">{word}</span>')
367
  word_index += 1
368
  else:
369
  html_parts.append(word)
 
385
 
386
  # Join syllables with dots
387
  syllable_text = '<span class="pronunciation-separator">ยท</span>'.join(syllables)
388
+ html_parts.append(f'<span class="pronunciation-word {color_class}" data-word-index="{word_index}">{syllable_text}</span>')
389
  word_index += 1
390
  else:
391
  html_parts.append(f'<span class="pronunciation-word">{word}</span>')
 
495
  # Original text with highlights
496
  st.markdown("### ๐Ÿ“– Original Text")
497
  original_html = render_highlighted_text(word_syllables, analyzer)
498
+ st.markdown(f'<div class="analysis-card hover-container"><div class="results-text">{original_html}</div></div>', unsafe_allow_html=True)
499
 
500
  # Pronunciation breakdown
501
  st.markdown("### ๐Ÿ”ค Pronunciation Breakdown")
502
  pronunciation_html = render_pronunciation(word_syllables, analyzer)
503
+ st.markdown(f'<div class="analysis-card hover-container"><div class="results-text">{pronunciation_html}</div></div>', unsafe_allow_html=True)
504
+
505
+ # Add JavaScript for hover interaction
506
+ st.components.v1.html("""
507
+ <script>
508
+ function addHoverInteraction() {
509
+ const words = parent.document.querySelectorAll('.word-highlight');
510
+ const pronunciations = parent.document.querySelectorAll('.pronunciation-word');
511
+
512
+ // Clear existing event listeners by cloning nodes
513
+ words.forEach((word, index) => {
514
+ const wordIndex = word.getAttribute('data-word-index');
515
+ if (wordIndex !== null) {
516
+ const newWord = word.cloneNode(true);
517
+ word.parentNode.replaceChild(newWord, word);
518
+
519
+ newWord.addEventListener('mouseenter', () => {
520
+ newWord.classList.add('word-active');
521
+ const correspondingPron = parent.document.querySelector(`[data-word-index="${wordIndex}"].pronunciation-word`);
522
+ if (correspondingPron) {
523
+ correspondingPron.classList.add('pronunciation-active');
524
+ }
525
+ });
526
+
527
+ newWord.addEventListener('mouseleave', () => {
528
+ newWord.classList.remove('word-active');
529
+ const correspondingPron = parent.document.querySelector(`[data-word-index="${wordIndex}"].pronunciation-word`);
530
+ if (correspondingPron) {
531
+ correspondingPron.classList.remove('pronunciation-active');
532
+ }
533
+ });
534
+ }
535
+ });
536
+
537
+ pronunciations.forEach((pron, index) => {
538
+ const wordIndex = pron.getAttribute('data-word-index');
539
+ if (wordIndex !== null) {
540
+ const newPron = pron.cloneNode(true);
541
+ pron.parentNode.replaceChild(newPron, pron);
542
+
543
+ newPron.addEventListener('mouseenter', () => {
544
+ newPron.classList.add('pronunciation-active');
545
+ const correspondingWord = parent.document.querySelector(`[data-word-index="${wordIndex}"].word-highlight`);
546
+ if (correspondingWord) {
547
+ correspondingWord.classList.add('word-active');
548
+ }
549
+ });
550
+
551
+ newPron.addEventListener('mouseleave', () => {
552
+ newPron.classList.remove('pronunciation-active');
553
+ const correspondingWord = parent.document.querySelector(`[data-word-index="${wordIndex}"].word-highlight`);
554
+ if (correspondingWord) {
555
+ correspondingWord.classList.remove('word-active');
556
+ }
557
+ });
558
+ }
559
+ });
560
+ }
561
+
562
+ // Run interaction setup
563
+ setTimeout(addHoverInteraction, 300);
564
+ </script>
565
+ """, height=0)
566
 
567
  # Word-by-word breakdown
568
  st.markdown("### ๐Ÿ“ Word-by-Word Analysis")