Skip to content

Commit f0c5d9d

Browse files
committed
UI improvements and added footer
1 parent 339d74b commit f0c5d9d

2 files changed

Lines changed: 57 additions & 5 deletions

File tree

app.js

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ function loadYouTubeAPI() {
6868
return ytApiPromise;
6969
}
7070

71-
function setupAutoAdvance(nextHash) {
71+
function setupAutoAdvance(nextHash, currentVid) {
7272
const iframe = document.getElementById("yt-player");
7373
if (!iframe) return;
7474
loadYouTubeAPI().then(() => {
@@ -78,8 +78,18 @@ function setupAutoAdvance(nextHash) {
7878
events: {
7979
onStateChange: (e) => {
8080
if (e.data === window.YT.PlayerState.ENDED && nextHash) {
81+
// Navigate to next video — render() will re-render the playlist with correct highlight
8182
location.hash = nextHash;
8283
}
84+
if (e.data === window.YT.PlayerState.PLAYING) {
85+
// Ensure the correct playlist item is highlighted (handles edge cases)
86+
document.querySelectorAll(".pl-item").forEach((el) => {
87+
const isActive = el.dataset.vid === currentVid;
88+
el.classList.toggle("active", isActive);
89+
const nowBadge = el.querySelector(".pl-now");
90+
if (nowBadge) nowBadge.style.display = isActive ? "" : "none";
91+
});
92+
}
8393
},
8494
},
8595
});
@@ -96,6 +106,8 @@ function thumbUrl(video) {
96106
function render() {
97107
const hash = location.hash.slice(1); // e.g. /product/crm/video/crm-1
98108
const parts = hash.split("/").filter(Boolean);
109+
const isHome = parts.length === 0 || parts[0] !== "product";
110+
document.querySelector(".navbar").classList.toggle("is-home", isHome);
99111
if (parts[0] === "product" && parts[2] === "video") {
100112
renderVideo(parts[1], parts[3]);
101113
} else if (parts[0] === "product") {
@@ -137,7 +149,23 @@ function renderHome() {
137149
</div>
138150
</div>
139151
<h2 class="section-label fade">Choose a product</h2>
140-
<div class="grid fade">${cards}</div>`;
152+
<div class="grid fade">${cards}</div>
153+
<footer class="site-footer fade">
154+
<div class="footer-inner">
155+
<div class="footer-brand">
156+
<img src="icons/browserstack-icon.svg" alt="BrowserStack" width="28" height="28" />
157+
<span>BrowserStack Demo Hub</span>
158+
</div>
159+
<p class="footer-desc">Your one-stop destination for BrowserStack product walkthroughs, onboarding videos, and documentation.</p>
160+
<div class="footer-links">
161+
<a href="https://www.browserstack.com/docs" target="_blank" rel="noopener">Documentation</a>
162+
<a href="https://www.browserstack.com/contact" target="_blank" rel="noopener">Support</a>
163+
<a href="https://www.browserstack.com/blog" target="_blank" rel="noopener">Blog</a>
164+
<a href="https://www.browserstack.com/pricing" target="_blank" rel="noopener">Pricing</a>
165+
</div>
166+
<p class="footer-copy">&copy; ${new Date().getFullYear()} BrowserStack. All rights reserved.</p>
167+
</div>
168+
</footer>`;
141169
}
142170

143171
function renderDashboard(pid) {
@@ -187,7 +215,7 @@ function renderVideo(pid, vid) {
187215
const playlist = p.videos
188216
.map(
189217
(item, i) => `
190-
<li class="pl-item ${item.id === v.id ? "active" : ""}" onclick="location.hash='#/product/${p.id}/video/${item.id}'">
218+
<li class="pl-item ${item.id === v.id ? "active" : ""}" data-vid="${item.id}" onclick="location.hash='#/product/${p.id}/video/${item.id}'">
191219
<span class="pl-index">${i + 1}</span>
192220
<img class="pl-thumb" src="${thumbUrl(item)}" alt="" onerror="this.classList.add('noimg')" />
193221
<span class="pl-meta">
@@ -231,7 +259,7 @@ function renderVideo(pid, vid) {
231259
</div>`;
232260
// Auto-advance to the next video when this one ends.
233261
const next = p.videos[idx + 1];
234-
setupAutoAdvance(next ? `#/product/${p.id}/video/${next.id}` : null);
262+
setupAutoAdvance(next ? `#/product/${p.id}/video/${next.id}` : null, v.id);
235263
// Keep the active playlist item in view.
236264
const active = document.querySelector(".pl-item.active");
237265
if (active) active.scrollIntoView({ block: "nearest" });

styles.css

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
font-size: 16px; transition: background 0.25s, transform 0.2s; flex-shrink: 0;
6464
}
6565
.dark-toggle:hover { background: var(--border); transform: scale(1.08); }
66+
.navbar.is-home .nav-cta { display: none; }
67+
.nav-cta { cursor: pointer; }
6668

6769
* { margin: 0; padding: 0; box-sizing: border-box; }
6870

@@ -298,4 +300,26 @@ header.hero p { color: var(--muted); margin-top: 16px; font-size: 1.15rem; max-w
298300
.grid .card:nth-child(3) { animation-delay: 0.16s; }
299301
.grid .card:nth-child(4) { animation-delay: 0.22s; }
300302
.grid .card:nth-child(5) { animation-delay: 0.28s; }
301-
.grid .card:nth-child(6) { animation-delay: 0.34s; }
303+
.grid .card:nth-child(6) { animation-delay: 0.34s; }
304+
305+
/* Footer */
306+
.site-footer {
307+
margin-top: 72px; border-top: 1px solid var(--border); padding: 48px 0 32px;
308+
}
309+
.footer-inner {
310+
max-width: 1180px; margin: 0 auto; padding: 0 24px;
311+
display: flex; flex-direction: column; align-items: center; gap: 20px; text-align: center;
312+
}
313+
.footer-brand {
314+
display: flex; align-items: center; gap: 10px;
315+
font-size: 1rem; font-weight: 700; color: var(--navy);
316+
}
317+
.footer-desc { color: var(--muted); font-size: 0.95rem; max-width: 520px; line-height: 1.6; }
318+
.footer-links { display: flex; flex-wrap: wrap; gap: 8px 24px; justify-content: center; }
319+
.footer-links a {
320+
color: var(--muted); text-decoration: none; font-size: 0.9rem; font-weight: 500;
321+
transition: color 0.2s;
322+
}
323+
.footer-links a:hover { color: var(--orange); }
324+
.footer-copy { color: var(--muted); font-size: 0.82rem; }
325+
[data-theme="dark"] .site-footer { border-top-color: var(--border); }

0 commit comments

Comments
 (0)