Changeset 39dab6b in Klonkt for src/assets
- Timestamp:
- 08/12/2026 09:43:20 PM (3 months ago)
- Children:
- 5e0fea7
- Parents:
- 2086ea2
- Location:
- src/assets
- Files:
-
- 1 added
- 3 edited
-
css/ward.css (modified) (10 diffs)
-
js/ward-sky.js (modified) (3 diffs)
-
js/ward-theme.js (added)
-
js/ward.js (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/assets/css/ward.css
r2086ea2 r39dab6b 6 6 --dim: #9aa7bb; 7 7 --accent: #5a32e6; 8 --on-accent: #ffffff; 9 --bg-top: #1a2233; 10 --bg-bottom: #0d1017; 8 11 --alarm: #ef9f27; 9 12 --ok: #46c26a; … … 17 20 body { 18 21 margin: 0; padding: 16px calc(16px + env(safe-area-inset-right)) 32px calc(16px + env(safe-area-inset-left)); 19 background: var(--bg); color: var(--ink); 22 background: linear-gradient(var(--bg-top), var(--bg-bottom)) fixed, var(--bg); 23 color: var(--ink); 20 24 font: 16px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; 21 25 } … … 27 31 .help button { 28 32 width: 100%; padding: 18px; border: 0; border-radius: 14px; 29 background: var(--accent); color: #fff; font-size: 1.1rem; font-weight: 600;33 background: var(--accent); color: var(--on-accent); font-size: 1.1rem; font-weight: 600; 30 34 } 31 35 .help button:disabled { background: #3a3f4d; color: var(--dim); } … … 50 54 51 55 /* ── De feed ──────────────────────────────────────────────────────────── */ 52 .cards { display: grid; gap: 12px; }53 56 .post { background: var(--card); border-radius: 12px; padding: 12px 14px; border: 2px solid transparent; } 54 57 .post .avatar { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; } … … 84 87 dialog#help-dialog menu { display: flex; gap: 8px; justify-content: flex-end; margin: 14px 0 0; padding: 0; } 85 88 dialog#help-dialog button { border: 0; border-radius: 10px; padding: 10px 14px; background: #2a3342; color: var(--ink); font: inherit; } 86 dialog#help-dialog button.primary { background: var(--accent); color: #fff; font-weight: 600; }89 dialog#help-dialog button.primary { background: var(--accent); color: var(--on-accent); font-weight: 600; } 87 90 88 91 /* Voor schermlezers, niet voor het oog. */ … … 138 141 background: #131a25; color: var(--ink); padding: 10px 16px; font: inherit; 139 142 } 140 #thread-form button { border: 0; border-radius: 999px; padding: 10px 18px; background: var(--accent); color: #fff; font: inherit; font-weight: 600; }143 #thread-form button { border: 0; border-radius: 999px; padding: 10px 18px; background: var(--accent); color: var(--on-accent); font: inherit; font-weight: 600; } 141 144 142 145 /* ── Het zwaai-paneel ─────────────────────────────────────────────────── */ … … 148 151 dialog#wave-dialog h2 { margin: 0 0 12px; font-size: 1.05rem; } 149 152 .wave-answers { display: grid; gap: 8px; } 150 .wave-answers button { border: 0; border-radius: 10px; padding: 12px; background: var(--accent); color: #fff; font: inherit; font-weight: 600; }153 .wave-answers button { border: 0; border-radius: 10px; padding: 12px; background: var(--accent); color: var(--on-accent); font: inherit; font-weight: 600; } 151 154 #wave-cancel { margin-top: 10px; border: 0; background: none; color: var(--dim); font: inherit; } 152 155 … … 170 173 .feed-head { display: flex; align-items: center; gap: 12px; } 171 174 .feed-head h2 { margin: 24px 0 10px; } 172 #compose-open { margin-left: auto; border: 0; border-radius: 999px; padding: 8px 16px; background: var(--accent); color: #fff; font: inherit; font-weight: 600; }175 #compose-open { margin-left: auto; border: 0; border-radius: 999px; padding: 8px 16px; background: var(--accent); color: var(--on-accent); font: inherit; font-weight: 600; } 173 176 174 177 dialog#compose-dialog { … … 180 183 .compose-head #compose-cancel { border: 0; background: #2a3342; color: var(--ink); border-radius: 10px; padding: 8px 12px; font-size: 1rem; } 181 184 .compose-head #compose-vis { flex: 1; border-radius: 10px; border: 1px solid #2a3342; background: #131a25; color: var(--ink); padding: 8px; font: inherit; } 182 .compose-head .primary { border: 0; border-radius: 10px; padding: 8px 16px; background: var(--accent); color: #fff; font: inherit; font-weight: 600; }185 .compose-head .primary { border: 0; border-radius: 10px; padding: 8px 16px; background: var(--accent); color: var(--on-accent); font: inherit; font-weight: 600; } 183 186 .compose-head .primary:disabled { background: #3a3f4d; color: var(--dim); } 184 187 #compose-text { width: 100%; border-radius: 12px; border: 1px solid #2a3342; background: #131a25; color: var(--ink); padding: 10px; font: inherit; resize: vertical; } … … 192 195 .compose-tools .tool { font-size: 1.4rem; cursor: pointer; padding: 4px 8px; border-radius: 10px; background: #131a25; } 193 196 .compose-tools .hint { margin-left: auto; } 197 198 /* ── Het kaartraster: meer kolommen naarmate er ruimte is ─────────────── */ 199 /* Robins wens (12-8): op desktop net als op mobiel en tablet MEERDERE 200 kolommen. auto-fill met een minimum vult zelf op: één kolom op een smalle 201 telefoon, twee op een tablet, drie of meer op een breed scherm. */ 202 .cards { 203 display: grid; 204 grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); 205 gap: 12px; 206 align-items: start; 207 } 208 209 /* ── De mini-speler ───────────────────────────────────────────────────── */ 210 #mini-player { 211 position: fixed; left: 12px; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom)); 212 z-index: 45; display: flex; align-items: center; gap: 10px; 213 padding: 8px 12px; border-radius: 14px; 214 background: var(--card); box-shadow: 0 6px 24px rgba(0,0,0,.4); 215 max-width: 520px; margin: 0 auto; 216 } 217 #mini-player #mini-toggle { border: 0; border-radius: 50%; width: 40px; height: 40px; background: var(--accent); color: var(--on-accent); font-size: 1rem; } 218 #mini-player #mini-title { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } 219 #mini-player #mini-close { border: 0; background: none; color: var(--dim); font-size: 1rem; } 220 221 /* ── De themakiezer ───────────────────────────────────────────────────── */ 222 .icon-btn { border: 0; background: #2a3342; border-radius: 999px; width: 38px; height: 38px; font-size: 1.1rem; } 223 dialog#theme-dialog { 224 border: 0; border-radius: 16px; padding: 18px; max-width: 320px; width: calc(100% - 48px); 225 background: var(--card); color: var(--ink); text-align: center; 226 } 227 dialog#theme-dialog::backdrop { background: rgba(0,0,0,.4); } 228 dialog#theme-dialog h2 { margin: 0 0 14px; font-size: 1.05rem; } 229 .swatches { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; } 230 .swatch { width: 100%; aspect-ratio: 1; border: 3px solid transparent; border-radius: 50%; cursor: pointer; } 231 .swatch.chosen { border-color: var(--ink); } 232 #theme-close { margin-top: 14px; border: 0; background: none; color: var(--dim); font: inherit; } -
src/assets/js/ward-sky.js
r2086ea2 r39dab6b 99 99 100 100 /** Eén canvas met alle avatars naast elkaar, zodat tekenen één drawImage is. */ 101 async function buildAtlas(faces ) {101 async function buildAtlas(faces, accent) { 102 102 const size = FACE * 2; // retina-scherp 103 103 const cols = Math.max(1, Math.ceil(Math.sqrt(faces.length || 1))); … … 120 120 g.save(); 121 121 g.beginPath(); g.arc(x + size / 2, y + size / 2, size / 2, 0, Math.PI * 2); g.clip(); 122 g.fillStyle = '#5a32e6'; g.fillRect(x, y, size, size);122 g.fillStyle = accent || '#5a32e6'; g.fillRect(x, y, size, size); 123 123 g.fillStyle = '#fff'; 124 124 g.font = `600 ${size * 0.45}px system-ui, sans-serif`; … … 176 176 this.faces = faces; 177 177 this.spots = orbitPlacement(faces.map((f) => f.ageMs)); 178 this.atlas = await buildAtlas(faces );178 this.atlas = await buildAtlas(faces, this._accent()); 179 179 this._resize(); 180 } 181 182 /** De themakleur uit de CSS-variabele, voor de placeholder-schijfjes. */ 183 _accent() { 184 return getComputedStyle(document.documentElement).getPropertyValue('--accent').trim() || '#5a32e6'; 185 } 186 187 /** Het thema veranderde: de letters-op-schijf opnieuw in het nieuwe accent. */ 188 async reskin() { 189 if (this.faces.length) this.atlas = await buildAtlas(this.faces, this._accent()); 180 190 } 181 191 -
src/assets/js/ward.js
r2086ea2 r39dab6b 8 8 */ 9 9 import { SkyRenderer } from '/ward/sky.js'; 10 import { PRESETS, loadColor, saveColor, applyColor } from '/ward/theme.js'; 10 11 11 12 const state = JSON.parse(document.getElementById('ward-state').textContent); 13 14 // De opgeslagen themakleur meteen toepassen, voor het eerste frame. 15 applyColor(loadColor()); 12 16 const $ = (id) => document.getElementById(id); 13 17 … … 421 425 } catch { /* zonder hemel blijft het scherm gewoon werken */ } 422 426 })(); 427 428 // De hemel skint zijn placeholder-schijfjes bij als de themakleur wisselt. 429 window.addEventListener('ward-accent', () => sky.reskin()); 423 430 } 424 431 … … 515 522 } 516 523 517 /** De controle kost per guardian een remote fetch, dus hij komt ná het tekenen. */ 524 /** 525 * De themakiezer (SkyPalette): acht presets, gekozen kleur kleurt alles. 526 * Een rij swatches in een dialoog; de keuze staat meteen en blijft bewaard. 527 */ 528 function wireTheme() { 529 const dlg = document.getElementById('theme-dialog'); 530 const row = document.getElementById('theme-swatches'); 531 const current = loadColor(); 532 row.replaceChildren(); 533 PRESETS.forEach((rgb) => { 534 const b = el('button', 'swatch'); 535 b.type = 'button'; 536 b.style.background = '#' + rgb.toString(16).padStart(6, '0'); 537 b.setAttribute('aria-label', 'kleur ' + rgb.toString(16)); 538 if (rgb === current) b.classList.add('chosen'); 539 b.addEventListener('click', () => { 540 saveColor(rgb); 541 row.querySelectorAll('.swatch').forEach((s) => s.classList.remove('chosen')); 542 b.classList.add('chosen'); 543 // De hemel tekent de placeholder-schijfjes in het accent; even opnieuw. 544 window.dispatchEvent(new CustomEvent('ward-accent')); 545 }); 546 row.append(b); 547 }); 548 document.getElementById('theme-open').addEventListener('click', () => dlg.showModal()); 549 document.getElementById('theme-close').addEventListener('click', () => dlg.close()); 550 } 551 552 /** 553 * De mini-speler: audio blijft doorspelen terwijl je scrolt of van stand 554 * wisselt. 555 * 556 * Een feed-kaart rendert een gewone <audio>, maar de feed wordt bij elke 557 * verversing opnieuw getekend en dan sterft dat element -- de muziek stopt 558 * midden in een nummer. Daarom is er ÉÉN blijvende speler buiten de feed; een 559 * audiotegel geeft alleen zijn bron door en pauzeert zichzelf. Zo overleeft 560 * het geluid een herteken en een wissel naar de hemel, precies als in de app. 561 */ 562 function wireMiniPlayer() { 563 const bar = document.getElementById('mini-player'); 564 const audio = document.getElementById('mini-audio'); 565 const title = document.getElementById('mini-title'); 566 const toggle = document.getElementById('mini-toggle'); 567 568 // Vangen in de CAPTURE-fase: zodra een feed-audio wil spelen, neemt de 569 // gedeelde speler het over. Delegatie op document, want de kaarten komen en 570 // gaan. 571 document.addEventListener('play', (e) => { 572 const t = e.target; 573 if (!(t instanceof HTMLAudioElement) || t === audio) return; 574 e.preventDefault(); 575 t.pause(); 576 const card = t.closest('.post'); 577 title.textContent = card?.querySelector('.name')?.textContent || 'Audio'; 578 if (audio.src !== new URL(t.currentSrc || t.src, location.href).href) { 579 audio.src = t.currentSrc || t.src; 580 } 581 audio.play().catch(() => {}); 582 bar.hidden = false; 583 }, true); 584 585 toggle.addEventListener('click', () => { audio.paused ? audio.play() : audio.pause(); }); 586 audio.addEventListener('play', () => { toggle.textContent = '⏸'; }); 587 audio.addEventListener('pause', () => { toggle.textContent = '▶'; }); 588 audio.addEventListener('ended', () => { bar.hidden = true; }); 589 document.getElementById('mini-close').addEventListener('click', () => { audio.pause(); bar.hidden = true; }); 590 } 591 592 /** De controle kost per guardian een remote fetch, dus hij komt ná het tekenen. *//** De controle kost per guardian een remote fetch, dus hij komt ná het tekenen. */ 518 593 async function loadChecks() { 519 594 if (!state.guardians.length) return; … … 542 617 wireSky(); 543 618 wireComposer(); 619 wireTheme(); 620 wireMiniPlayer(); 544 621 loadFeed(); 545 622 renderOffers();
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)