diff --git a/DeepDrftPublic.Client/Controls/GalleryViewMode.cs b/DeepDrftPublic.Client/Controls/GalleryViewMode.cs new file mode 100644 index 0000000..b1f1cc2 --- /dev/null +++ b/DeepDrftPublic.Client/Controls/GalleryViewMode.cs @@ -0,0 +1,7 @@ +namespace DeepDrftPublic.Client.Controls; + +public enum GalleryViewMode +{ + Grid, + List +} diff --git a/DeepDrftPublic.Client/Controls/TrackCard.razor b/DeepDrftPublic.Client/Controls/TrackCard.razor index 5464481..3d331d3 100644 --- a/DeepDrftPublic.Client/Controls/TrackCard.razor +++ b/DeepDrftPublic.Client/Controls/TrackCard.razor @@ -1,9 +1,12 @@ @{ var hasLink = !string.IsNullOrEmpty(TrackModel?.EntryKey); var trackHref = hasLink ? $"/track/{TrackModel!.EntryKey}" : null; + var hasArt = !string.IsNullOrEmpty(TrackModel?.ImagePath); } -
+@if (ViewMode == GalleryViewMode.Grid) +{ +
@* Cover and title/artist link to the detail page; the play button (below, outside any anchor) stays the sole playback entry point. display:contents keeps the grid intact. *@ @@ -107,3 +110,102 @@
+} +else +{ +
+ + + + @if (hasLink) + { + + @* art thumb *@ + @if (!string.IsNullOrEmpty(TrackModel?.ImagePath)) + { +
+
+ } + else + { +
+ } + + @* text block *@ +
+ + @TrackModel?.Artist + + + @TrackModel?.TrackName + +
+ + @* right metadata *@ +
+ @if (!string.IsNullOrEmpty(TrackModel?.Genre)) + { + + @TrackModel.Genre + + } + @if (TrackModel?.ReleaseDate.HasValue == true) + { + + @TrackModel.ReleaseDate.Value.Year + + } +
+
+ } + else + { + @* same structure without anchor *@ + @if (!string.IsNullOrEmpty(TrackModel?.ImagePath)) + { +
+
+ } + else + { +
+ } +
+ + @TrackModel?.Artist + + + @TrackModel?.TrackName + +
+
+ @if (!string.IsNullOrEmpty(TrackModel?.Genre)) + { + + @TrackModel.Genre + + } + @if (TrackModel?.ReleaseDate.HasValue == true) + { + + @TrackModel.ReleaseDate.Value.Year + + } +
+ } +
+} diff --git a/DeepDrftPublic.Client/Controls/TrackCard.razor.cs b/DeepDrftPublic.Client/Controls/TrackCard.razor.cs index e4be2c5..3b2dd76 100644 --- a/DeepDrftPublic.Client/Controls/TrackCard.razor.cs +++ b/DeepDrftPublic.Client/Controls/TrackCard.razor.cs @@ -11,6 +11,7 @@ public partial class TrackCard : ComponentBase [Parameter] public EventCallback OnPause { get; set; } [Parameter] public bool IsPlaying { get; set; } = false; [Parameter] public bool IsPaused { get; set; } = false; + [Parameter] public GalleryViewMode ViewMode { get; set; } = GalleryViewMode.Grid; // Pause only when actively playing; every other state (idle, paused) reads as "press to play". private bool IsActivelyPlaying => IsPlaying && !IsPaused; diff --git a/DeepDrftPublic.Client/Controls/TrackCard.razor.css b/DeepDrftPublic.Client/Controls/TrackCard.razor.css index 05845b7..a018ce1 100644 --- a/DeepDrftPublic.Client/Controls/TrackCard.razor.css +++ b/DeepDrftPublic.Client/Controls/TrackCard.razor.css @@ -86,3 +86,100 @@ height: 200px; } } + +/* ── Mode A: hover-reveal overlay (art cards only) ──────────────────────── */ + +/* Gate the hidden-at-rest rule on (a) art present and (b) a hover-capable pointer. + Fallback cards (no --art modifier) and touch devices always show the overlay. */ +@media (hover: hover) and (pointer: fine) { + .deepdrft-track-card-container--art .deepdrft-track-card-content { + opacity: 0; + background: transparent; + transition: opacity 180ms ease, background-color 180ms ease; + } + .deepdrft-track-card-container--art:hover .deepdrft-track-card-content { + opacity: 1; + background: var(--deepdrft-navy-mid, #162437); + transition: opacity 180ms ease, background-color 180ms ease; + } +} + +/* ── Mode B: list row ───────────────────────────────────────────────────── */ + +.deepdrft-track-row { + display: flex; + flex-direction: row; + align-items: center; + gap: 16px; + height: 80px; + padding: 8px 16px; + background: var(--deepdrft-navy-mid, #162437); + border: 1px solid rgba(250, 250, 248, 0.12); + border-radius: 4px; + box-sizing: border-box; + width: 100%; +} + +.deepdrft-track-row-link { + display: flex; + flex-direction: row; + align-items: center; + gap: 16px; + flex: 1 1 auto; + min-width: 0; + text-decoration: none; + color: inherit; +} + +::deep .deepdrft-track-row-fab { + flex: 0 0 auto; +} + +.deepdrft-track-row-thumb { + flex: 0 0 64px; + width: 64px; + height: 64px; + background-size: cover; + background-position: center; + border-radius: 2px; +} + +.deepdrft-track-row-thumb--fallback { + background: color-mix(in srgb, var(--deepdrft-navy-mid, #162437) 60%, rgba(250,250,248,0.1)); + border: 1px solid rgba(250, 250, 248, 0.12); +} + +.deepdrft-track-row-text { + flex: 1 1 auto; + min-width: 0; + display: flex; + flex-direction: column; + justify-content: center; +} + +.deepdrft-track-row-meta { + flex: 0 0 auto; + display: flex; + flex-direction: column; + align-items: flex-end; + justify-content: center; + gap: 4px; +} + +@media (max-width: 480px) { + .deepdrft-track-row { + height: auto; + min-height: 72px; + padding: 8px 12px; + gap: 10px; + } + .deepdrft-track-row-thumb { + flex: 0 0 48px; + width: 48px; + height: 48px; + } +} + +.deepdrft-track-row--playing { + border-left: 3px solid var(--deepdrft-green-interactive, #3aa163); +} diff --git a/DeepDrftPublic.Client/Controls/TracksGallery.razor b/DeepDrftPublic.Client/Controls/TracksGallery.razor index 808e76d..db42790 100644 --- a/DeepDrftPublic.Client/Controls/TracksGallery.razor +++ b/DeepDrftPublic.Client/Controls/TracksGallery.razor @@ -1,16 +1,36 @@ - - - @foreach (var track in Tracks) - { - - - - } - - +@if (ViewMode == GalleryViewMode.Grid) +{ + + + @foreach (var track in Tracks) + { + + + + } + + +} +else +{ + +
+ @foreach (var track in Tracks) + { + + } +
+
+} diff --git a/DeepDrftPublic.Client/Controls/TracksGallery.razor.cs b/DeepDrftPublic.Client/Controls/TracksGallery.razor.cs index bc6a8f5..47878c7 100644 --- a/DeepDrftPublic.Client/Controls/TracksGallery.razor.cs +++ b/DeepDrftPublic.Client/Controls/TracksGallery.razor.cs @@ -13,6 +13,7 @@ public partial class TracksGallery : ComponentBase [Parameter] public TrackDto? ActiveTrack { get; set; } [Parameter] public bool IsPlaying { get; set; } [Parameter] public bool IsPaused { get; set; } + [Parameter] public GalleryViewMode ViewMode { get; set; } = GalleryViewMode.Grid; [Parameter] public EventCallback OnPlay { get; set; } [Parameter] public EventCallback OnPause { get; set; } diff --git a/DeepDrftPublic.Client/Controls/TracksGallery.razor.css b/DeepDrftPublic.Client/Controls/TracksGallery.razor.css index be316f8..0d0736c 100644 --- a/DeepDrftPublic.Client/Controls/TracksGallery.razor.css +++ b/DeepDrftPublic.Client/Controls/TracksGallery.razor.css @@ -6,3 +6,10 @@ display: flex; justify-content: center; } + +.deepdrft-track-list { + display: flex; + flex-direction: column; + gap: 8px; + width: 100%; +} diff --git a/DeepDrftPublic.Client/Pages/TracksView.razor b/DeepDrftPublic.Client/Pages/TracksView.razor index 27b4659..83a0e79 100644 --- a/DeepDrftPublic.Client/Pages/TracksView.razor +++ b/DeepDrftPublic.Client/Pages/TracksView.razor @@ -7,8 +7,19 @@
@if (ViewModel.Page != null) { +
+ + + + + + + + +
interactive (WASM) seam. diff --git a/DeepDrftPublic.Client/Pages/TracksView.razor.css b/DeepDrftPublic.Client/Pages/TracksView.razor.css index 4134c43..8a57c43 100644 --- a/DeepDrftPublic.Client/Pages/TracksView.razor.css +++ b/DeepDrftPublic.Client/Pages/TracksView.razor.css @@ -18,3 +18,9 @@ align-items: center; gap: 16px; } + +.tracks-view-header { + display: flex; + justify-content: flex-end; + padding: 0 0 12px 0; +}