Skip to content

Instantly share code, notes, and snippets.

@jonshipman
Last active December 24, 2023 15:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonshipman/83a8a710f1ec90b1619239412c7843f9 to your computer and use it in GitHub Desktop.
Save jonshipman/83a8a710f1ec90b1619239412c7843f9 to your computer and use it in GitHub Desktop.
select
<script lang="ts">
import { Spinner } from '$lib/util';
import './select.css';
interface Option {
value: string;
label: string;
}
export let value = '';
export let label = '';
export let loading = false;
let visible = false;
let selectLabel = '';
let options: Option[] = [];
$: selectLabel = options.find((o) => o.value === value)?.label || '';
$: console.log(selectLabel, options);
function handleSelect(select: string) {
value = select;
toggleDropdown();
}
function toggleDropdown() {
visible = !visible;
}
function optionBuilder(node: HTMLSelectElement) {
options = [...node.options].map((x) => ({ value: x.value, label: x.textContent || '' }));
return {
destroy() {
options = [];
}
};
}
</script>
<label
class="relative rounded-3xl flex items-center border border-gray-500 py-2 px-3 gap-2 bg-white text-gray-500 text-sm"
>
{#if label}
<span class="font-bold text-black whitespace-nowrap select-none">{label}</span>
{/if}
{#if loading}
<span class="w-12 block">
<Spinner class="w-4 h-4" />
</span>
<input name="none" type="hidden" />
{:else}
<div
class="max-w-28 select-none cursor-pointer"
role="button"
tabindex={0}
on:click={toggleDropdown}
on:keydown={toggleDropdown}
>
{selectLabel}
</div>
{#if visible}
<div class="absolute top-full right-0 z-10 pt-2">
<div class="bg-white rounded drop-shadow-lg max-h-64 overflow-y-auto whitespace-nowrap">
{#each options as option}
<div
role="button"
tabindex={0}
on:keydown={() => handleSelect(option.value)}
on:click={() => handleSelect(option.value)}
class="cursor-pointer select-none px-4 py-2 first:rounded-t last:rounded-b first:pt-4 last:pb-4 hover:bg-indigo-500 hover:text-white"
>
{option.label}
</div>
{/each}
</div>
</div>
{/if}
<select use:optionBuilder class="hidden" bind:value>
<slot />
</select>
{/if}
</label>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment