Компонент Combobox

Компонент Combobox представляет собой расширенный элемент выбора из списка, совмещающий возможности обычного <select> и текстового поля для поиска. Он обеспечивает интерактивность, улучшает UX при работе с большим количеством опций и позволяет интегрировать автозаполнение и фильтрацию данных.


Структура Combobox

Базовый Combobox включает следующие ключевые элементы:

  1. Input-поле – текстовое поле для ввода и фильтрации опций.
  2. Dropdown-список – контейнер с доступными вариантами.
  3. Option – отдельная опция внутри списка.
  4. Label и Placeholder – элементы для улучшения доступности и визуальной подсказки.

Простейшая структура в SvelteKit может выглядеть так:

<script>
  import { Combobox } from 'sveltekit-ui';
  let selectedItem = null;
  const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];
</script>

<Combobox bind:value={selectedItem} items={items} placeholder="Выберите фрукт" />

Свойства компонента

Компонент Combobox поддерживает следующие важные свойства:

  • items – массив значений, доступных для выбора.
  • value / bind:value – выбранное значение, двусторонняя привязка.
  • placeholder – текст подсказки внутри поля.
  • disabled – блокировка ввода и открытия списка.
  • filter – функция фильтрации, используемая для поиска по списку.
  • multiple – позволяет выбирать несколько элементов.
  • clearable – возможность очистки выбранного значения.

Пример с кастомной фильтрацией:

<Combobox
  bind:value={selectedItem}
  {items}
  placeholder="Начните вводить название фрукта"
  filter={(input, item) => item.toLowerCase().includes(input.toLowerCase())}
/>

Обработка событий

Combobox поддерживает стандартные события Svelte, такие как:

  • on:change – срабатывает при изменении выбранного значения.
  • on:input – срабатывает при вводе текста.
  • on:focus / on:blur – события фокусировки для управления стилями или логикой валидации.

Пример использования события change:

<Combobox
  bind:value={selectedItem}
  items={items}
  on:change={(e) => console.log('Выбран:', e.detail)}
/>

Множественный выбор

Для сценариев, когда нужно выбрать несколько опций одновременно, используется свойство multiple. Это превращает Combobox в компонент, напоминающий теговый ввод с возможностью удаления отдельных элементов.

<Combobox
  bind:value={selectedItems}
  items={items}
  multiple
  placeholder="Выберите фрукты"
/>

В selectedItems хранится массив выбранных значений, который можно динамически обновлять и использовать в логике приложения.


Стилизация и кастомизация

SvelteKit UI позволяет тонко настраивать внешний вид Combobox через:

  1. CSS-классы – добавляются через class или специальные свойства class:item, class:dropdown.
  2. Slot-ы – возможность полностью заменить шаблон элементов списка, например, для добавления иконок или описаний.
  3. Тема – глобальные переменные темы влияют на цвета, отступы и эффекты при наведении.

Пример кастомного слота для опции:

<Combobox bind:value={selectedItem} items={items}>
  <svelte:fragment slot="item" let:item>
    <div class="option">
      <strong>{item}</strong> - дополнительная информация
    </div>
  </svelte:fragment>
</Combobox>

Интеграция с асинхронными данными

Combobox легко работает с асинхронными источниками данных, например, при поиске на сервере. Для этого используется реактивная переменная с массивом элементов и await внутри функции фильтрации.

<script>
  import { Combobox } from 'sveltekit-ui';
  let items = [];
  let query = '';

  $: if (query.length > 1) {
    fetch(`/api/fruits?search=${query}`)
      .then(res => res.json())
      .then(data => items = data);
  }
</script>

<Combobox
  bind:value={selectedItem}
  {items}
  placeholder="Поиск фрукта"
  on:input={(e) => query = e.detail}
/>

Доступность (Accessibility)

Combobox автоматически поддерживает:

  • Управление клавиатурой (стрелки вверх/вниз, Enter, Escape).
  • ARIA-атрибуты (role="combobox", aria-expanded, aria-selected).
  • Корректную навигацию для скринридеров.

Для сложных случаев можно дополнительно использовать слоты для label и description, чтобы улучшить доступность.


Советы по оптимизации

  • Использовать filter для локальной фильтрации, чтобы снизить нагрузку на сервер.
  • При большом списке элементов применять виртуализацию или ленивую подгрузку.
  • Для нескольких Combobox в одной форме использовать отдельные состояния, чтобы избежать конфликтов привязки.

Расширенные возможности

  • Tagging – возможность создавать новые элементы на лету, если введённое значение отсутствует в списке.
  • Async debounce – задержка перед отправкой запроса для поиска, чтобы уменьшить количество API-вызовов.
  • Custom option rendering – использование компонентов внутри опций (например, с картинками или цветными метками).

Пример комбинирования кастомного рендера и нового тега:

<Combobox
  bind:value={selectedItem}
  items={items}
  allow-new
>
  <svelte:fragment slot="item" let:item>
    <div style="display:flex; align-items:center;">
      <img src={`/images/${item}.png`} alt="" width="20" height="20"/>
      <span>{item}</span>
    </div>
  </svelte:fragment>
</Combobox>

Этот подход позволяет создавать высокоинтерактивные и визуально насыщенные интерфейсы, полностью используя возможности SvelteKit UI.