Changeset abd2093 in Klonkt


Ignore:
Timestamp:
08/16/2026 12:23:45 PM (3 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
a982e7e
Parents:
bec9001
Message:

Beheer: audio en playlists ook op de gedeelde ax-romp

Mijn regressie van de vorige commit: ik haalde de opmaak van de tabbalk
uit media-tabs.ejs en zette hem in de partial, maar audio en playlists
nemen die partial niet op. Hun tabbalk stond er dus wel in de markup en
had geen enkele regel CSS -- vijf kale links, en de pagina zat er niet
meer onder.

Beide pagina's nemen de partial nu op, boven hun eigen style-blok zodat
wat daar blijft staan later komt en dus wint.

En daarmee kon het ontdubbelen alsnog, maar nu met een echte ontleding:
scripts/admin-css.mjs leest de tekens een voor een en kent commentaar,
tekenreeksen en geneste blokken. Dat was nodig -- mijn regex van
vanochtend telde @media-varianten als losse regels en commentaar als
selector, en zat er voor playlists 7 regels naast. Twee fouten zaten ook
in de eerste versie van dit script: /* Mobiel */ voor een @media maakte
het blok onherkenbaar, en geneste regels droegen posities uit hun
binnentekst -- daarmee had het weghalen de verkeerde bytes geknipt.

Weg: 27 regels uit admin-audio, 34 uit admin-playlists. Wat afwijkt
blijft staan en wordt gemeld (audio heeft 10 eigen varianten, playlists
2).

scripts/admin-css-gelijk.mjs is het bewijs: hij rendert elke pagina nu
en zoals hij was, rekent per (media-context, selector) uit wat er
uiteindelijk geldt, en legt de twee naast elkaar. Uitkomst over alle
vijf: geen regel verdwenen, geen regel veranderd, en op audio en
playlists 21 resp. 22 regels erbij -- de tabbalk voorop.

Dat audio en playlists nu ook .ax-grid en .ax-tile meekrijgen die ze niet
gebruiken, is de prijs van een gedeelde partial. Een paar honderd bytes.

Co-Authored-By: Claude Opus 5 <noreply@…>

Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • src/views/pages/admin-audio.ejs

    rbec9001 rabd2093  
     1<%# De gedeelde ax-*-primitieven. MOET boven het eigen style-blok van deze
     2    pagina staan: wat hieronder blijft staan wijkt bewust af en hoort dus
     3    later te komen, anders wint de partial ervan. %>
     4<%- include('../partials/admin-styles') %>
    15<div class="container ax-page">
    26
     
    150154  padding: 0 1rem;
    151155}
    152 .ax-header {
    153   display: flex; align-items: flex-start; gap: 0.75rem;
    154   margin-bottom: 1.5rem;
    155 }
    156 .ax-header h1 {
    157   font-family: var(--font-display, serif);
    158   font-size: 1.75rem;
    159   margin: 0 0 0.25rem;
    160 }
    161 .ax-tagline {
    162   color: var(--ink-muted, var(--ink-soft));
    163   margin: 0;
    164   font-size: 0.9rem;
    165   line-height: 1.5;
    166 }
    167 .ax-tagline code {
    168   background: var(--paper-2);
    169   padding: 0.1em 0.4em;
    170   border-radius: 4px;
    171   font-size: 0.9em;
    172 }
    173 .ax-back {
    174   display: inline-flex; align-items: center; justify-content: center;
    175   width: 40px; height: 40px;
    176   border: 1px solid var(--rule);
    177   border-radius: 8px;
    178   background: var(--paper);
    179   color: var(--ink);
    180   text-decoration: none;
    181   font-size: 1.1rem;
    182   flex-shrink: 0;
    183   transition: border-color 120ms;
    184 }
    185 .ax-back:hover { border-color: var(--accent); }
    186 
    187 /* ─── Flash messages ───────────────────────────────────────────── */
    188 .ax-flash {
    189   padding: 0.75rem 1rem;
    190   border-radius: 8px;
    191   margin-bottom: 1rem;
    192   font-size: 0.9rem;
    193 }
    194 .ax-flash-ok  { background: rgba(40,160,90,.15); color: #2a9d5e; border: 1px solid rgba(40,160,90,.3); }
    195 .ax-flash-err { background: rgba(200,60,60,.15); color: #c33;    border: 1px solid rgba(200,60,60,.3); }
    196 
    197 /* ─── Card sections ────────────────────────────────────────────── */
    198 .ax-card {
    199   background: var(--paper);
    200   border: 1px solid var(--rule);
    201   border-radius: 12px;
    202   padding: 1.25rem;
    203   margin-bottom: 1rem;
    204 }
    205156.ax-card-title {
    206157  font-family: var(--font-display, serif);
     
    319270  -webkit-tap-highlight-color: transparent;
    320271}
    321 .ax-btn:hover { border-color: var(--accent); }
    322 .ax-btn-secondary { background: var(--paper-2); }
    323 .ax-btn-primary {
    324   background: var(--accent); color: white;
    325   border-color: var(--accent);
    326 }
    327 .ax-btn-primary:hover { opacity: 0.92; border-color: var(--accent); }
    328 
    329 /* Tiny icon-only button for row actions */
    330 .ax-icon-btn {
    331   display: inline-flex; align-items: center; justify-content: center;
    332   width: 40px; height: 40px;
    333   border: 1px solid var(--rule);
    334   background: var(--paper-2);
    335   color: var(--ink);
    336   border-radius: 8px;
    337   cursor: pointer;
    338   font-size: 1rem;
    339   transition: background 120ms, border-color 120ms, color 120ms;
    340 }
    341 .ax-icon-btn:hover { border-color: var(--accent); }
    342 .ax-icon-btn-danger:hover { color: #dc2626; border-color: #dc2626; }
    343272
    344273.ax-track-play.is-playing {
     
    348277}
    349278.ax-track-play-icon { font-size: 0.85rem; line-height: 1; }
    350 
    351 /* ─── Empty state ──────────────────────────────────────────────── */
    352 .ax-empty {
    353   text-align: center;
    354   padding: 2rem 1rem;
    355   color: var(--ink-muted, var(--ink-soft));
    356 }
    357279.ax-empty-icon {
    358280  font-size: 2.5rem;
     
    362284  margin-bottom: 0.5rem;
    363285}
    364 .ax-empty p { margin: 0; }
    365 
    366 /* ─── Track list (card per row) ────────────────────────────────── */
    367 .ax-list {
    368   list-style: none; padding: 0; margin: 0;
    369   display: flex; flex-direction: column;
    370   gap: 0.6rem;
    371 }
    372286.ax-track {
    373287  display: grid;
     
    381295  transition: border-color 120ms;
    382296}
    383 .ax-track:hover { border-color: var(--accent); }
    384297.ax-track-cover {
    385298  width: 56px; height: 56px;
     
    411324  display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center;
    412325}
    413 .ax-track-sep { opacity: 0.5; }
    414326.ax-embed {
    415327  display: inline-block;
     
    427339  transition: background 120ms;
    428340}
    429 .ax-embed:hover { background: var(--rule); }
    430 .ax-embed.is-copied { background: rgba(40,160,90,0.2); color: #2a9d5e; }
    431 
    432 .ax-track-actions {
    433   display: flex; gap: 0.4rem;
    434   flex-shrink: 0;
    435 }
    436341.ax-track-delete { display: inline; }
    437342
     
    444349  }
    445350  .ax-track-cover { grid-area: cover; width: 48px; height: 48px; }
    446   .ax-track-meta  { grid-area: meta; }
    447   .ax-track-actions {
    448     grid-area: actions;
    449     justify-content: flex-end;
    450     border-top: 1px solid var(--rule);
    451     padding-top: 0.5rem;
    452     margin-top: 0.25rem;
    453   }
    454351}
    455352
  • src/views/pages/admin-playlists.ejs

    rbec9001 rabd2093  
    55const _csrf = (typeof csrfToken !== 'undefined' && csrfToken) || '';
    66%>
     7<%# De gedeelde ax-*-primitieven. MOET boven het eigen style-blok van deze
     8    pagina staan: wat hieronder blijft staan wijkt bewust af en hoort dus
     9    later te komen, anders wint de partial ervan. %>
     10<%- include('../partials/admin-styles') %>
    711<div class="container ax-page">
    812
     
    8387
    8488.ax-page { max-width: 880px; margin: 1.5rem auto 4rem; padding: 0 1rem; }
    85 .ax-header { display: flex; align-items: flex-start; gap: 0.75rem; margin-bottom: 1.5rem; }
    86 .ax-header h1 { font-family: var(--font-display, serif); font-size: 1.75rem; margin: 0 0 0.25rem; }
    87 .ax-tagline { color: var(--ink-muted, var(--ink-soft)); margin: 0; font-size: 0.9rem; line-height: 1.5; }
    88 .ax-tagline code { background: var(--paper-2); padding: 0.1em 0.4em; border-radius: 4px; font-size: 0.9em; }
    89 .ax-back {
    90   display: inline-flex; align-items: center; justify-content: center;
    91   width: 40px; height: 40px;
    92   border: 1px solid var(--rule); border-radius: 8px;
    93   background: var(--paper); color: var(--ink); text-decoration: none;
    94   font-size: 1.1rem; flex-shrink: 0; transition: border-color 120ms;
    95 }
    96 .ax-back:hover { border-color: var(--accent); }
    97 
    98 .ax-actions-bar {
    99   display: flex;
    100   margin-bottom: 1rem;
    101 }
    102 
    103 .ax-card {
    104   background: var(--paper);
    105   border: 1px solid var(--rule);
    106   border-radius: 12px;
    107   padding: 1.25rem;
    108   margin-bottom: 1rem;
    109 }
    110 
    111 /* ─── Buttons (same primitives as admin-audio) ─────────────────── */
    112 .ax-btn {
    113   display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
    114   padding: 0.6rem 1.1rem;
    115   border: 1px solid var(--rule); background: var(--paper-2);
    116   color: var(--ink);
    117   font-family: var(--font-ui, system-ui), sans-serif;
    118   font-size: 0.95rem; font-weight: 500;
    119   text-decoration: none; border-radius: 8px; cursor: pointer;
    120   min-height: 44px;
    121   transition: background 120ms, border-color 120ms;
    122   -webkit-tap-highlight-color: transparent;
    123 }
    124 .ax-btn:hover { border-color: var(--accent); }
    125 .ax-btn-primary { background: var(--accent); color: white; border-color: var(--accent); }
    12689.ax-btn-primary:hover { opacity: 0.92; }
    127 
    128 .ax-icon-btn {
    129   display: inline-flex; align-items: center; justify-content: center;
    130   width: 40px; height: 40px;
    131   border: 1px solid var(--rule); border-radius: 8px;
    132   background: var(--paper-2); color: var(--ink);
    133   cursor: pointer; font-size: 1rem;
    134   transition: background 120ms, border-color 120ms, color 120ms;
    135 }
    136 .ax-icon-btn:hover { border-color: var(--accent); }
    137 .ax-icon-btn-danger:hover { color: #dc2626; border-color: #dc2626; }
    138 
    139 /* ─── Empty state ──────────────────────────────────────────────── */
    140 .ax-empty { text-align: center; padding: 2rem 1rem; color: var(--ink-muted, var(--ink-soft)); }
    141 .ax-empty-icon { font-size: 2.5rem; margin-bottom: 0.5rem; opacity: 0.5; }
    142 .ax-empty p { margin: 0; }
    143 .ax-empty-sub { font-size: 0.85rem; margin-top: 0.5rem !important; }
    144 
    145 /* ─── List items (same as audio tracks) ───────────────────────── */
    146 .ax-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.6rem; }
    147 .ax-track {
    148   display: grid;
    149   grid-template-columns: 64px 1fr auto;
    150   gap: 0.85rem; align-items: center;
    151   padding: 0.85rem;
    152   background: var(--paper);
    153   border: 1px solid var(--rule);
    154   border-radius: 12px;
    155   transition: border-color 120ms;
    156 }
    157 .ax-track:hover { border-color: var(--accent); }
    15890.ax-track-cover {
    15991  width: 64px; height: 64px; border-radius: 8px;
     
    16496  flex-shrink: 0;
    16597}
    166 .ax-track-meta { min-width: 0; display: flex; flex-direction: column; gap: 0.25rem; }
    167 .ax-track-title {
    168   font-family: var(--font-display, serif);
    169   font-weight: 600; font-size: 1.05rem; color: var(--ink);
    170   display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap;
    171 }
    172 .ax-pill {
    173   font-family: var(--font-ui);
    174   font-size: 0.7rem; font-weight: 500;
    175   color: var(--ink-soft);
    176   background: var(--paper-2);
    177   padding: 0.15em 0.55em; border-radius: 999px;
    178   letter-spacing: 0;
    179 }
    180 .ax-track-sub {
    181   font-size: 0.85rem;
    182   color: var(--ink-muted, var(--ink-soft));
    183   display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center;
    184 }
    185 .ax-track-sep { opacity: 0.5; }
    186 .ax-embed {
    187   display: inline-block;
    188   background: var(--paper-2);
    189   padding: 0.15rem 0.5rem;
    190   border-radius: 4px;
    191   font-family: var(--font-mono, ui-monospace, monospace);
    192   font-size: 0.75rem;
    193   color: var(--ink-soft);
    194   cursor: pointer; user-select: all;
    195   margin-top: 0.15rem;
    196   word-break: break-all;
    197   align-self: flex-start;
    198   transition: background 120ms;
    199 }
    200 .ax-embed:hover { background: var(--rule); }
    201 .ax-embed.is-copied { background: rgba(40,160,90,0.2); color: #2a9d5e; }
    202 
    203 .ax-track-actions { display: flex; gap: 0.4rem; flex-shrink: 0; }
    20498
    20599/* ─── Mobile ──────────────────────────────────────────────────── */
    206100@media (max-width: 480px) {
    207   .ax-track {
    208     grid-template-columns: 56px 1fr;
    209     grid-template-areas: "cover meta" "actions actions";
    210     gap: 0.6rem;
    211   }
    212   .ax-track-cover { grid-area: cover; width: 56px; height: 56px; }
    213   .ax-track-meta  { grid-area: meta; }
    214   .ax-track-actions {
    215     grid-area: actions;
    216     justify-content: flex-end;
    217     border-top: 1px solid var(--rule);
    218     padding-top: 0.5rem;
    219     margin-top: 0.25rem;
    220   }
    221101}
    222102</style>
  • src/views/partials/admin-styles.ejs

    rbec9001 rabd2093  
    204204.ax-tile-badge-r { left: auto; right: 6px; background: rgba(0,0,0,.6); }
    205205
    206 /* ─── Mobiel ───────────────────────────────────────────────────── */
    207206@media (max-width: 480px) {
    208207  .ax-track {
Note: See TracChangeset for help on using the changeset viewer.