Выбор цветов в Tom Select реализуется через комбинацию кастомных значений опций, переопределения рендеринга элементов и управления вводом новых значений. Библиотека не предоставляет встроенный color picker, но позволяет легко построить полноценный интерфейс выбора цветов поверх стандартного механизма тегов и селектов.
Основная идея заключается в том, что цвет представляется как
строковое значение (обычно HEX, реже RGB или HSL), а визуальное
отображение формируется через кастомные шаблоны
render.option и render.item. Это позволяет
превращать обычный select в компонент, визуально похожий на палитру.
Tom Select работает с унифицированными значениями опций. Для цветов чаще всего используется HEX-формат:
{
value: "#ff0000",
text: "Красный"
}
Однако текстовое поле не обязательно должно содержать название цвета — оно может быть дублирующим или вспомогательным. В интерфейсах, ориентированных на визуальный выбор, текст часто вообще скрывается, а ключевым становится только цветовое значение.
При работе с динамическими палитрами значения могут формироваться на лету:
const colors = [
{ value: "#1abc9c", text: "Turquoise" },
{ value: "#2ecc71", text: "Emerald" },
{ value: "#3498db", text: "Peter River" }
];
Для поддержки произвольного ввода цветов используется режим создания новых элементов:
new TomSelect("#color-select", {
persist: false,
create: true
});
В этом режиме любое введённое значение становится новым элементом
списка. При работе с цветами это позволяет вводить HEX-коды вручную,
например #a1b2c3.
Часто добавляется дополнительная нормализация ввода, чтобы гарантировать корректность формата:
create: function(input) {
const isValidHex = /^#([0-9a-fA-F]{6})$/.test(input);
if (!isValidHex) return false;
return {
value: input,
text: input
};
}
Ключевой аспект работы с цветами — переопределение отображения
элементов списка. Для этого используется render.option:
new TomSelect("#color-select", {
options: colors,
valueField: "value",
labelField: "text",
searchField: "text",
render: {
option: function(data, escape) {
return `
<div class="color-option">
<span class="color-swatch" style="background:${escape(data.value)}"></span>
<span class="color-label">${escape(data.text)}</span>
</div>
`;
},
item: function(data, escape) {
return `
<div class="color-item">
<span class="color-swatch" style="background:${escape(data.value)}"></span>
<span>${escape(data.value)}</span>
</div>
`;
}
}
});
Такой подход разделяет визуальную и текстовую части: цвет отображается через inline-стиль, а текст используется только для идентификации.
CSS-часть играет ключевую роль в восприятии компонента. Обычно используется минималистичная круглая или квадратная индикация:
.color-option,
.color-item {
display: flex;
align-items: center;
gap: 8px;
}
.color-swatch {
width: 14px;
height: 14px;
border-radius: 3px;
border: 1px solid rgba(0,0,0,0.1);
}
При необходимости можно добавить динамическую тень или обводку для светлых цветов, чтобы они не терялись на белом фоне:
.color-swatch {
box-shadow: inset 0 0 0 1px rgba(0,0,0,0.08);
}
Tom Select изначально поддерживает мультивыбор, что особенно полезно для палитр:
new TomSelect("#color-select", {
plugins: ["remove_button"],
maxItems: null
});
В этом режиме выбранные цвета отображаются как отдельные элементы, каждый из которых можно стилизовать независимо. Это позволяет реализовать интерфейсы тегирования цветами, например подбор палитры для дизайна.
Часто цвета не вводятся вручную, а генерируются автоматически. Например, палитра может формироваться на основе алгоритма равномерного распределения оттенков:
function generatePalette(n) {
const colors = [];
for (let i = 0; i < n; i++) {
const hue = Math.round((360 / n) * i);
colors.push({
value: `hsl(${hue}, 70%, 50%)`,
text: `Hue ${hue}`
});
}
return colors;
}
Такая модель удобна для UI-конструкторов, где важно быстро предложить визуально различимые варианты.
При работе с пользовательским вводом необходимо ограничивать допустимые форматы. Помимо HEX, часто поддерживаются RGB и HSL, однако внутри системы обычно выполняется приведение к единому виду.
Простейшая проверка:
function normalizeColor(input) {
const hex = input.trim();
if (/^#([0-9a-f]{6})$/i.test(hex)) return hex;
return null;
}
Более сложные реализации могут включать конвертацию через временный DOM-элемент или canvas.
Tom Select часто используется совместно с отдельными библиотеками выбора цвета. В этом случае select служит контейнером для сохранения результата:
const select = new TomSelect("#color-select", {
create: true
});
someColorPicker.on("change", (color) => {
select.addOption({ value: color.hex, text: color.hex });
select.addItem(color.hex);
});
Такой подход разделяет ответственность: picker отвечает за выбор, Tom Select — за хранение и отображение.
Поиск по цветам обычно не нужен, но при наличии названий оттенков фильтрация может быть полезной:
new TomSelect("#color-select", {
searchField: ["text", "value"]
});
При этом можно реализовать приоритет поиска по названию, а не по HEX-коду, чтобы ускорить выбор.
Цветовые наборы могут изменяться в зависимости от состояния приложения:
const control = new TomSelect("#color-select", {
options: []
});
function updatePalette(newColors) {
control.clearOptions();
control.addOptions(newColors);
control.refreshOptions(false);
}
Это используется в системах темизации, где доступные цвета зависят от выбранного режима интерфейса.
Внутренне Tom Select хранит выбранные цвета как массив значений. Это позволяет легко сериализовать результат:
const selected = control.getValue();
// ["#ff0000", "#00ff00"]
При отправке формы значения могут напрямую использоваться в API, где цвет уже интерпретируется как параметр визуального оформления.
Для сложных интерфейсов цвет может быть не просто строкой, а объектом:
{
value: "#ff0000",
text: "Red",
meta: {
contrast: "high",
category: "primary"
}
}
Отображение при этом адаптируется:
render: {
option: function(data, escape) {
return `
<div>
<span style="background:${escape(data.value)}" class="swatch"></span>
<span>${escape(data.text)}</span>
<small>${escape(data.meta.category)}</small>
</div>
`;
}
}
Такой подход позволяет строить сложные системы выбора палитр, где цвет связан с семантикой интерфейса, а не только с визуальным значением.