diff --git a/src/views/library/library.css b/src/views/library/library.css index 84d7319..277aaf4 100644 --- a/src/views/library/library.css +++ b/src/views/library/library.css @@ -540,3 +540,362 @@ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); } } + +/* Game Detail View Styles */ +.game-detail-view { + position: absolute; + inset: 0; + display: flex; + flex-direction: column; + overflow: hidden; + background: linear-gradient(180deg, rgba(17, 24, 48, 0.95), rgba(8, 12, 27, 0.98)); +} + +.game-detail-header-image { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 40%; + background-size: cover; + background-position: center; + background-color: rgba(79, 216, 255, 0.08); + z-index: 1; +} + +.game-detail-header-overlay { + position: absolute; + inset: 0; + background: linear-gradient(180deg, rgba(7, 10, 20, 0.3), rgba(7, 10, 20, 0.95)); + z-index: 1; +} + +.game-detail-content { + position: relative; + z-index: 2; + flex: 1; + overflow-y: auto; + display: flex; + flex-direction: column; +} + +.game-detail-header { + padding: 28px 40px 20px; + display: grid; + grid-template-columns: 1fr auto; + gap: 40px; + align-items: start; +} + +.game-detail-title-section h1 { + margin: 0; + font-size: 48px; + line-height: 1.1; + letter-spacing: -0.02em; + max-width: 600px; +} + +.game-detail-title-section .library-section-kicker { + display: block; + margin-bottom: 12px; +} + +.game-detail-meta { + display: flex; + gap: 24px; + margin-top: 12px; + font-size: 14px; + color: var(--nebula-color-muted); + flex-wrap: wrap; +} + +.game-detail-play-button-container { + display: flex; + gap: 12px; +} + +.game-detail-play-button { + min-width: 160px; + padding: 16px 32px; + font-size: 18px; + font-weight: 900; + text-transform: uppercase; + letter-spacing: 0.08em; + border: none; + border-radius: 12px; + background: linear-gradient(135deg, var(--nebula-color-accent), #78f0ff); + color: #04101d; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + box-shadow: 0 12px 32px rgba(79, 216, 255, 0.34); + transition: all 0.2s ease; + white-space: nowrap; +} + +.game-detail-play-button .play-icon { + font-size: 20px; +} + +.game-detail-play-button.is-focused { + transform: scale(1.08); + box-shadow: + 0 0 0 2px rgba(79, 216, 255, 0.3), + 0 16px 40px rgba(79, 216, 255, 0.42); +} + +.game-detail-main { + display: grid; + grid-template-columns: 1fr 320px; + gap: 40px; + padding: 0 40px 40px; +} + +.game-detail-left-column { + display: flex; + flex-direction: column; + gap: 32px; + max-width: 700px; +} + +.game-detail-right-column { + display: flex; + flex-direction: column; + gap: 24px; +} + +.game-detail-section-title { + margin: 0 0 16px 0; + font-size: 18px; + font-weight: 900; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--nebula-color-accent); +} + +.game-detail-description { + display: flex; + flex-direction: column; + gap: 12px; +} + +.game-detail-description p { + margin: 0; + color: var(--nebula-color-muted); + line-height: 1.6; +} + +.game-detail-description .long-description { + color: var(--nebula-color-muted); + opacity: 0.85; +} + +.game-detail-info { + display: flex; + flex-direction: column; + gap: 12px; +} + +.game-detail-info-list { + display: grid; + gap: 12px; +} + +.game-detail-info-list div { + display: grid; + grid-template-columns: 120px 1fr; + gap: 12px; + padding: 12px; + border-radius: var(--nebula-radius-md); + background: rgba(79, 216, 255, 0.05); + border: 1px solid rgba(79, 216, 255, 0.08); +} + +.game-detail-info-list dt { + font-size: 12px; + font-weight: 900; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--nebula-color-accent); +} + +.game-detail-info-list dd { + margin: 0; + color: var(--nebula-color-muted); + word-break: break-word; +} + +/* Screenshots Section */ +.game-detail-screenshots { + display: flex; + flex-direction: column; + gap: 16px; +} + +.screenshots-carousel { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 12px; +} + +.screenshot-item { + aspect-ratio: 16 / 9; + border-radius: 12px; + overflow: hidden; + border: 1px solid rgba(79, 216, 255, 0.12); + background: rgba(10, 16, 34, 0.6); +} + +.screenshot-item img { + width: 100%; + height: 100%; + object-fit: cover; +} + +/* Achievements Section */ +.game-detail-achievements { + display: flex; + flex-direction: column; + gap: 16px; + padding: 16px; + border-radius: var(--nebula-radius-lg); + background: linear-gradient(135deg, rgba(79, 216, 255, 0.08), rgba(157, 79, 224, 0.08)); + border: 1px solid rgba(79, 216, 255, 0.12); +} + +.achievements-container { + display: flex; + flex-direction: column; + gap: 12px; +} + +.achievements-progress { + display: grid; + grid-template-columns: auto 1fr auto; + gap: 12px; + align-items: center; +} + +.achievement-stat { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; +} + +.achievement-number { + font-size: 20px; + font-weight: 900; + color: var(--nebula-color-accent); +} + +.achievement-label { + font-size: 11px; + font-weight: 800; + text-transform: uppercase; + color: var(--nebula-color-muted); + margin-top: 4px; +} + +.achievement-bar { + height: 8px; + border-radius: 4px; + background: rgba(255, 255, 255, 0.08); + overflow: hidden; +} + +.achievement-bar-fill { + height: 100%; + background: linear-gradient(90deg, var(--nebula-color-accent), #78f0ff); + border-radius: 4px; +} + +/* Features and Badges */ +.game-detail-features { + display: flex; + flex-direction: column; + gap: 12px; + padding: 16px; + border-radius: var(--nebula-radius-lg); + background: rgba(255, 255, 255, 0.04); + border: 1px solid rgba(255, 255, 255, 0.07); +} + +.features-grid { + display: grid; + gap: 10px; +} + +.feature-badge { + display: inline-block; + padding: 8px 12px; + border-radius: 8px; + font-size: 12px; + font-weight: 800; + text-transform: uppercase; + letter-spacing: 0.04em; + background: rgba(79, 216, 255, 0.14); + color: var(--nebula-color-accent); + border: 1px solid rgba(79, 216, 255, 0.22); +} + +.feature-badge.verified { + background: rgba(79, 255, 136, 0.12); + color: #9effbc; + border-color: rgba(79, 255, 136, 0.24); +} + +/* Actions */ +.game-detail-actions { + display: grid; + gap: 10px; + padding: 16px; + border-radius: var(--nebula-radius-lg); + background: rgba(255, 255, 255, 0.02); + border: 1px solid rgba(255, 255, 255, 0.05); +} + +.library-detail-button { + padding: 12px 16px; + border-radius: var(--nebula-radius-md); + font-weight: 900; + font-size: 14px; + text-align: left; +} + +.library-detail-button.is-focused { + border-color: var(--nebula-color-accent); + box-shadow: + 0 0 0 2px rgba(79, 216, 255, 0.14), + 0 0 26px rgba(79, 216, 255, 0.34); + transform: scale(1.03) translateZ(0); +} + +/* Scrollbar styling for content area */ +.game-detail-content::-webkit-scrollbar { + width: 8px; +} + +.game-detail-content::-webkit-scrollbar-track { + background: transparent; +} + +.game-detail-content::-webkit-scrollbar-thumb { + background: rgba(79, 216, 255, 0.24); + border-radius: 4px; +} + +.game-detail-content::-webkit-scrollbar-thumb:hover { + background: rgba(79, 216, 255, 0.36); +} + +/* Update the library-details-panel for full-screen mode */ +.library-details-panel.is-open { + display: flex; +} + +.game-detail-view { + z-index: 31; +} diff --git a/src/views/library/library.js b/src/views/library/library.js index eb8101d..5871f75 100644 --- a/src/views/library/library.js +++ b/src/views/library/library.js @@ -158,7 +158,7 @@ export const createLibraryView = ({ state, renderView }) => { if (action === "card") { runtime.focusedId = element.dataset.itemId; - return launchFocusedItem(); + return openDetails(); } if (action === "launch") return launchFocusedItem(); diff --git a/src/views/library/libraryComponents.js b/src/views/library/libraryComponents.js index 2724544..3f7ccf1 100644 --- a/src/views/library/libraryComponents.js +++ b/src/views/library/libraryComponents.js @@ -255,45 +255,161 @@ export const renderGrid = (items, focusedId) => { export const renderDetailsPanel = (item) => { if (!item) return ""; + const achievements = item.achievementsSupported ? `${item.achievementsUnlocked ?? 0} / ${item.achievementsTotal ?? "?"}` : "Not supported"; + + const screenshotsHtml = item.screenshots && item.screenshots.length > 0 + ? ` +