your personal website on atproto - mirror blento.app
at mobile-editing 102 lines 3.8 kB view raw
1<script lang="ts"> 2 import { AllCardDefinitions } from '$lib/cards'; 3 import type { CardDefinition } from '$lib/cards/types'; 4 import { Command, Dialog } from 'bits-ui'; 5 6 const CardDefGroups = [ 7 'Core', 8 ...Array.from( 9 new Set( 10 AllCardDefinitions.map((cardDef) => cardDef.groups) 11 .flat() 12 .filter((g) => g) 13 ) 14 ) 15 .sort() 16 .filter((g) => g !== 'Core') 17 ]; 18 19 let { 20 open = $bindable(false), 21 onselect 22 }: { open: boolean; onselect: (cardDef: CardDefinition) => void } = $props(); 23 24 function handleKeydown(e: KeyboardEvent) { 25 if (e.key === 'k' && (e.metaKey || e.ctrlKey)) { 26 e.preventDefault(); 27 open = true; 28 } 29 } 30</script> 31 32<svelte:document onkeydown={handleKeydown} /> 33 34<Dialog.Root bind:open> 35 <Dialog.Portal> 36 <Dialog.Overlay 37 class="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80" 38 /> 39 <Dialog.Content 40 class="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-36 left-[50%] z-50 w-full max-w-[94%] translate-x-[-50%] outline-hidden sm:max-w-lg md:w-full" 41 > 42 <Dialog.Title class="sr-only">Command Menu</Dialog.Title> 43 <Dialog.Description class="sr-only"> 44 This is the command menu. Use the arrow keys to navigate and press ⌘K to open the search 45 bar. 46 </Dialog.Description> 47 <Command.Root 48 class="border-base-200 dark:border-base-800 mx-auto flex h-full w-full max-w-[90vw] flex-col overflow-hidden rounded-2xl border bg-white dark:bg-black" 49 > 50 <Command.Input 51 class="focus-override placeholder:text-base-900/50 dark:placeholder:text-base-50/50 border-base-200 dark:border-base-800 bg-base-100 mx-1 mt-1 inline-flex truncate rounded-2xl rounded-tl-2xl px-4 text-sm transition-colors focus:ring-0 focus:outline-hidden dark:bg-black" 52 placeholder="Search for a card..." 53 /> 54 <Command.List 55 class="focus:outline-accent-500/50 max-h-[50vh] overflow-x-hidden overflow-y-auto rounded-br-2xl rounded-bl-2xl bg-white px-2 pb-2 focus:border-0 dark:bg-black" 56 > 57 <Command.Viewport> 58 <Command.Empty 59 class="text-base-900 dark:text-base-100 flex w-full items-center justify-center pt-8 pb-6 text-sm" 60 > 61 No results found. 62 </Command.Empty> 63 64 {#each CardDefGroups as group, index} 65 {#if group && AllCardDefinitions.some((cardDef) => cardDef.groups?.includes(group))} 66 <Command.Group> 67 <Command.GroupHeading 68 class="text-base-600 dark:text-base-400 px-3 pt-4 pb-2 text-xs" 69 > 70 {group} 71 </Command.GroupHeading> 72 <Command.GroupItems> 73 {#each AllCardDefinitions.filter( (cardDef) => cardDef.groups?.includes(group) ) as cardDef} 74 <Command.Item 75 onSelect={() => { 76 open = false; 77 onselect(cardDef); 78 }} 79 class="rounded-button data-selected:bg-accent-500/10 flex h-10 cursor-pointer items-center gap-2 rounded-xl px-3 py-2.5 text-sm outline-hidden select-none" 80 keywords={[group, cardDef.type, ...(cardDef.keywords || [])]} 81 > 82 {#if cardDef.icon} 83 <div class="text-base-700 dark:text-base-300"> 84 {@html cardDef.icon} 85 </div> 86 {/if} 87 {cardDef.name} 88 </Command.Item> 89 {/each} 90 </Command.GroupItems> 91 </Command.Group> 92 {#if index < CardDefGroups.length - 1} 93 <Command.Separator class="bg-base-900/5 dark:bg-base-50/5 my-1 h-px w-full" /> 94 {/if} 95 {/if} 96 {/each} 97 </Command.Viewport> 98 </Command.List> 99 </Command.Root> 100 </Dialog.Content> 101 </Dialog.Portal> 102</Dialog.Root>