feat: keep preview glow permanently after animation completes

This commit is contained in:
2026-01-16 15:14:43 +01:00
parent 0b22263a68
commit d78f0ac0b4
3 changed files with 28 additions and 3 deletions

View File

@@ -539,6 +539,7 @@ function resetSuccessIndicators() {
elements.previewWrapper?.classList.remove("matched");
elements.previewWrapper?.classList.remove("completed-glow");
elements.previewSection?.classList.remove("matched");
elements.previewSection?.classList.remove("completed-glow");
// Remove completion badge if present
const badge = document.querySelector(".completion-badge");
@@ -661,8 +662,9 @@ function loadCurrentLesson() {
elements.lessonTitleRow.appendChild(badge);
}
// Show gradient border for completed lessons
// Show gradient border and glow for completed lessons
elements.previewWrapper?.classList.add("completed-glow");
elements.previewSection?.classList.add("completed-glow");
} else {
elements.runBtn.querySelector("span").textContent = t("run");
@@ -670,6 +672,7 @@ function loadCurrentLesson() {
const badge = document.querySelector(".completion-badge");
if (badge) badge.remove();
elements.previewWrapper?.classList.remove("completed-glow");
elements.previewSection?.classList.remove("completed-glow");
}
// Update level indicator (hide in playground mode)
@@ -932,8 +935,9 @@ function runCode() {
state.animationTimeout = setTimeout(() => {
elements.previewWrapper?.classList.remove("matched");
elements.previewSection?.classList.remove("matched");
// Keep the gradient border visible after animation
// Keep the gradient border and glow visible after animation
elements.previewWrapper?.classList.add("completed-glow");
elements.previewSection?.classList.add("completed-glow");
state.animationTimeout = null;
}, 3500);

View File

@@ -1,5 +1,12 @@
import { t, applyTranslations } from "./i18n.js";
// Analytics tracking helper
function track(eventName, eventData = {}) {
if (typeof umami !== "undefined" && umami.track) {
umami.track(eventName, eventData);
}
}
let currentUser = null;
let oauthHandled = false;
let lessonEngineRef = null;
@@ -40,6 +47,8 @@ export async function handleOAuthCallback() {
if (!error && data?.session) {
oauthHandled = true;
const provider = data.session.user?.app_metadata?.provider || "oauth";
track("auth_login", { method: provider });
}
}

View File

@@ -662,6 +662,18 @@ kbd {
pointer-events: none;
}
/* Persistent glow for completed lessons */
.preview-section.completed-glow::before {
content: "";
position: absolute;
inset: var(--spacing-md);
border-radius: var(--border-radius-md);
background: conic-gradient(from 0deg, #9163b8, #d45aa0, #1aafb8, #7c4dff, #9163b8);
filter: blur(30px);
opacity: 0.35;
pointer-events: none;
}
.preview-header {
display: flex;
justify-content: space-between;
@@ -813,7 +825,7 @@ kbd {
}
100% {
--border-angle: -360deg;
opacity: 0;
opacity: 0.35;
}
}