A music player that connects to your cloud/distributed storage.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: dashboard grid design improvements

+71 -27
+2 -4
src/_components/grid.vto
··· 34 34 35 35 <li 36 36 class="grid-item" 37 + style="--grid-item-color: {{color}}" 37 38 data-active-color="{{color}}" 38 39 data-description="{{item.desc.trim()}}" 39 40 data-name="{{item.title}}" ··· 42 43 data-tags="{{ item.tags?.join(',') ?? `` }}" 43 44 data-uri="{{ facetUri }}" 44 45 > 45 - <div 46 - class="grid-item__contents" 47 - style="--grid-item-color: {{color}}" 48 - > 46 + <div class="grid-item__contents"> 49 47 <div class="grid-item__title"> 50 48 {{ if item.kind === "prelude" }} 51 49 <span style="color: {{ color }}; padding: var(--space-3xs) 0">
+16 -10
src/common/pages/dashboard.js
··· 1 1 import { html, render } from "lit-html"; 2 + import { classMap } from "lit-html/directives/class-map.js"; 2 3 import { keyed } from "lit-html/directives/keyed.js"; 3 4 import { marked } from "marked"; 4 5 import { unsafeHTML } from "lit-html/directives/unsafe-html.js"; ··· 202 203 return keyed( 203 204 c.id, 204 205 html` 205 - <li class="grid-item" ?data-disabled="${!(c.enabled ?? true)}"> 206 - <div 207 - class="grid-item__contents" 208 - style="--grid-item-color: ${color}" 209 - > 206 + <li 207 + class="grid-item" 208 + style="--grid-item-color: ${color}" 209 + ?data-disabled="${!(c.enabled ?? true)}" 210 + > 211 + <div class="grid-item__contents"> 210 212 <div class="grid-item__title" style="color: ${color}"> 211 213 ${title} 212 214 </div> ··· 237 239 </div> 238 240 </div> 239 241 240 - <div class="grid-item__menu"> 242 + <div class="grid-item__menu ${classMap({ 243 + "grid-item__menu--active": c.enabled ?? true, 244 + })}"> 241 245 <button 242 246 class="button--transparent" 243 247 title="${(c.enabled ?? true) ··· 247 251 : "Light"}" 248 252 @click="${toggleFacetEnabled({ id: c.id })}" 249 253 > 250 - <i class="ph-bold ${(c.enabled ?? true) 251 - ? c.kind === "prelude" ? "ph-lightning" : "ph-eye" 254 + <i class="${(c.enabled ?? true) 255 + ? c.kind === "prelude" 256 + ? "ph-fill ph-lightning" 257 + : "ph-fill ph-eye" 252 258 : c.kind === "prelude" 253 - ? "ph-lightning-slash" 254 - : "ph-eye-slash"}"></i> 259 + ? "ph-bold ph-lightning-slash" 260 + : "ph-bold ph-eye-slash"}"></i> 255 261 </button> 256 262 <hr /> 257 263 <button
+19 -13
src/common/pages/grid.js
··· 94 94 item.hidden = !isBase; 95 95 } else { 96 96 const kindMatch = kind === "all" || item.dataset.kind === kind; 97 - const catMatch = category === "all" || item.dataset.category === category; 97 + const catMatch = category === "all" || 98 + item.dataset.category === category; 98 99 item.hidden = !(kindMatch && catMatch && !isBase); 99 100 } 100 101 }); ··· 109 110 }); 110 111 111 112 const storedKind = localStorage.getItem(FILTER_KIND_STORAGE_KEY); 112 - activeKind = 113 - storedKind === "prelude" || storedKind === "interface" || 113 + activeKind = storedKind === "prelude" || storedKind === "interface" || 114 114 storedKind === "base" 115 - ? storedKind 116 - : "all"; 115 + ? storedKind 116 + : "all"; 117 117 activeCategory = new URL(location.href).searchParams.get("category") ?? "all"; 118 118 applyFilter(activeKind, activeCategory); 119 119 } ··· 150 150 if (isActive) { 151 151 out.facets.save(collection.filter((f) => f.uri !== uri)); 152 152 } else { 153 - const facet = await facetFromURI({ description, kind, name, tags, uri }, { 154 - fetchHTML: false, 155 - }); 153 + const facet = await facetFromURI( 154 + { description, kind, name, tags, uri }, 155 + { 156 + fetchHTML: false, 157 + }, 158 + ); 156 159 out.facets.save([...collection, facet]); 157 160 } 158 161 }); ··· 181 184 182 185 for (const li of gridItems) { 183 186 const uri = li.getAttribute("data-uri"); 187 + const menu = /** @type {HTMLElement | null} */ ( 188 + li.querySelector(".grid-item__menu") 189 + ); 190 + 184 191 const button = /** @type {HTMLElement | null} */ ( 185 192 li.querySelector("button[data-action='toggle']") 186 193 ); 194 + 187 195 const icon = button?.querySelector("i"); 188 196 189 - if (!button || !icon || !uri) continue; 197 + if (!menu || !button || !icon || !uri) continue; 190 198 191 199 const item = colMap.get(uri); 192 200 const isActive = item && item.html === undefined; 193 201 const isPrelude = li.dataset.kind === "prelude"; 202 + 203 + menu.classList.toggle("grid-item__menu--active", isActive ?? false); 194 204 195 205 button.style.opacity = "revert-layer"; 196 206 button.title = isActive ··· 205 215 206 216 /** @type {HTMLElement} */ (icon).style.transform = isActive && !isPrelude 207 217 ? "rotate(-45deg)" 208 - : ""; 209 - 210 - /** @type {HTMLElement} */ (icon).style.color = isActive 211 - ? li.dataset.activeColor ?? "var(--accent-twist-2)" 212 218 : ""; 213 219 } 214 220 });
+34
src/styles/diffuse/page.css
··· 363 363 border-left: 1px solid var(--border-color); 364 364 display: flex; 365 365 flex-direction: column; 366 + font-size: var(--fs-sm); 366 367 justify-content: space-evenly; 368 + position: relative; 369 + 370 + &.grid-item__menu--active { 371 + --grid-item-gradient-opacity: 0.375; 372 + 373 + @media (prefers-color-scheme: dark) { 374 + --grid-item-gradient-opacity: 0.3; 375 + } 376 + 377 + button, 378 + .button { 379 + color: var(--grid-item-color); 380 + opacity: 0.5; 381 + 382 + &:focus, 383 + &:hover { 384 + opacity: 1; 385 + } 386 + } 387 + } 388 + 389 + &.grid-item__menu--active::before { 390 + background: linear-gradient( 391 + to bottom, 392 + oklch(from var(--grid-item-color, transparent) l c h / var(--grid-item-gradient-opacity)), 393 + transparent 65% 394 + ); 395 + content: ""; 396 + inset: 0; 397 + pointer-events: none; 398 + position: absolute; 399 + } 367 400 368 401 hr { 369 402 background: var(--border-color); ··· 864 897 865 898 .dither-mask, 866 899 .grid-item__contents::before, 900 + .grid-item__menu--active::before, 867 901 h2, 868 902 h3 { 869 903 mask: