Иконки в опциях

Slim Select предоставляет механизм кастомизации отображения опций через шаблоны рендеринга, что позволяет внедрять иконки прямо в элементы списка выбора. Основной подход заключается в использовании HTML-разметки внутри text, innerHTML-ориентированных конфигураций или через функции кастомного рендера render.

Иконки в опциях обычно используются для визуального различения сущностей: типов данных, категорий, статусов, ролей или любых семантически значимых групп. В рамках Slim Select это реализуется без изменения базовой логики компонента — только на уровне отображения.


Базовый принцип внедрения иконок через HTML в option

Наиболее простой способ добавить иконки — передать HTML непосредственно в текст опции.

new SlimSelect({
  select: '#select',
  data: [
    {
      text: '<span class="icon icon-user"></span> Пользователь',
      value: 'user'
    },
    {
      text: '<span class="icon icon-admin"></span> Администратор',
      value: 'admin'
    }
  ]
});

CSS-иконки:

.icon {
  display: inline-block;
  width: 16px;
  height: 16px;
  margin-right: 8px;
  vertical-align: middle;
}

.icon-user {
  background: url('/icons/user.svg') no-repeat center;
  background-size: contain;
}

.icon-admin {
  background: url('/icons/admin.svg') no-repeat center;
  background-size: contain;
}

В таком подходе Slim Select просто вставляет HTML как есть, не выполняя его трансформацию. Это делает метод быстрым, но потенциально небезопасным при использовании внешних данных.


Использование SVG внутри опций

SVG-иконки обеспечивают более высокое качество отображения и гибкость стилизации.

data: [
  {
    text: `
      <svg class="ss-icon" viewBox="0 0 24 24">
        <path d="M12 2L2 7l10 5 10-5-10-5z"></path>
      </svg>
      Проект
    `,
    value: 'project'
  }
]
.ss-icon {
  width: 16px;
  height: 16px;
  margin-right: 6px;
  vertical-align: middle;
  fill: currentColor;
}

SVG позволяет управлять цветом через currentColor, что удобно при адаптации под темы интерфейса.


Кастомизация отображения через render-функции

Slim Select поддерживает расширенный рендеринг через render, что даёт полный контроль над HTML опции.

new SlimSelect({
  select: '#select',
  data: [
    { text: 'Онлайн', value: 'online', icon: 'online' },
    { text: 'Оффлайн', value: 'offline', icon: 'offline' }
  ],
  render: {
    option: (data) => {
      return `
        <div class="option-item">
          <span class="status-icon status-${data.icon}"></span>
          <span>${data.text}</span>
        </div>
      `;
    },
    selected: (data) => {
      return `
        <div class="selected-item">
          <span class="status-icon status-${data.icon}"></span>
          <span>${data.text}</span>
        </div>
      `;
    }
  }
});

CSS:

.option-item,
.selected-item {
  display: flex;
  align-items: center;
  gap: 8px;
}

.status-icon {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}

.status-online {
  background-color: #2ecc71;
}

.status-offline {
  background-color: #e74c3c;
}

Такой подход отделяет данные от представления и упрощает масштабирование интерфейса.


Использование иконок через внешние библиотеки

Slim Select не ограничивает использование сторонних иконочных систем. Часто применяются:

  • Font Awesome
  • Material Icons
  • Lucide
  • Bootstrap Icons

Пример с Font Awesome:

data: [
  {
    text: '<i class="fa fa-user"></i> Профиль',
    value: 'profile'
  },
  {
    text: '<i class="fa fa-cog"></i> Настройки',
    value: 'settings'
  }
]

Особенность подхода заключается в том, что библиотека иконок должна быть заранее подключена в проекте, иначе элементы не отобразятся.


Динамическое формирование иконок на основе данных

Иконки часто определяются не статически, а через бизнес-логику.

const users = [
  { name: 'Алексей', role: 'admin' },
  { name: 'Ирина', role: 'editor' },
  { name: 'Павел', role: 'viewer' }
];

const data = users.map(user => {
  let iconClass = '';

  switch (user.role) {
    case 'admin':
      iconClass = 'icon-admin';
      break;
    case 'editor':
      iconClass = 'icon-editor';
      break;
    default:
      iconClass = 'icon-viewer';
  }

  return {
    text: `<span class="${iconClass}"></span> ${user.name}`,
    value: user.name
  };
});

new SlimSelect({
  select: '#select',
  data
});

Такой подход позволяет централизованно управлять отображением ролей и статусов.


Разделение иконки и текста через структуру данных

Более устойчивый подход — хранить иконку отдельно от текста, а не внедрять HTML в строку.

data: [
  {
    text: 'Документы',
    value: 'docs',
    icon: 'file'
  },
  {
    text: 'Изображения',
    value: 'images',
    icon: 'image'
  }
]

И рендер:

render: {
  option: (data) => `
    <div class="option">
      <span class="icon icon-${data.icon}"></span>
      <span>${data.text}</span>
    </div>
  `
}

Преимущество такого подхода — разделение логики данных и UI, что снижает связность компонентов.


Управление состояниями иконок

Иконки могут отражать состояния элементов: активность, доступность, ошибки.

render: {
  option: (data) => {
    const disabledClass = data.disabled ? 'is-disabled' : '';
    return `
      <div class="option ${disabledClass}">
        <span class="icon icon-${data.type}"></span>
        <span>${data.text}</span>
        ${data.disabled ? '<span class="badge">недоступно</span>' : ''}
      </div>
    `;
  }
}
.is-disabled {
  opacity: 0.5;
}

.badge {
  margin-left: auto;
  font-size: 10px;
  color: #999;
}

Производительность при использовании иконок

Внедрение HTML и иконок в опции увеличивает нагрузку на DOM-рендеринг, особенно при больших списках.

Ключевые моменты оптимизации:

  • минимизация вложенных DOM-элементов
  • использование CSS вместо inline-стилей
  • кеширование сгенерированных шаблонов
  • избегание тяжелых SVG с большим количеством path

При больших наборах данных предпочтительнее использовать упрощённые иконки (например, CSS-бейджи или символы), а не полноценные SVG-графики.


Стилизация иконок в контексте темы

Slim Select часто используется в системах с тёмной и светлой темой, что требует адаптивных иконок.

.ss-dark .icon {
  filter: invert(1);
}

.ss-light .icon {
  filter: none;
}

Либо через currentColor:

.icon {
  fill: currentColor;
  color: inherit;
}

Такой подход обеспечивает автоматическую адаптацию без дублирования ресурсов.


Иконки в выбранном значении (selected state)

Отображение выбранного значения требует отдельного рендера.

render: {
  selected: (data) => `
    <div class="selected">
      <span class="icon icon-${data.icon}"></span>
      <span>${data.text}</span>
    </div>
  `
}

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


Комбинирование иконок с группировкой опций

При группировке опций иконки могут применяться как к группам, так и к отдельным элементам.

render: {
  optgroup: (data) => `
    <div class="optgroup">
      <span class="group-icon icon-${data.icon}"></span>
      <span>${data.label}</span>
    </div>
  `
}

Такой подход усиливает визуальную иерархию и облегчает навигацию по длинным спискам.