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.

chore: improve grid design, replace toggle

+92 -62
+27 -1
src/_components/grid.vto
··· 28 28 } 29 29 })() }} 30 30 31 + {{ set facetUri = item.url |> facetURI }} 32 + 31 33 <li 32 34 class="grid-item" 33 35 data-active-color="{{color}}" ··· 35 37 data-name="{{item.title}}" 36 38 data-category="{{ item.category ?? `` }}" 37 39 data-kind="{{item.kind ?? `interface`}}" 38 - data-uri="{{ item.url |> facetURI }}" 40 + data-uri="{{ facetUri }}" 39 41 > 40 42 <div 41 43 class="grid-item__contents" ··· 55 57 </div> 56 58 <div class="list-description"> 57 59 {{ item.desc |> md(true) }} 60 + </div> 61 + </div> 62 + <div class="grid-item__menu"> 63 + <button 64 + class="button--transparent" 65 + data-action="toggle" 66 + style="opacity: 0" 67 + title="{{ item.kind === `prelude` ? `Add` : `Bookmark` }}" 68 + > 69 + <i class="ph-bold {{ item.kind === `prelude` ? `ph-plus` : `ph-bookmark` }}"></i> 70 + </button> 71 + <hr /> 72 + <button 73 + class="button--transparent" 74 + title="More actions" 75 + popovertarget="grid-item-menu-{{ index }}" 76 + > 77 + <i class="ph-bold ph-dots-three-vertical"></i> 78 + </button> 79 + <div id="grid-item-menu-{{ index }}" class="dropdown" popover> 80 + <a class="with-icon" href="code/?uri={{ encodeURIComponent(facetUri) }}&name={{ encodeURIComponent(item.title) }}&kind={{ item.kind ?? `interface` }}&description={{ encodeURIComponent(item.desc.trim()) }}"> 81 + <i class="ph-fill ph-code-block"></i> 82 + Open code in editor 83 + </a> 58 84 </div> 59 85 </div> 60 86 </li>
+16 -6
src/common/pages/code.js
··· 267 267 //////////////////////////////////////////// 268 268 269 269 export async function editFacetFromURL() { 270 - const idParam = new URLSearchParams(location.search).get("id"); 270 + const params = new URLSearchParams(location.search); 271 + const idParam = params.get("id"); 272 + const uriParam = params.get("uri"); 271 273 272 - if (idParam) { 273 - setEditorLoading(true); 274 - try { 274 + setEditorLoading(true); 275 + try { 276 + if (idParam) { 275 277 const out = await output(); 276 278 const col = await Output.data(out.facets); 277 279 const facet = col.find((f) => f.id === idParam); 278 280 if (facet) await editFacet(facet); 279 - } finally { 280 - setEditorLoading(false); 281 + } else if (uriParam) { 282 + const facet = await facetFromURI({ 283 + uri: uriParam, 284 + name: params.get("name") ?? "", 285 + kind: /** @type {any} */ (params.get("kind") ?? undefined), 286 + description: params.get("description") ?? undefined, 287 + }, { fetchHTML: true }); 288 + await editFacet(facet); 281 289 } 290 + } finally { 291 + setEditorLoading(false); 282 292 } 283 293 }
+49 -55
src/common/pages/grid.js
··· 111 111 } 112 112 113 113 //////////////////////////////////////////// 114 - // OUTPUT INDICATOR 115 - //////////////////////////////////////////// 116 - 117 - /** @type {() => void | undefined} */ 118 - let stopOutputIndicator; 119 - 120 - export async function setupOutputIndicator() { 121 - if (stopOutputIndicator) stopOutputIndicator(); 122 - 123 - const filterEl = document.querySelector(".grid-filter"); 124 - if (!filterEl) return; 125 - 126 - const out = await output(); 127 - 128 - /** @type {HTMLElement | null} */ 129 - const indicator = filterEl.querySelector(".grid-filter--output"); 130 - if (!indicator) return; 131 - 132 - /** @type {HTMLElement | null} */ 133 - const label = filterEl.querySelector(".grid-filter--label-output"); 134 - if (!label) return; 135 - 136 - setTimeout(() => { 137 - indicator.style.opacity = "1"; 138 - label.style.opacity = "0.4"; 139 - }, 250); 140 - 141 - stopOutputIndicator = effect(() => { 142 - const selected = out.selected(); 143 - const label = selected?.label ?? selected?.getAttribute?.("label") ?? 144 - "Local storage"; 145 - indicator.textContent = label; 146 - }); 147 - } 148 - 149 - //////////////////////////////////////////// 150 114 // TOGGLE BUTTONS 151 115 //////////////////////////////////////////// 152 116 ··· 156 120 ); 157 121 158 122 for (const li of gridItems) { 159 - const container = li.querySelector(".grid-item__title"); 160 - if (!container) continue; 161 - 162 - const button = document.createElement("button"); 163 - button.className = "button--transparent"; 164 - button.style.cssText = 165 - `color: oklch(from currentColor l c h / 0.4); font-size: var(--fs-md); opacity: 0; padding: 0;`; 166 - button.innerHTML = `<i class="ph-fill ph-toggle-left"></i>`; 123 + const button = li.querySelector("button[data-action='toggle']"); 124 + if (!button) continue; 167 125 168 - button.addEventListener("click", async (event) => { 169 - event.preventDefault(); 170 - 126 + button.addEventListener("click", async () => { 171 127 const uri = li.getAttribute("data-uri"); 172 128 const name = li.getAttribute("data-name"); 173 129 const kind = li.getAttribute("data-kind") ?? undefined; ··· 190 146 out.facets.save([...collection, facet]); 191 147 } 192 148 }); 193 - 194 - container.appendChild(button); 195 149 } 196 150 } 197 151 ··· 217 171 218 172 for (const li of gridItems) { 219 173 const uri = li.getAttribute("data-uri"); 220 - const button = 221 - /** @type {HTMLElement | null} */ (li.querySelector("button")); 174 + const button = /** @type {HTMLElement | null} */ ( 175 + li.querySelector("button[data-action='toggle']") 176 + ); 222 177 const icon = button?.querySelector("i"); 223 178 224 179 if (!button || !icon || !uri) continue; ··· 227 182 228 183 const item = colMap.get(uri); 229 184 const isActive = item && item.html === undefined; 185 + const isPrelude = li.dataset.kind === "prelude"; 230 186 231 187 button.title = isActive 232 - ? "Remove from your collection" 233 - : "Add to your collection"; 188 + ? (isPrelude ? "Remove feature" : "Remove bookmark") 189 + : (isPrelude ? "Add feature" : "Add bookmark"); 234 190 icon.className = isActive 235 - ? "ph-fill ph-toggle-right" 236 - : "ph-fill ph-toggle-left"; 191 + ? isPrelude ? "ph-bold ph-check" : "ph-fill ph-bookmark-simple" 192 + : isPrelude 193 + ? "ph-bold ph-plus" 194 + : "ph-bold ph-bookmark-simple"; 237 195 /** @type {HTMLElement} */ (icon).style.color = isActive 238 196 ? li.dataset.activeColor ?? "var(--accent-twist-2)" 239 197 : ""; 240 198 } 241 199 }); 242 200 } 201 + 202 + //////////////////////////////////////////// 203 + // OUTPUT INDICATOR 204 + //////////////////////////////////////////// 205 + 206 + /** @type {() => void | undefined} */ 207 + let stopOutputIndicator; 208 + 209 + export async function setupOutputIndicator() { 210 + if (stopOutputIndicator) stopOutputIndicator(); 211 + 212 + const filterEl = document.querySelector(".grid-filter"); 213 + if (!filterEl) return; 214 + 215 + const out = await output(); 216 + 217 + /** @type {HTMLElement | null} */ 218 + const indicator = filterEl.querySelector(".grid-filter--output"); 219 + if (!indicator) return; 220 + 221 + /** @type {HTMLElement | null} */ 222 + const label = filterEl.querySelector(".grid-filter--label-output"); 223 + if (!label) return; 224 + 225 + setTimeout(() => { 226 + indicator.style.opacity = "1"; 227 + label.style.opacity = "0.4"; 228 + }, 250); 229 + 230 + stopOutputIndicator = effect(() => { 231 + const selected = out.selected(); 232 + const label = selected?.label ?? selected?.getAttribute?.("label") ?? 233 + "Local storage"; 234 + indicator.textContent = label; 235 + }); 236 + }