docs: mark track-card plain-shell refactor completed
This commit is contained in:
@@ -60,6 +60,31 @@ Collapsed the two divergent Razor trees in `AudioPlayerBar.razor` (`@if (_isDesk
|
|||||||
**Notes for future work:**
|
**Notes for future work:**
|
||||||
- First-render layout flash eliminated by construction (CSS media query evaluates at paint, not async subscription).
|
- First-render layout flash eliminated by construction (CSS media query evaluates at paint, not async subscription).
|
||||||
|
|
||||||
|
### Track Card Plain-Shell Refactor
|
||||||
|
|
||||||
|
**Landed 2026-06-05.**
|
||||||
|
|
||||||
|
Eliminated `!important` declarations from track card CSS by replacing MudBlazor surface components with plain HTML. Implemented per `product-notes/track-card-css-architecture.md` Option A.
|
||||||
|
|
||||||
|
**Razor changes (`DeepDrftShared.Client/Components/TrackCard.razor`):**
|
||||||
|
- `MudCard` → `<div class="deepdrft-track-card-container">`
|
||||||
|
- Fallback `MudPaper` → `<div class="deepdrft-track-card-fallback">`
|
||||||
|
- `MudCardContent` → `<div class="deepdrft-track-card-content">`
|
||||||
|
- `MudText`, `MudChip`, `MudFab` unchanged.
|
||||||
|
|
||||||
|
**CSS changes (`DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` §8):**
|
||||||
|
- Removed four `!important` declarations from `.deepdrft-track-card-container`, `.deepdrft-track-card-fallback` base, and the dark/light theme-scoped variants.
|
||||||
|
- Plain single-class selectors now win by cascade without `!important`; theme-scoped rules use normal specificity hierarchy.
|
||||||
|
|
||||||
|
**Scope:**
|
||||||
|
- `TrackCard` component in shared `DeepDrftShared.Client` consumed by both public site and CMS.
|
||||||
|
- CSS in `DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` (public site only).
|
||||||
|
- Build clean: 0 errors, 0 new warnings.
|
||||||
|
|
||||||
|
**Notes for future work:**
|
||||||
|
- Plain-div shell re-enables CSS isolation as an option (a `TrackCard.razor.css` would now work against the shell divs). Section 8's public-only scoping remains convenient; isolation is optional for future polish.
|
||||||
|
- Removes the structural mismatch of using a Material surface component (`MudCard`/`MudPaper`) solely as a layout shell. TrackCard now mirrors the construction of `NowPlayingCard` (plain divs + themed CSS).
|
||||||
|
|
||||||
**Status:** Desktop AudioPlayerBar redesign landed on 2026-06-04.
|
**Status:** Desktop AudioPlayerBar redesign landed on 2026-06-04.
|
||||||
|
|
||||||
### Desktop AudioPlayerBar — migrate to MudBlazor theme system
|
### Desktop AudioPlayerBar — migrate to MudBlazor theme system
|
||||||
|
|||||||
@@ -0,0 +1,446 @@
|
|||||||
|
# Track Card CSS Architecture — eliminate `!important` from section 8
|
||||||
|
|
||||||
|
Status: completed. Author: product-designer. Date: 2026-06-05. Implementer: daniel-c-harvey. Landed: 2026-06-05.
|
||||||
|
|
||||||
|
Predecessor: [`track-card-theming.md`](track-card-theming.md) (completed 2026-06-05) landed the
|
||||||
|
navy-glass + moss-green treatment and, in doing so, introduced the two `!important` rules this
|
||||||
|
spec exists to remove. That note is the *what it should look like*; this note is the *how the
|
||||||
|
CSS should be structured so it looks like that without `!important`*. Nothing here changes the
|
||||||
|
visual design — only the mechanism.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §1. Root cause analysis — why MudCard/MudPaper fight our CSS
|
||||||
|
|
||||||
|
### 1.1 The two `!important` rules in question
|
||||||
|
|
||||||
|
`DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` section 8:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.deepdrft-track-card-container { ... background: transparent !important; } /* line 222 */
|
||||||
|
.deepdrft-track-card-fallback { ... background: var(--deepdrft-navy-mid, #162437) !important; } /* line 268 */
|
||||||
|
.deepdrft-theme-dark .deepdrft-track-card-fallback { ... !important; } /* line 273 */
|
||||||
|
.deepdrft-theme-light .deepdrft-track-card-fallback { ... !important; } /* line 280 */
|
||||||
|
```
|
||||||
|
|
||||||
|
Four `!important` declarations, all on `background`, all on elements rendered by MudBlazor
|
||||||
|
(`MudCard` → container, `MudPaper` → fallback).
|
||||||
|
|
||||||
|
### 1.2 What MudBlazor paints and with what selector
|
||||||
|
|
||||||
|
MudBlazor ships a single global `<style>` block (injected by `MudThemeProvider`, served as
|
||||||
|
`_content/MudBlazor/MudBlazor.min.css`). The relevant rules are roughly:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.mud-paper {
|
||||||
|
background-color: var(--mud-palette-surface); /* the conflict */
|
||||||
|
color: var(--mud-palette-text-primary);
|
||||||
|
...
|
||||||
|
}
|
||||||
|
.mud-card { /* composes .mud-paper */ }
|
||||||
|
```
|
||||||
|
|
||||||
|
`MudCard` and `MudPaper` both render a root element carrying the `.mud-paper` class, and
|
||||||
|
`--mud-palette-surface` resolves to `DeepDrftPalettes.Surface` — `#162437` (navy-mid) in dark,
|
||||||
|
`#FAFAF8` (off-white) in light. So **every** track card root gets a painted surface color we do
|
||||||
|
not want, because we layer our own album-art div / fallback glass / scrim underneath the content.
|
||||||
|
|
||||||
|
### 1.3 Why our scoped CSS can't reach it and `!important` was the escape hatch
|
||||||
|
|
||||||
|
Two compounding facts:
|
||||||
|
|
||||||
|
1. **Specificity / source-order.** `.mud-paper { background-color: ... }` is a single class
|
||||||
|
selector (specificity `0,1,0`). Our `.deepdrft-track-card-container { background: ... }` is
|
||||||
|
*also* a single class selector (`0,1,0`). When specificity ties, **source order wins** — and
|
||||||
|
MudBlazor's stylesheet load order relative to `deepdrft-styles.css` is not something section 8
|
||||||
|
controls reliably (framework CSS, theme-injected CSS, and our sheet are separate links). To
|
||||||
|
guarantee we win regardless of order, the author reached for `!important`. That is the smell:
|
||||||
|
`!important` is being used to paper over an *ordering/specificity* uncertainty, not a genuine
|
||||||
|
need.
|
||||||
|
|
||||||
|
2. **CSS isolation cannot help here.** This is the deeper structural reason. Blazor scoped CSS
|
||||||
|
(`*.razor.css`) works by stamping a `b-<hash>` attribute onto elements *that Blazor renders*
|
||||||
|
and rewriting the scoped selector to `.foo[b-<hash>]` (specificity `0,2,0` — would beat
|
||||||
|
`.mud-paper`). But `MudCard`/`MudPaper` render their **own** inner HTML; Blazor never stamps
|
||||||
|
the scope attribute onto MudBlazor's internal elements. So a `TrackCard.razor.css` rule
|
||||||
|
targeting `.mud-paper` would compile to `.mud-paper[b-<hash>]` and match **nothing**. (This is
|
||||||
|
also why no `TrackCard.razor.css` exists today — it would be inert against the very elements
|
||||||
|
that need overriding.) The team correctly fell back to global rules in section 8 — but global
|
||||||
|
single-class rules don't beat MudBlazor without either higher specificity or `!important`.
|
||||||
|
|
||||||
|
**The fundamental mismatch:** we are using MudBlazor surface components (`MudCard`, `MudPaper`)
|
||||||
|
as *layout shells* while wanting to own their backgrounds entirely. MudBlazor's whole contract is
|
||||||
|
"I paint the surface from the palette." We are fighting the component's purpose. Every option
|
||||||
|
below is a different way to stop fighting it.
|
||||||
|
|
||||||
|
### 1.4 What we actually need from these two elements
|
||||||
|
|
||||||
|
Stripped to first principles, the container and fallback need:
|
||||||
|
- **Container:** a `position: relative`, fixed-size, `overflow: hidden` box. A *transparent*
|
||||||
|
stacking context so the album-art div, fallback glass, and content scrim layer correctly.
|
||||||
|
No surface paint, no Material elevation (already `Elevation="0"`), no ripple.
|
||||||
|
- **Fallback:** an absolutely-positioned full-bleed panel painted with our navy-glass (dark) or
|
||||||
|
navy-tint (light) treatment, with a border + `backdrop-filter`.
|
||||||
|
|
||||||
|
Neither needs anything MudBlazor's surface model provides. That observation drives the
|
||||||
|
recommendation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §2. Option A — Replace container + fallback with plain `<div>`
|
||||||
|
|
||||||
|
Drop `MudCard` → `<div class="deepdrft-track-card-container">` and the fallback `MudPaper` →
|
||||||
|
`<div class="deepdrft-track-card-fallback">`. Keep `MudCardContent`, `MudText`, `MudChip`,
|
||||||
|
`MudFab` (none of these own a competing background once the card root is a plain div — and the
|
||||||
|
text/chip/fab already work today).
|
||||||
|
|
||||||
|
**Note:** `MudCardContent` technically expects a `MudCard` ancestor, but it only emits a
|
||||||
|
`<div class="mud-card-content">` with padding — no background, no JS, no required parent context.
|
||||||
|
It renders fine inside a plain div. If we want zero MudBlazor coupling in the shell, it can also
|
||||||
|
become a plain `<div class="deepdrft-track-card-content">` (the class already carries all the
|
||||||
|
real styling — padding, flex, z-index, scrim). Recommend replacing it too, for consistency.
|
||||||
|
|
||||||
|
### Pros
|
||||||
|
- **Removes the conflict at the source.** No `.mud-paper` background means no `!important`
|
||||||
|
anywhere. Section 8 backgrounds become plain single-class rules that win by default.
|
||||||
|
- **Re-enables CSS isolation as an option.** With plain divs, a future `TrackCard.razor.css`
|
||||||
|
*would* work (Blazor stamps the scope attribute on divs it renders). We are not required to use
|
||||||
|
it — section 8's public-only scoping is still convenient per the predecessor note — but the door
|
||||||
|
reopens. This satisfies the "design the seam" instinct: we are not just fixing today, we are
|
||||||
|
removing a structural block.
|
||||||
|
- **Precedent already exists in this codebase.** `NowPlayingCard.razor` is built entirely from
|
||||||
|
plain `<div>`s with a `.razor.css` and achieves the *exact aesthetic these cards are imitating*.
|
||||||
|
This option makes TrackCard structurally consistent with the component it was told to match.
|
||||||
|
The two should be siblings in construction, not one Material and one hand-rolled.
|
||||||
|
- **Lighter DOM + less CSS the browser must override.** Removes `.mud-card` / `.mud-paper`
|
||||||
|
rulesets from applying to these nodes entirely.
|
||||||
|
|
||||||
|
### Cons — what MudBlazor functionality is lost
|
||||||
|
- **Elevation shadow:** already `Elevation="0"` on both elements (current Razor). Nothing lost —
|
||||||
|
the design explicitly moved to flat-glass (predecessor §3d). A plain div is the honest
|
||||||
|
expression of `Elevation="0"`.
|
||||||
|
- **Ripple:** `MudCard`/`MudPaper` do **not** ripple (ripple is a `MudButton`/`MudFab`/`MudIconButton`
|
||||||
|
behavior). The card is not clickable as a whole — the only interactive element is the `MudFab`,
|
||||||
|
which stays and keeps its ripple. Nothing lost.
|
||||||
|
- **ARIA / semantics:** `MudCard` renders a plain `<div>` with no implicit role — it adds no ARIA
|
||||||
|
semantics a plain div lacks. The card conveys meaning through its text content and the labeled
|
||||||
|
FAB, not through a container role. Nothing lost. (If anything, a future enhancement could add an
|
||||||
|
explicit `role`/`aria-label` to the div — easier on a plain element than fighting MudBlazor's.)
|
||||||
|
- **Theme reactivity of the surface color:** we *want* to lose this — the whole problem is that
|
||||||
|
MudBlazor repaints the surface from the palette. Our section-8 rules are already theme-aware via
|
||||||
|
`.deepdrft-theme-dark` / `-light` wrappers, so theme switching still works.
|
||||||
|
- **Migration cost:** ~6 lines of Razor changed. Trivial.
|
||||||
|
|
||||||
|
**Assessment:** acceptable in full. There is no MudBlazor capability the track-card shell actually
|
||||||
|
uses. This is the option that resolves the root cause rather than the symptom.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §3. Option B — Inline `Style="background: transparent"` on MudCard/MudPaper
|
||||||
|
|
||||||
|
Keep the MudBlazor components; pass an inline style to clear their background:
|
||||||
|
|
||||||
|
```razor
|
||||||
|
<MudCard Class="deepdrft-track-card-container" Elevation="0" Style="background: transparent;">
|
||||||
|
<MudPaper Class="deepdrft-track-card-fallback" Elevation="0" Style="background: transparent;">
|
||||||
|
```
|
||||||
|
|
||||||
|
Inline styles have specificity above any selector (and above `!important` from a stylesheet, for
|
||||||
|
non-`!important` inline declarations the inline wins over normal stylesheet rules; MudBlazor's
|
||||||
|
`.mud-paper` background is *not* `!important`, so inline transparent beats it cleanly).
|
||||||
|
|
||||||
|
But note: the fallback's *real* navy-glass paint then has to come from **somewhere**. If we set
|
||||||
|
the MudPaper transparent inline and paint via `.deepdrft-track-card-fallback` in CSS, we are
|
||||||
|
back to a CSS class trying to beat `.mud-paper` — except now `.mud-paper` is already transparent
|
||||||
|
(inline), so our class wins without `!important`. That works. The container is simpler: it just
|
||||||
|
wants transparent, which the inline gives directly.
|
||||||
|
|
||||||
|
### Pros
|
||||||
|
- No `!important`. Inline transparent neutralizes `.mud-paper`, then our classes paint normally.
|
||||||
|
- Smaller change than Option A (no element swap), keeps MudBlazor components if there's a reason
|
||||||
|
to (there isn't a strong one here).
|
||||||
|
- No risk of `MudCardContent`-without-`MudCard` edge cases.
|
||||||
|
|
||||||
|
### Cons
|
||||||
|
- **Scatters styling concern into Razor.** The whole point of section 8 is centralized,
|
||||||
|
theme-aware card styling. An inline `Style` on the component is a second place card appearance
|
||||||
|
is decided — exactly the maintenance split the team should avoid. Next person editing the card
|
||||||
|
background looks in section 8, doesn't find the override, and is confused.
|
||||||
|
- **Doesn't address the root mismatch.** We're still using a surface component as a layout shell
|
||||||
|
and then telling it "don't be a surface." It reads as an apology for the wrong component choice.
|
||||||
|
- **CSS isolation stays blocked** — MudBlazor still renders the inner HTML, so a `.razor.css`
|
||||||
|
still can't reach it. The seam stays closed.
|
||||||
|
- **Inline `transparent` is itself a quiet "magic override."** It's `!important` by another name —
|
||||||
|
a higher-specificity hammer applied at the element. Marginally cleaner than `!important` in a
|
||||||
|
sheet, but the same category of move: beating MudBlazor by force rather than not inviting the
|
||||||
|
fight.
|
||||||
|
|
||||||
|
**Assessment:** cleaner than `!important` strictly speaking, but trades one smell (sheet
|
||||||
|
`!important`) for a milder one (scattered inline overrides) and leaves the structural mismatch and
|
||||||
|
the blocked isolation seam intact. A lateral move, not a fix.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §4. Option C — Override `--mud-palette-surface` locally on the container
|
||||||
|
|
||||||
|
Scope a CSS custom-property override to the card so MudBlazor's own
|
||||||
|
`background-color: var(--mud-palette-surface)` resolves to transparent inside the card subtree:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.deepdrft-track-card-container {
|
||||||
|
--mud-palette-surface: transparent;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Because `.mud-paper` reads `var(--mud-palette-surface)` and custom properties inherit, both the
|
||||||
|
container's own paint and the nested `MudPaper` fallback would inherit the transparent value — no
|
||||||
|
`!important` needed (we're changing the *input* to MudBlazor's rule, not overriding the rule).
|
||||||
|
|
||||||
|
### Pros
|
||||||
|
- No `!important`, no inline styles, no element swap. One declaration.
|
||||||
|
- Works *with* MudBlazor's mechanism instead of against it — arguably the most "correct" CSS-vars
|
||||||
|
approach. We feed the palette variable the value we want for this subtree.
|
||||||
|
- Centralized in section 8.
|
||||||
|
|
||||||
|
### Cons
|
||||||
|
- **Blast radius is the whole subtree.** `--mud-palette-surface` is read by *many* MudBlazor
|
||||||
|
components, not just paper. Any MudBlazor component nested in the card that relies on
|
||||||
|
`--mud-palette-surface` (now or in future) silently renders transparent. Today the card nests
|
||||||
|
`MudChip` and `MudFab` — both read other palette vars (`--mud-palette-primary` etc.), but a
|
||||||
|
future addition (a `MudMenu`, a `MudTooltip` surface, a `MudPaper` accent) would inherit the
|
||||||
|
transparent surface and break subtly. This is a **spooky-action-at-a-distance** override: it
|
||||||
|
works today but plants a trap.
|
||||||
|
- **Fragile against MudBlazor internals.** It depends on `.mud-paper` continuing to read exactly
|
||||||
|
`--mud-palette-surface` for its background. If a MudBlazor version computes the surface
|
||||||
|
differently (e.g. a derived var, or `color-mix`), the override misses. Coupling our fix to a
|
||||||
|
framework implementation detail is a maintenance liability — the kind of thing that breaks on a
|
||||||
|
minor version bump with no compile error.
|
||||||
|
- **Still doesn't reopen CSS isolation.** Same as B — MudBlazor renders the HTML.
|
||||||
|
- **Obscure.** The next maintainer sees a card rendering transparent and has no obvious thread to
|
||||||
|
pull — the cause is a custom-property override three rules up, not a `background` declaration.
|
||||||
|
Low discoverability.
|
||||||
|
|
||||||
|
**Assessment:** the most elegant-looking, the most dangerous. It's a clever override that depends
|
||||||
|
on framework internals and leaks into every descendant. Reject for the trap it sets, despite the
|
||||||
|
aesthetics.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §5. Option D — Keep `!important` with a clear comment
|
||||||
|
|
||||||
|
Leave the four `!important`s, add a comment explaining the MudBlazor specificity conflict, accept
|
||||||
|
it as documented technical debt.
|
||||||
|
|
||||||
|
### Pros
|
||||||
|
- Zero change, zero risk. The cards render correctly today.
|
||||||
|
- A good comment turns a mystery smell into a known, explained trade-off — which is genuinely
|
||||||
|
better than an *unexplained* `!important`.
|
||||||
|
|
||||||
|
### Cons
|
||||||
|
- **Doesn't meet the stated goal.** The task is explicitly to *eliminate* `!important` from
|
||||||
|
section 8. Documenting it is not eliminating it.
|
||||||
|
- **`!important` is contagious.** Once the card backgrounds are `!important`, any future rule that
|
||||||
|
needs to legitimately override them (a "now playing" highlight state on a card, a selected
|
||||||
|
state, a hover treatment) must *also* be `!important`, escalating the war. The predecessor note
|
||||||
|
already floats a genre-chip treatment and skeleton tints — feature growth on this card is
|
||||||
|
expected, and each new state inherits the `!important` tax.
|
||||||
|
- **Leaves the structural mismatch and blocked isolation seam in place** — same as B and C.
|
||||||
|
|
||||||
|
**Assessment:** honest, but it's the do-nothing option dressed as a decision. Acceptable only if
|
||||||
|
all other options were blocked, which they are not. The comment is worth keeping *as a fallback*
|
||||||
|
if Option A is somehow rejected.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §6. Recommendation — Option A (plain `<div>` shell)
|
||||||
|
|
||||||
|
**Replace `MudCard` and the fallback `MudPaper` with plain `<div>`s. Replace `MudCardContent` with
|
||||||
|
a plain `<div>` too (it carries no behavior). Keep `MudText`, `MudChip`, `MudFab`.** This removes
|
||||||
|
all four `!important` declarations, preserves the glass-card aesthetic exactly (the section-8 paint
|
||||||
|
rules are unchanged except for dropping `!important`), is the most maintainable, and aligns
|
||||||
|
TrackCard structurally with `NowPlayingCard` — the very component it was designed to imitate.
|
||||||
|
|
||||||
|
Why A over the others, in one line each:
|
||||||
|
- **Over B (inline transparent):** A fixes the root mismatch and reopens the isolation seam; B
|
||||||
|
scatters overrides and leaves both problems.
|
||||||
|
- **Over C (palette-var override):** A has no blast radius and no coupling to MudBlazor internals;
|
||||||
|
C plants a transparent-surface trap for every future nested component.
|
||||||
|
- **Over D (keep `!important`):** A meets the stated goal; D doesn't.
|
||||||
|
|
||||||
|
Trade-off being accepted with A: TrackCard's shell stops being a MudBlazor component. That is a
|
||||||
|
*feature* here (the card never used MudBlazor's surface behavior), but it does mean the shell no
|
||||||
|
longer auto-reacts to a future palette change to `Surface` — which is exactly what we want, since
|
||||||
|
our theme-aware section-8 rules own the card's appearance. No real cost.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6.1 Exact Razor changes — `DeepDrftShared.Client/Components/TrackCard.razor`
|
||||||
|
|
||||||
|
Replace the current file body with the following. Only the three shell elements change
|
||||||
|
(`MudCard`→`div`, `MudPaper`→`div`, `MudCardContent`→`div`); all class hooks, `MudText`,
|
||||||
|
`MudChip`, and `MudFab` are preserved verbatim from the current file.
|
||||||
|
|
||||||
|
```razor
|
||||||
|
<div class="deepdrft-track-card-container">
|
||||||
|
|
||||||
|
@if (!string.IsNullOrEmpty(TrackModel?.ImagePath))
|
||||||
|
{
|
||||||
|
<div class="deepdrft-track-card-bg" style="background-image: url('@TrackModel.ImagePath');">
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="deepdrft-track-card-fallback"></div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="deepdrft-track-card-content">
|
||||||
|
|
||||||
|
<div class="deepdrft-track-info-top">
|
||||||
|
<MudText Typo="Typo.subtitle1"
|
||||||
|
Class="deepdrft-track-title text-truncate mb-1">
|
||||||
|
@TrackModel?.TrackName
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<MudText Typo="Typo.caption"
|
||||||
|
Class="deepdrft-track-artist text-truncate mb-2">
|
||||||
|
@TrackModel?.Artist
|
||||||
|
</MudText>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="deepdrft-track-info-middle">
|
||||||
|
@if (!string.IsNullOrEmpty(TrackModel?.Album))
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.caption"
|
||||||
|
Class="deepdrft-track-meta text-truncate">
|
||||||
|
@TrackModel.Album
|
||||||
|
</MudText>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (!string.IsNullOrEmpty(TrackModel?.Genre))
|
||||||
|
{
|
||||||
|
<MudChip T="string"
|
||||||
|
Size="Size.Small"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
Class="deepdrft-genre-chip">
|
||||||
|
@TrackModel.Genre
|
||||||
|
</MudChip>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="deepdrft-track-info-bottom">
|
||||||
|
@if (TrackModel?.ReleaseDate.HasValue == true)
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.caption"
|
||||||
|
Class="deepdrft-track-meta">
|
||||||
|
@TrackModel.ReleaseDate.Value.Year
|
||||||
|
</MudText>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div></div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<MudFab Color="Color.Primary"
|
||||||
|
Size="Size.Medium"
|
||||||
|
StartIcon="@PlayPauseIcon"
|
||||||
|
OnClick="@PlayClick"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
Changes, precisely:
|
||||||
|
- Line 1–2: `<MudCard Class="deepdrft-track-card-container" Elevation="0">` →
|
||||||
|
`<div class="deepdrft-track-card-container">`. (Drop `Elevation="0"` — meaningless on a div; the
|
||||||
|
flat look is the default.)
|
||||||
|
- Line 11–13: `<MudPaper Class="deepdrft-track-card-fallback" Elevation="0"></MudPaper>` →
|
||||||
|
`<div class="deepdrft-track-card-fallback"></div>`.
|
||||||
|
- Line 16: `<MudCardContent Class="deepdrft-track-card-content">` →
|
||||||
|
`<div class="deepdrft-track-card-content">`.
|
||||||
|
- Line 72 (`</MudCard>`) → `</div>`; the `</MudCardContent>` close (line 70) → `</div>`.
|
||||||
|
|
||||||
|
No change to `TrackCard.razor.cs` — it references no MudBlazor card types (only `Icons`,
|
||||||
|
`TrackDto`, `EventCallback`). The `using MudBlazor;` stays (still used by `Icons.Material`).
|
||||||
|
|
||||||
|
### 6.2 Exact CSS changes — `DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` section 8
|
||||||
|
|
||||||
|
Remove `!important` from all four declarations. No other change — the colors, layout, and
|
||||||
|
theme-aware scoping all stay exactly as they are.
|
||||||
|
|
||||||
|
**Line 216–223** — container:
|
||||||
|
```css
|
||||||
|
.deepdrft-track-card-container {
|
||||||
|
width: 250px;
|
||||||
|
height: 250px;
|
||||||
|
min-width: 250px;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background: transparent; /* was: transparent !important */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Line 262–269** — fallback base:
|
||||||
|
```css
|
||||||
|
.deepdrft-track-card-fallback {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: var(--deepdrft-navy-mid, #162437); /* was: ... !important */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Line 272–276** — fallback dark:
|
||||||
|
```css
|
||||||
|
.deepdrft-theme-dark .deepdrft-track-card-fallback {
|
||||||
|
background: color-mix(in srgb, var(--deepdrft-navy) 55%, transparent); /* was: ... !important */
|
||||||
|
border: 1px solid rgba(250, 250, 248, 0.12);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Line 279–282** — fallback light:
|
||||||
|
```css
|
||||||
|
.deepdrft-theme-light .deepdrft-track-card-fallback {
|
||||||
|
background: color-mix(in srgb, var(--deepdrft-navy) 8%, var(--deepdrft-white)); /* was: ... !important */
|
||||||
|
border: 1px solid var(--deepdrft-border);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After this change, the four backgrounds are plain single-class (and class-under-theme-wrapper)
|
||||||
|
rules painting plain `<div>`s. Nothing competes; nothing needs `!important`. The
|
||||||
|
`.deepdrft-theme-dark .deepdrft-track-card-fallback` selector is `0,2,0` and the base is `0,1,0`,
|
||||||
|
so the theme override correctly beats the base — the normal cascade, working as intended.
|
||||||
|
|
||||||
|
### 6.3 Verification checklist for the implementer
|
||||||
|
- Dark public site: card with album art shows art + scrim + green/off-white text; card without
|
||||||
|
art shows navy-glass fallback. No grey/teal surface flash on hydration (the base
|
||||||
|
`--deepdrft-navy-mid` fallback rule still covers the no-wrapper-class window).
|
||||||
|
- Light public site: fallback shows the navy-tint-on-white panel; text legible.
|
||||||
|
- Toggle dark/light: card repaints correctly (theme-wrapper-scoped rules still drive it).
|
||||||
|
- Confirm no other component references `.deepdrft-track-card-container` / `-fallback` expecting a
|
||||||
|
`.mud-paper` ancestor (grep — `TracksGallery.razor` wraps cards but only positions them via
|
||||||
|
`.deepdrft-track-gallery-item-center`).
|
||||||
|
- Confirm the rendered card root is now a plain `<div>` (devtools) with **no** `.mud-paper` /
|
||||||
|
`.mud-card` class, and that no `background ... !important` remains anywhere in section 8.
|
||||||
|
|
||||||
|
### 6.4 What this unblocks (not in scope, noted for the seam)
|
||||||
|
With a plain-div shell, the deferred polish items from the predecessor note become cleaner to
|
||||||
|
implement and could, if desired, migrate to a real `TrackCard.razor.css` (now functional):
|
||||||
|
genre-chip distinct treatment (predecessor §3a), skeleton tints (§3c), card hover/selected/now-
|
||||||
|
playing states. None are required by this spec; flagged so a future pass knows the seam is open.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §7. Fallback position
|
||||||
|
|
||||||
|
If Option A is rejected for a reason not surfaced here (e.g. a policy that shell components must
|
||||||
|
remain MudBlazor for consistency with other cards), the next-best is **Option D with comments** —
|
||||||
|
not B or C. B scatters the override and C couples to framework internals; a *documented*
|
||||||
|
`!important` is more honest and more maintainable than either clever hack. But A has no real cost
|
||||||
|
identified, so this fallback should not be needed.
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user