svelte-multiselect Svelte MultiSelect

Snippets

Svelte SVG component as "removeIcon" snippet

svelte<script lang="ts">
  import MultiSelect, { Icon } from '$lib'
  import { languages } from '$site/options'
  import { LanguageSnippet, MinusIcon } from '$site'
</script>

<MultiSelect
  options={languages}
  maxSelect={5}
  placeholder="What languages do you know?"
  selected={['Python', 'TypeScript', 'Julia']}
>
  {#snippet children({ option })}
    <LanguageSnippet {option} />
  {/snippet}
  {#snippet expandIcon({ open, disabled })}
    <Icon icon={open ? 'Collapse' : 'Expand'} style={disabled ? `opacity: 0.5` : null} />
  {/snippet}
  {#snippet removeIcon({ isRemoveAll })}
    {#if isRemoveAll}Clear all{:else}<MinusIcon width="1em" />{/if}
  {/snippet}
</MultiSelect>

  1. LanguageSnippet.svelte
    svelte<script lang="ts">
      import type { HTMLAttributes } from 'svelte/elements'
    
      let { option, idx = undefined, height = `20px`, gap = `5pt`, ...rest }: {
        option: string
        idx?: number | undefined
        height?: string
        gap?: string
      } & HTMLAttributes<HTMLSpanElement> = $props()
    
      let lang = $derived(
        option.toLowerCase().replaceAll(`+`, `plus`).replace(`#`, `sharp`),
      )
      let src = $derived(
        `https://cdn.jsdelivr.net/gh/devicons/devicon/icons/${lang}/${lang}-original.svg`,
      )
      let hidden = $state(false)
    
      // default back to visible every time src changes to see if image loads successfully
      $effect(() => {
        if (src) hidden = false
      })
    </script>
    
    <span style:gap {...rest}>
      {#if idx !== undefined}
        <strong>{idx + 1}</strong>
      {/if}
      <img {src} {height} alt={option} {hidden} onerror={() => (hidden = true)} />
      {option}
    </span>
    
    <style>
      span {
        display: flex;
        align-items: center;
      }
      img[alt='Rust'] {
        filter: invert(1);
      }
    </style>
    
  2. MinusIcon.svelte
    svelte<script lang="ts">
      import type { SVGAttributes } from 'svelte/elements'
    
      let { ...props }: SVGAttributes<EventTarget> = $props()
    </script>
    
    <svg aria-hidden="true" role="img" fill="currentColor" viewBox="0 0 24 24" {...props}>
      <path
        d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2zm4 11H8c-.55 0-1-.45-1-1s.45-1 1-1h8c.55 0 1 .45 1 1s-.45 1-1 1z"
      />
    </svg>
    

Simple HTML tag as "removeIcon" snippet

svelte<script lang="ts">
  import MultiSelect, { Icon } from '$lib'
  import { languages } from '$site/options'
  import { LanguageSnippet } from '$site'

  // local variable used in CollapseIcon onclick callback to close dropdown
  let open = $state(false)
</script>

<MultiSelect
  options={languages}
  maxSelect={5}
  placeholder="What languages do you know?"
  selected={[`Python`, `TypeScript`, `Julia`]}
  bind:open
>
  {#snippet selectedItem({ option })}
    <LanguageSnippet {option} />
  {/snippet}
  {#snippet option({ option, selected })}
    <LanguageSnippet {option} style={selected ? `opacity: 0.6` : ``} />
  {/snippet}
  {#snippet expandIcon({ open: expandOpen, disabled })}
    <button {disabled}>
      <Icon icon={expandOpen ? `Collapse` : `Expand`} />
    </button>
  {/snippet}
  {#snippet removeIcon({ option: opt, isRemoveAll })}
    <span style="width: 2ex" title={isRemoveAll ? `Remove all` : `Remove ${opt}`}>✕</span>
  {/snippet}
</MultiSelect>

"user-msg" snippet

svelte<script lang="ts">
  import MultiSelect, { Icon } from '$lib'
  import { languages } from '$site/options'
  import { LanguageSnippet } from '$site'

  let selected: string[] = $state([`Python`, `TypeScript`, `Julia`])
  let searchText = $state(`Julia`)
</script>

<MultiSelect
  options={languages}
  bind:searchText
  bind:selected
  maxSelect={5}
  placeholder="What languages do you know?"
  open
  allowUserOptions
>
  {#snippet userMsg({ msg })}
    <span>{msg} {selected?.includes(searchText) ? '🤦' : '👷'}</span>
  {/snippet}
</MultiSelect>