your personal website on atproto - mirror blento.app
at remove-extra-buttons 88 lines 2.3 kB view raw
1<script lang="ts"> 2 import { AppBskyActorDefs } from '@atcute/bluesky'; 3 import { Combobox } from 'bits-ui'; 4 import { searchActorsTypeahead } from '$lib/atproto'; 5 import { Avatar } from '@foxui/core'; 6 7 let results: AppBskyActorDefs.ProfileViewBasic[] = $state([]); 8 9 async function search(q: string) { 10 if (!q || q.length < 2) { 11 results = []; 12 return; 13 } 14 results = (await searchActorsTypeahead(q, 5)).actors; 15 } 16 let open = $state(false); 17 18 let { 19 value = $bindable(), 20 onselected, 21 ref = $bindable() 22 }: { 23 value: string; 24 onselected: (actor: AppBskyActorDefs.ProfileViewBasic) => void; 25 ref?: HTMLInputElement | null; 26 } = $props(); 27</script> 28 29<Combobox.Root 30 type="single" 31 onOpenChangeComplete={(o) => { 32 if (!o) results = []; 33 }} 34 bind:value={ 35 () => { 36 return value; 37 }, 38 (val) => { 39 const profile = results.find((v) => v.handle === val); 40 if (profile) onselected?.(profile); 41 42 value = val; 43 } 44 } 45 bind:open={ 46 () => { 47 return open && results.length > 0; 48 }, 49 (val) => { 50 open = val; 51 } 52 } 53> 54 <Combobox.Input 55 bind:ref 56 oninput={(e) => { 57 value = e.currentTarget.value; 58 search(e.currentTarget.value); 59 }} 60 class="focus-within:outline-accent-600 dark:focus-within:outline-accent-500 dark:placeholder:text-base-400 w-full touch-none rounded-full border-0 bg-white ring-0 outline-1 -outline-offset-1 outline-gray-300 focus-within:outline-2 focus-within:-outline-offset-2 dark:bg-white/5 dark:outline-white/10" 61 placeholder="handle" 62 id="" 63 aria-label="enter your handle" 64 /> 65 <Combobox.Content 66 class="border-base-300 bg-base-50 dark:bg-base-900 dark:border-base-800 z-100 max-h-[30dvh] w-full rounded-2xl border shadow-lg" 67 sideOffset={10} 68 align="start" 69 side="top" 70 > 71 <Combobox.Viewport class="w-full p-1"> 72 {#each results as actor (actor.did)} 73 <Combobox.Item 74 class="rounded-button data-highlighted:bg-accent-100 dark:data-highlighted:bg-accent-600/30 my-0.5 flex w-full cursor-pointer items-center gap-2 rounded-xl p-2 px-2" 75 value={actor.handle} 76 label={actor.handle} 77 > 78 <Avatar 79 src={actor.avatar?.replace('avatar', 'avatar_thumbnail')} 80 alt="" 81 class="size-6 rounded-full" 82 /> 83 {actor.handle} 84 </Combobox.Item> 85 {/each} 86 </Combobox.Viewport> 87 </Combobox.Content> 88</Combobox.Root>