yt embed redesign
This commit is contained in:
@@ -170,33 +170,48 @@ const YOUTUBE_CHANNEL_ID = import.meta.env.YOUTUBE_CHANNEL_ID;
|
||||
<!-- Latest YouTube Video -->
|
||||
<section class="mb-16">
|
||||
<div
|
||||
class="youtube-widget-container"
|
||||
class="yt-featured-wrapper group"
|
||||
id="youtubeWidget"
|
||||
data-api-key={YOUTUBE_API_KEY}
|
||||
data-channel-id={YOUTUBE_CHANNEL_ID}
|
||||
>
|
||||
<div class="widget-header">
|
||||
<div class="yt-icon"></div>
|
||||
<span class="widget-label">Latest Video</span>
|
||||
<div class="live-dot" title="Automatically updates"></div>
|
||||
<!-- Decorative Glow -->
|
||||
<div class="yt-glow"></div>
|
||||
|
||||
<div class="yt-header-area">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="yt-status-blob">
|
||||
<div class="yt-status-dot"></div>
|
||||
</div>
|
||||
<span class="yt-label-text">Latest from YouTube</span>
|
||||
</div>
|
||||
<a href="https://www.youtube.com/@teletypegames" target="_blank" class="yt-channel-link">
|
||||
Visit Channel ↗
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="yt-card">
|
||||
<div class="player-wrap" id="playerWrap">
|
||||
<div class="state-overlay" id="stateOverlay">
|
||||
<div class="spinner"></div>
|
||||
<div class="state-text">Loading video...</div>
|
||||
<div class="yt-content-grid">
|
||||
<div class="yt-player-container">
|
||||
<div class="player-wrap" id="playerWrap">
|
||||
<div class="state-overlay" id="stateOverlay">
|
||||
<div class="spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="meta" id="metaBox" style="display:none;">
|
||||
<div class="video-title" id="videoTitle">–</div>
|
||||
<div class="meta-row">
|
||||
<span class="meta-chip" id="publishDate">📅 –</span>
|
||||
<span class="meta-chip" id="viewCount">👁 –</span>
|
||||
<span class="new-badge">New</span>
|
||||
<a class="yt-link" id="ytLink" href="#" target="_blank" rel="noopener">
|
||||
Watch on YouTube ↗
|
||||
<div class="yt-info-sidebar" id="metaBox" style="display:none;">
|
||||
<div class="mb-auto">
|
||||
<span class="yt-new-tag">New Release</span>
|
||||
<h3 class="yt-video-title" id="videoTitle">–</h3>
|
||||
<div class="yt-stats-row">
|
||||
<span id="publishDate">📅 –</span>
|
||||
<span id="viewCount">👁 –</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<a id="ytLink" href="#" target="_blank" class="yt-play-button">
|
||||
<span class="text-xl">▶</span> Watch on YouTube
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -401,78 +416,71 @@ const YOUTUBE_CHANNEL_ID = import.meta.env.YOUTUBE_CHANNEL_ID;
|
||||
@apply text-gray-600 mb-6 flex-grow leading-relaxed;
|
||||
}
|
||||
|
||||
/* YouTube Widget */
|
||||
.youtube-widget-container {
|
||||
--yt-accent: #ff0000;
|
||||
--bg-card: #181818;
|
||||
--bg-meta: #1f1f1f;
|
||||
--text-primary: #f1f1f1;
|
||||
--text-secondary: #aaaaaa;
|
||||
--border: rgba(255,255,255,0.08);
|
||||
--radius: 12px;
|
||||
@apply w-full max-w-4xl mx-auto;
|
||||
/* YouTube Featured Wrapper */
|
||||
.yt-featured-wrapper {
|
||||
@apply relative overflow-hidden bg-gradient-to-br from-slate-900 via-slate-900 to-indigo-950 rounded-3xl shadow-2xl border border-slate-800 p-6 md:p-8;
|
||||
}
|
||||
|
||||
.yt-glow {
|
||||
@apply absolute -top-24 -right-24 w-96 h-96 bg-indigo-500/10 rounded-full blur-[100px] pointer-events-none;
|
||||
}
|
||||
|
||||
.youtube-widget-container .widget-header {
|
||||
@apply flex items-center gap-2.5 mb-5;
|
||||
}
|
||||
.youtube-widget-container .yt-icon {
|
||||
@apply w-7 h-5 bg-[#ff0000] rounded-[5px] flex items-center justify-center flex-shrink-0;
|
||||
}
|
||||
.youtube-widget-container .yt-icon::after {
|
||||
content: '';
|
||||
@apply border-l-[10px] border-l-white border-t-[6px] border-t-transparent border-b-[6px] border-b-transparent ml-0.5;
|
||||
}
|
||||
.youtube-widget-container .widget-label {
|
||||
@apply text-[11px] font-semibold tracking-[0.12em] uppercase text-gray-500;
|
||||
}
|
||||
.youtube-widget-container .live-dot {
|
||||
@apply w-[7px] h-[7px] rounded-full bg-[#ff0000] ml-auto animate-pulse;
|
||||
.yt-header-area {
|
||||
@apply flex items-center justify-between mb-6 relative z-10;
|
||||
}
|
||||
|
||||
.youtube-widget-container .yt-card {
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
@apply overflow-hidden shadow-xl;
|
||||
.yt-status-blob {
|
||||
@apply w-3 h-3 bg-red-500/20 rounded-full flex items-center justify-center;
|
||||
}
|
||||
.yt-status-dot {
|
||||
@apply w-1.5 h-1.5 bg-red-500 rounded-full animate-pulse;
|
||||
}
|
||||
.yt-label-text {
|
||||
@apply text-xs font-bold uppercase tracking-widest text-slate-400;
|
||||
}
|
||||
.yt-channel-link {
|
||||
@apply text-xs font-semibold text-indigo-400 hover:text-indigo-300 transition-colors;
|
||||
}
|
||||
|
||||
.youtube-widget-container .player-wrap {
|
||||
@apply relative w-full aspect-video bg-black;
|
||||
.yt-content-grid {
|
||||
@apply flex flex-col lg:flex-row gap-8 relative z-10;
|
||||
}
|
||||
.youtube-widget-container .player-wrap :global(iframe) {
|
||||
|
||||
.yt-player-container {
|
||||
@apply flex-[1.6] overflow-hidden rounded-2xl border border-white/5 shadow-inner bg-black;
|
||||
}
|
||||
.yt-player-container .player-wrap {
|
||||
@apply relative w-full aspect-video;
|
||||
}
|
||||
.yt-player-container .player-wrap :global(iframe) {
|
||||
@apply w-full h-full border-none block;
|
||||
}
|
||||
|
||||
.youtube-widget-container .state-overlay {
|
||||
@apply absolute inset-0 flex flex-col items-center justify-center gap-4 bg-black;
|
||||
}
|
||||
.youtube-widget-container .state-overlay :global(.spinner) {
|
||||
@apply w-9 h-9 border-4 border-white/10 border-t-[#ff0000] rounded-full animate-spin;
|
||||
}
|
||||
.youtube-widget-container .state-text {
|
||||
@apply text-[13px] text-[#aaaaaa] text-center px-6;
|
||||
.yt-info-sidebar {
|
||||
@apply flex-1 flex flex-col justify-center;
|
||||
}
|
||||
|
||||
.youtube-widget-container .meta {
|
||||
padding: 1.1rem 1.25rem;
|
||||
background: var(--bg-meta);
|
||||
border-top: 1px solid var(--border);
|
||||
.yt-new-tag {
|
||||
@apply inline-block px-2 py-1 bg-red-500/10 text-red-400 border border-red-500/20 rounded-md text-[10px] font-black uppercase tracking-tighter mb-4;
|
||||
}
|
||||
.youtube-widget-container .video-title {
|
||||
@apply text-[15px] font-semibold leading-[1.4] text-[#f1f1f1] mb-1.5 truncate;
|
||||
|
||||
.yt-video-title {
|
||||
@apply text-2xl font-black text-white mb-4 leading-tight group-hover:text-indigo-200 transition-colors;
|
||||
}
|
||||
.youtube-widget-container .meta-row {
|
||||
@apply flex items-center gap-3 flex-wrap;
|
||||
|
||||
.yt-stats-row {
|
||||
@apply flex gap-4 text-sm text-slate-400 font-medium;
|
||||
}
|
||||
.youtube-widget-container .meta-chip {
|
||||
@apply text-[12px] text-[#aaaaaa] flex items-center gap-1;
|
||||
|
||||
.yt-play-button {
|
||||
@apply flex items-center justify-center gap-2 w-full py-4 bg-white text-slate-900 font-black rounded-xl transition-all hover:scale-[1.02] hover:bg-indigo-50 active:scale-95 shadow-xl;
|
||||
}
|
||||
.youtube-widget-container .new-badge {
|
||||
@apply text-[10px] font-bold tracking-[0.08em] bg-[#ff0000] text-white px-1.5 py-0.5 rounded uppercase;
|
||||
|
||||
.yt-player-container .state-overlay {
|
||||
@apply absolute inset-0 flex items-center justify-center bg-slate-950;
|
||||
}
|
||||
.youtube-widget-container .yt-link {
|
||||
@apply ml-auto text-[12px] text-[#ff0000] no-underline font-medium opacity-85 transition-opacity hover:opacity-100;
|
||||
.yt-player-container .state-overlay :global(.spinner) {
|
||||
@apply w-10 h-10 border-4 border-white/5 border-t-indigo-500 rounded-full animate-spin;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -529,7 +537,9 @@ const YOUTUBE_CHANNEL_ID = import.meta.env.YOUTUBE_CHANNEL_ID;
|
||||
|
||||
if (!playerWrap || !API_KEY || !CHANNEL_ID) {
|
||||
if (playerWrap && (!API_KEY || !CHANNEL_ID)) {
|
||||
showError('Missing YouTube API key or Channel ID.');
|
||||
if (stateOverlay) {
|
||||
stateOverlay.innerHTML = `<div class="text-slate-500 text-xs">Missing API Configuration</div>`;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -537,8 +547,8 @@ const YOUTUBE_CHANNEL_ID = import.meta.env.YOUTUBE_CHANNEL_ID;
|
||||
function showError(msg) {
|
||||
if (stateOverlay) {
|
||||
stateOverlay.innerHTML = `
|
||||
<div class="text-2xl">⚠️</div>
|
||||
<div class="text-[13px] text-[#aaaaaa] text-center px-6">${msg}</div>`;
|
||||
<div class="text-xl mb-2">⚠️</div>
|
||||
<div class="text-[11px] text-slate-500 text-center px-4 font-bold uppercase tracking-tighter">${msg}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user