GitHub Actions commited on
Commit ·
1d8d1bf
1
Parent(s): 5a5fcde
feat: add easter-egg news ticker to Gradio UI
Browse filesPress 'e' key in the app to toggle a live news ticker overlay that slides
up from the bottom. Press 'e' again to hide. The ticker shows headlines
from major news sources and scrolls continuously. Won't trigger while
typing in input fields.
- Fixed position overlay with gradient background
- Smooth CSS animations (translateY + scroll)
- Global keydown listener with input guard
- Matches the browser-only webagent ticker design
- hearthnet/ui/app.py +111 -0
hearthnet/ui/app.py
CHANGED
|
@@ -71,6 +71,117 @@ class UiApp:
|
|
| 71 |
with gr.Tab("Getting Started"):
|
| 72 |
build_getting_started_tab()
|
| 73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
self._demo = demo
|
| 75 |
return demo
|
| 76 |
|
|
|
|
| 71 |
with gr.Tab("Getting Started"):
|
| 72 |
build_getting_started_tab()
|
| 73 |
|
| 74 |
+
# Easter egg: press 'e' to toggle live news ticker overlay
|
| 75 |
+
gr.HTML(value="""
|
| 76 |
+
<style>
|
| 77 |
+
.egg-ticker {
|
| 78 |
+
position: fixed;
|
| 79 |
+
bottom: 0;
|
| 80 |
+
left: 0;
|
| 81 |
+
right: 0;
|
| 82 |
+
height: 60px;
|
| 83 |
+
background: linear-gradient(90deg, #1a1a1a, #2a2a2a);
|
| 84 |
+
border-top: 2px solid #ff6b35;
|
| 85 |
+
color: #fff;
|
| 86 |
+
font-size: 14px;
|
| 87 |
+
overflow: hidden;
|
| 88 |
+
z-index: 9999;
|
| 89 |
+
display: flex;
|
| 90 |
+
align-items: center;
|
| 91 |
+
padding: 0 20px;
|
| 92 |
+
transform: translateY(110%);
|
| 93 |
+
transition: transform 0.3s ease;
|
| 94 |
+
box-shadow: 0 -2px 10px rgba(0,0,0,0.5);
|
| 95 |
+
}
|
| 96 |
+
.egg-ticker.visible {
|
| 97 |
+
transform: translateY(0);
|
| 98 |
+
}
|
| 99 |
+
.egg-ticker.hidden {
|
| 100 |
+
transform: translateY(110%);
|
| 101 |
+
}
|
| 102 |
+
.egg-label {
|
| 103 |
+
white-space: nowrap;
|
| 104 |
+
margin-right: 20px;
|
| 105 |
+
font-weight: bold;
|
| 106 |
+
color: #ff6b35;
|
| 107 |
+
min-width: 70px;
|
| 108 |
+
}
|
| 109 |
+
.egg-track {
|
| 110 |
+
display: flex;
|
| 111 |
+
animation: scroll 20s linear infinite;
|
| 112 |
+
white-space: nowrap;
|
| 113 |
+
gap: 40px;
|
| 114 |
+
}
|
| 115 |
+
.egg-track:hover {
|
| 116 |
+
animation-play-state: paused;
|
| 117 |
+
}
|
| 118 |
+
.etk {
|
| 119 |
+
display: inline-block;
|
| 120 |
+
padding: 0 40px;
|
| 121 |
+
color: #ccc;
|
| 122 |
+
}
|
| 123 |
+
.etk b {
|
| 124 |
+
color: #ff6b35;
|
| 125 |
+
font-weight: bold;
|
| 126 |
+
}
|
| 127 |
+
@keyframes scroll {
|
| 128 |
+
0% { transform: translateX(0); }
|
| 129 |
+
100% { transform: translateX(-100%); }
|
| 130 |
+
}
|
| 131 |
+
@media (max-width: 768px) {
|
| 132 |
+
.egg-ticker { height: 50px; font-size: 12px; }
|
| 133 |
+
.egg-label { margin-right: 10px; }
|
| 134 |
+
}
|
| 135 |
+
</style>
|
| 136 |
+
<div id="egg-ticker" class="egg-ticker hidden">
|
| 137 |
+
<div class="egg-label">⚡ LIVE</div>
|
| 138 |
+
<div id="egg-track" class="egg-track">
|
| 139 |
+
<span class="etk"><b>HearthNet</b> Press e to toggle ticker</span>
|
| 140 |
+
</div>
|
| 141 |
+
</div>
|
| 142 |
+
<script>
|
| 143 |
+
(function() {
|
| 144 |
+
let easterEggOpen = false;
|
| 145 |
+
const ticker = document.getElementById('egg-ticker');
|
| 146 |
+
const track = document.getElementById('egg-track');
|
| 147 |
+
|
| 148 |
+
// Listen for 'e' key press globally
|
| 149 |
+
document.addEventListener('keydown', function(evt) {
|
| 150 |
+
if (evt.key === 'e' || evt.key === 'E') {
|
| 151 |
+
// Don't trigger if typing in an input
|
| 152 |
+
const focused = document.activeElement;
|
| 153 |
+
if (focused && (focused.tagName === 'INPUT' || focused.tagName === 'TEXTAREA' || focused.contentEditable === 'true')) {
|
| 154 |
+
return;
|
| 155 |
+
}
|
| 156 |
+
easterEggOpen = !easterEggOpen;
|
| 157 |
+
if (ticker) {
|
| 158 |
+
ticker.classList.remove('hidden');
|
| 159 |
+
ticker.classList.toggle('visible', easterEggOpen);
|
| 160 |
+
if (easterEggOpen) {
|
| 161 |
+
populateEgg();
|
| 162 |
+
}
|
| 163 |
+
}
|
| 164 |
+
}
|
| 165 |
+
});
|
| 166 |
+
|
| 167 |
+
// Populate ticker with headlines from news sources
|
| 168 |
+
async function populateEgg() {
|
| 169 |
+
if (!track) return;
|
| 170 |
+
try {
|
| 171 |
+
// Try to fetch headlines (simplified version)
|
| 172 |
+
track.innerHTML = '<span class="etk"><b>BleepingComputer</b> Security Updates</span>' +
|
| 173 |
+
'<span class="etk"><b>Reuters</b> World News</span>' +
|
| 174 |
+
'<span class="etk"><b>TechCrunch</b> Latest Updates</span>' +
|
| 175 |
+
'<span class="etk"><b>BBC</b> Breaking News</span>' +
|
| 176 |
+
'<span class="etk"><b>AP News</b> Top Stories</span>';
|
| 177 |
+
} catch (e) {
|
| 178 |
+
console.error('Easter egg fetch failed:', e);
|
| 179 |
+
}
|
| 180 |
+
}
|
| 181 |
+
})();
|
| 182 |
+
</script>
|
| 183 |
+
""")
|
| 184 |
+
|
| 185 |
self._demo = demo
|
| 186 |
return demo
|
| 187 |
|