From 8d12c1b05d57135fec07d8c5d6203d8275932545 Mon Sep 17 00:00:00 2001 From: Elijah Duffy Date: Tue, 15 Jul 2025 18:58:25 -0700 Subject: [PATCH] combobox: default icon support, smart icon width --- src/lib/Combobox.svelte | 24 ++++++++++++++++-------- src/routes/+page.svelte | 6 ++++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/lib/Combobox.svelte b/src/lib/Combobox.svelte index c31c673..537eec3 100644 --- a/src/lib/Combobox.svelte +++ b/src/lib/Combobox.svelte @@ -24,7 +24,7 @@ import { Portal } from '@jsrob/svelte-portal'; import { browser } from '$app/environment'; import { scale } from 'svelte/transition'; - import { generateIdentifier } from './util'; + import { generateIdentifier, type IconDef } from './util'; import type { ClassValue } from 'svelte/elements'; import { matchSorter } from 'match-sorter'; import Spinner from './Spinner.svelte'; @@ -40,6 +40,8 @@ invalidMessage?: string | null; label?: string; placeholder?: string; + /** displayed by default if no item is selected that has its own icon */ + icon?: IconDef; /** * enables loading spinner and fallback text if no items are found. may be changed * internally if lazy is enabled. loading is, however, not bindable, so don't expect @@ -76,6 +78,7 @@ invalidMessage = 'Please select an option', label, placeholder, + icon, loading = false, lazy = false, compact = false, @@ -98,6 +101,7 @@ let searchValue = $state(''); let pickerPosition = $state<'top' | 'bottom'>('bottom'); let searching = $state(false); + let iconWidth = $state(undefined); let searchInput = $state(null); let searchContainer = $state(null); @@ -121,13 +125,12 @@ }); /** controls whether an icon should be displayed */ - let iconVisible = $derived.by(() => { - return ( - (open && highlighted && highlighted.icon) || + let iconVisible = $derived( + (open && highlighted && highlighted.icon) || (value && value.icon && searchValue === '') || - loading - ); - }); + loading || + icon !== undefined + ); /** controls whether the highlighted option should be used in the selection preview */ let useHighlighted = $derived.by(() => { @@ -494,9 +497,11 @@ {#if iconVisible}
{#if loading} @@ -504,6 +509,8 @@ {@render highlighted.icon(highlighted)} {:else if value?.icon} {@render value.icon(value)} + {:else if icon} + {:else} ❌ {/if} @@ -511,7 +518,8 @@ {/if}