111 lines
4.7 KiB
Plaintext
111 lines
4.7 KiB
Plaintext
@namespace DeepDrftPublic.Client.Controls
|
|
|
|
@* Shared background-image hero with all release metadata overlaid: top row (genre/date + share),
|
|
bottom row (optional cover thumb + title/artist + play). Single source of truth for the overlay
|
|
composition consumed by both Session and Mix detail. Purely presentational — owns no data fetch
|
|
and no player wiring; play/share ride in as slots so each page keeps its own toggle. Per-page
|
|
aspect/sizing variance rides the Class parameter (e.g. Mix's square `mix-hero`), never a fork. *@
|
|
|
|
@{
|
|
var hasGenre = !string.IsNullOrEmpty(Genre);
|
|
var hasDate = ReleaseDate is not null;
|
|
// Show the cover thumbnail only when it differs from the hero background — otherwise it would
|
|
// duplicate the same image. Mix passes CoverThumbKey=null, so this is false there for free.
|
|
var showCover = !string.IsNullOrEmpty(CoverThumbKey) && CoverThumbKey != HeroImageKey;
|
|
}
|
|
|
|
@* The hero is the positioning context for every overlay row; the gradient shim and the
|
|
top/bottom overlays are absolutely positioned children of this wrapper. *@
|
|
<div class="release-hero @Class">
|
|
@if (!string.IsNullOrEmpty(HeroImageKey))
|
|
{
|
|
<div class="release-hero-img"
|
|
style="@($"background-image: url('api/image/{Uri.EscapeDataString(HeroImageKey)}');")"></div>
|
|
}
|
|
else
|
|
{
|
|
<div class="release-hero-placeholder deepdrft-gradient-soft-secondary">
|
|
<MudIcon Icon="@PlaceholderIcon" Color="Color.Primary" />
|
|
</div>
|
|
}
|
|
|
|
@* Darkening shim so overlaid text/controls stay legible over any image. *@
|
|
<div class="release-hero-shim"></div>
|
|
|
|
@* Top overlay: secondary details (genre, release date) and the share affordance. *@
|
|
<div class="release-hero-top">
|
|
<MudStack Row AlignItems="AlignItems.Center" Spacing="3" Class="release-hero-meta">
|
|
@if (hasGenre)
|
|
{
|
|
<MudChip T="string" Variant="Variant.Outlined" Class="release-overlay-chip">
|
|
@Genre
|
|
</MudChip>
|
|
}
|
|
@if (hasDate)
|
|
{
|
|
<div class="release-overlay-date">
|
|
<span class="release-overlay-label">Released</span>
|
|
<span class="release-overlay-value">@ReleaseDate!.Value.ToString("MMMM yyyy")</span>
|
|
</div>
|
|
}
|
|
</MudStack>
|
|
@if (ShareContent is not null)
|
|
{
|
|
<div class="release-hero-share">
|
|
@ShareContent
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
@* Bottom overlay: cover thumbnail, title/artist, and the play affordance in one row. *@
|
|
<div class="release-hero-bottom">
|
|
<MudStack Row AlignItems="AlignItems.Center" Spacing="4" Class="release-hero-bottom-row">
|
|
@if (showCover)
|
|
{
|
|
<div class="release-cover-thumb">
|
|
<div class="deepdrft-track-detail-cover-art"
|
|
style="@($"background-image: url('api/image/{Uri.EscapeDataString(CoverThumbKey!)}');")"></div>
|
|
</div>
|
|
}
|
|
<div class="release-hero-titles">
|
|
<div class="release-overlay-title">@Title</div>
|
|
<div class="release-overlay-artist">@Artist</div>
|
|
</div>
|
|
@if (PlayContent is not null)
|
|
{
|
|
<div class="release-hero-play">
|
|
@PlayContent
|
|
</div>
|
|
}
|
|
</MudStack>
|
|
</div>
|
|
</div>
|
|
|
|
@code {
|
|
/// <summary>Background image entry key. Null renders the placeholder treatment.</summary>
|
|
[Parameter] public string? HeroImageKey { get; set; }
|
|
|
|
/// <summary>Material icon for the no-image placeholder (Session: Piano; Mix: Album).</summary>
|
|
[Parameter] public required string PlaceholderIcon { get; set; }
|
|
|
|
/// <summary>
|
|
/// Optional small cover thumbnail in the bottom row. Shown only when it differs from
|
|
/// <see cref="HeroImageKey"/> (otherwise it would duplicate the background). Mix passes null.
|
|
/// </summary>
|
|
[Parameter] public string? CoverThumbKey { get; set; }
|
|
|
|
[Parameter] public required string Title { get; set; }
|
|
[Parameter] public string? Artist { get; set; }
|
|
[Parameter] public string? Genre { get; set; }
|
|
[Parameter] public DateOnly? ReleaseDate { get; set; }
|
|
|
|
/// <summary>Share affordance slot — each page passes its own SharePopover with the right params.</summary>
|
|
[Parameter] public RenderFragment? ShareContent { get; set; }
|
|
|
|
/// <summary>Play affordance slot — each page passes its PlayStateIcon wired to its own toggle.</summary>
|
|
[Parameter] public RenderFragment? PlayContent { get; set; }
|
|
|
|
/// <summary>Extra class for per-page aspect/sizing variance (e.g. Mix's square `mix-hero`).</summary>
|
|
[Parameter] public string? Class { get; set; }
|
|
}
|