decentralized and customizable links page on top of atproto ligo.at
atproto link-in-bio python uv
9
fork

Configure Feed

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

fix some stuff in the typeahead

+31 -14
+31 -14
src/static/actor-typeahead.js
··· 3 3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 4 * 5 5 * Copyright (c) 2026 Jake Lazaroff 6 + * Copyright (c) 2026 ligo.at contributors 6 7 * 7 - * Repository: https://tangled.org/jakelazaroff.com/actor-typeahead 8 + * Changes 9 + * 2026-03-15 10 + * Fix: Correctly count rows of actors. 11 + * Fix: Disable browser autocomplete to not collide with the typeahead. 12 + * Fix: Remove hardcoded `font-family`. 13 + * New: You can press `Enter` while on the field to send the form. 14 + * New: You can press `ArrowDown` while on the field to open the dropdown menu. 8 15 */ 9 16 10 17 const template = document.createElement("template"); ··· 24 31 --padding-menu-inherited: var(--padding-menu, 4px); 25 32 display: block; 26 33 position: relative; 27 - font-family: system-ui; 28 34 } 29 35 30 36 *, *::before, *::after { ··· 166 172 /** @type {Array<{ handle: string; avatar: string }>} */ 167 173 #actors = []; 168 174 #index = -1; 175 + /** @type {HTMLInputElement} */ 176 + #input; 169 177 #pressed = false; 170 178 171 179 constructor() { ··· 179 187 this.#shadow.addEventListener("pointerdown", this); 180 188 this.#shadow.addEventListener("pointerup", this); 181 189 this.#shadow.addEventListener("click", this); 190 + this.#input = this.querySelector("input"); 191 + if (!this.#input) { 192 + console.error(`Missing <input> tag inside <${ActorTypeahead.tag}>`); 193 + } 194 + this.#input.autocomplete = "off"; 182 195 } 183 196 184 197 get #rows() { ··· 224 237 switch (evt.key) { 225 238 case "ArrowDown": 226 239 evt.preventDefault(); 227 - this.#index = Math.min(this.#index + 1, this.#rows - 1); 240 + if (this.#actors.length === 0) { 241 + this.#oninput(evt); 242 + break; 243 + } 244 + this.#index = Math.min(this.#index + 1, this.#actors.length - 1); 228 245 this.#render(); 229 246 break; 230 247 231 248 case "PageDown": 232 249 evt.preventDefault(); 233 - this.#index = this.#rows - 1; 250 + this.#index = this.#actors.length - 1; 234 251 this.#render(); 235 252 break; 236 253 ··· 254 271 break; 255 272 256 273 case "Enter": 257 - evt.preventDefault(); 258 - this.#shadow 259 - .querySelectorAll("button") 260 - [ 261 - this.#index 262 - ]?.dispatchEvent(new PointerEvent("pointerup", { bubbles: true })); 274 + const selected = this.#shadow.querySelectorAll("button")[this.#index]; 275 + if (selected) { 276 + evt.preventDefault(); 277 + selected.dispatchEvent( 278 + new PointerEvent("pointerup", { bubbles: true }), 279 + ); 280 + } 263 281 break; 264 282 } 265 283 } ··· 327 345 #onpointerup(evt) { 328 346 this.#pressed = false; 329 347 330 - this.querySelector("input")?.focus(); 348 + this.#input.focus(); 331 349 332 350 const button = evt.target?.closest("button"); 333 - const input = this.querySelector("input"); 334 - if (!input || !button) return; 351 + if (!button) return; 335 352 336 - input.value = button.dataset.handle || ""; 353 + this.#input.value = button.dataset.handle || ""; 337 354 this.#actors = []; 338 355 this.#render(); 339 356 }