Templates

Templates personalizados usando apenas emojis e CSS, sem dependências externas. Customize a aparência dos itens no dropdown e na seleção.

Países com Bandeiras e Códigos

Emojis de bandeiras nativas + badges com códigos de país.

Ver código

HTML

<select id="countries"></select>

JavaScript

const countriesData = [
  { id: 'us', text: 'United States', flag: '🇺🇸', code: 'US' },
  { id: 'br', text: 'Brazil', flag: '🇧🇷', code: 'BR' },
  { id: 'uk', text: 'United Kingdom', flag: '🇬🇧', code: 'UK' },
  { id: 'fr', text: 'France', flag: '🇫🇷', code: 'FR' },
  { id: 'de', text: 'Germany', flag: '🇩🇪', code: 'DE' }
];

new VanillaSmartSelect('#countries', {
  data: countriesData,
  placeholder: 'Selecione um país...',
  allowClear: true,
  templateResult: (item) => {
    const div = document.createElement('div');
    div.style.display = 'flex';
    div.style.alignItems = 'center';
    div.style.gap = '10px';
    div.innerHTML = `
      <span style="font-size: 24px;">${item.flag}</span>
      <span style="font-weight: 500; flex: 1;">${item.text}</span>
      <span style="background: #e9ecef; padding: 2px 8px; border-radius: 3px; 
                   font-size: 11px; font-weight: 600;">${item.code}</span>
    `;
    return div;
  },
  templateSelection: (item) => {
    return `${item.flag} ${item.text} (${item.code})`;
  }
});

Usuários com Avatares Emoji

Avatares coloridos com gradientes + informações de cargo.

Ver código

HTML

<select id="users"></select>

JavaScript

const usersData = [
  { id: 1, text: 'Ana Silva', role: 'Gerente de Projetos', emoji: '👩‍💼' },
  { id: 2, text: 'Carlos Santos', role: 'Desenvolvedor Senior', emoji: '👨‍💻' },
  { id: 3, text: 'Maria Oliveira', role: 'Designer UX/UI', emoji: '👩‍🎨' },
  { id: 4, text: 'João Costa', role: 'Analista de Dados', emoji: '👨‍🔬' },
  { id: 5, text: 'Paula Ferreira', role: 'Product Manager', emoji: '👩‍🚀' }
];

new VanillaSmartSelect('#users', {
  data: usersData,
  placeholder: 'Selecione um usuário...',
  allowClear: true,
  templateResult: (item) => {
    const div = document.createElement('div');
    div.style.display = 'flex';
    div.style.alignItems = 'center';
    div.style.gap = '12px';
    div.innerHTML = `
      <div style="font-size: 32px; width: 40px; height: 40px; display: flex; 
                  align-items: center; justify-content: center; 
                  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 
                  border-radius: 50%;">${item.emoji}</div>
      <div>
        <div style="font-weight: 500;">${item.text}</div>
        <div style="font-size: 12px; color: #666;">${item.role}</div>
      </div>
    `;
    return div;
  },
  templateSelection: (item) => {
    return `${item.emoji} ${item.text}`;
  }
});

Templates Diferentes: Dropdown vs Seleção

Demonstra como usar templates detalhados no dropdown e simplificados na seleção.

Ver código

HTML

<select id="employees"></select>

JavaScript

const employeesData = [
  { id: 1, text: 'Sarah Connor', role: 'Engineering Manager', department: 'Engineering', emoji: '👩‍💼' },
  { id: 2, text: 'Kyle Reese', role: 'Senior Developer', department: 'Engineering', emoji: '👨‍💻' },
  { id: 3, text: 'Miles Dyson', role: 'Tech Lead', department: 'Research', emoji: '👨‍🔬' },
  { id: 4, text: 'John Connor', role: 'Product Manager', department: 'Product', emoji: '👨‍🚀' }
];

new VanillaSmartSelect('#employees', {
  data: employeesData,
  placeholder: 'Selecione um funcionário...',
  allowClear: true,
  // Template detalhado para o dropdown
  templateResult: (item) => {
    const div = document.createElement('div');
    div.style.display = 'flex';
    div.style.alignItems = 'center';
    div.style.gap = '12px';
    div.innerHTML = `
      <div style="width: 40px; height: 40px; display: flex; align-items: center; 
                  justify-content: center; font-size: 24px; border-radius: 50%;
                  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
        ${item.emoji}
      </div>
      <div>
        <div style="font-weight: 500;">${item.text}</div>
        <div style="font-size: 12px; color: #666;">
          ${item.role} • ${item.department}
        </div>
      </div>
    `;
    return div;
  },
  // Template simplificado para o item selecionado (apenas nome)
  templateSelection: (item) => {
    return item.text;
  }
});
✅ Flexibilidade: Use templateResult para mostrar informações detalhadas no dropdown e templateSelection para manter a seleção limpa e compacta.

Produtos com Ícones e Preços

Ícones emoji + nome, categoria e preço formatado.

Ver código

HTML

<select id="products"></select>

JavaScript

const productsData = [
  { id: 1, text: 'Notebook Pro', category: 'Eletrônicos', price: 4299.90, icon: '💻', color: '#007bff' },
  { id: 2, text: 'Mouse Wireless', category: 'Periféricos', price: 89.90, icon: '🖱️', color: '#28a745' },
  { id: 3, text: 'Teclado Mecânico', category: 'Periféricos', price: 349.90, icon: '⌨️', color: '#17a2b8' },
  { id: 4, text: 'Monitor 4K 27"', category: 'Eletrônicos', price: 1899.90, icon: '🖥️', color: '#6f42c1' },
  { id: 5, text: 'Webcam HD', category: 'Acessórios', price: 299.90, icon: '📹', color: '#fd7e14' }
];

new VanillaSmartSelect('#products', {
  data: productsData,
  placeholder: 'Selecione um produto...',
  allowClear: true,
  templateResult: (item) => {
    const div = document.createElement('div');
    div.style.display = 'flex';
    div.style.alignItems = 'center';
    div.style.gap = '12px';
    div.innerHTML = `
      <div style="width: 40px; height: 40px; display: flex; align-items: center; 
                  justify-content: center; border-radius: 8px; font-size: 24px;
                  background: ${item.color}20; color: ${item.color};">
        ${item.icon}
      </div>
      <div style="flex: 1;">
        <div style="font-weight: 500;">${item.text}</div>
        <div style="font-size: 12px; color: #666;">${item.category}</div>
      </div>
      <div style="font-weight: 600; color: #007bff;">
        R$ ${item.price.toFixed(2).replace('.', ',')}
      </div>
    `;
    return div;
  },
  templateSelection: (item) => {
    return `${item.icon} ${item.text} - R$ ${item.price.toFixed(2).replace('.', ',')}`;
  }
});

Tasks com Status (Multi-Select)

Multi-select com ícones de status e badges coloridos.

Ver código

HTML

<select id="tasks" multiple></select>

JavaScript

const tasksData = [
  { id: 1, text: 'Atualizar documentação', status: 'active', statusText: 'Em andamento', icon: '📝' },
  { id: 2, text: 'Corrigir bug #123', status: 'active', statusText: 'Em andamento', icon: '🐛' },
  { id: 3, text: 'Revisar pull request', status: 'pending', statusText: 'Pendente', icon: '👀' },
  { id: 4, text: 'Deploy em produção', status: 'pending', statusText: 'Pendente', icon: '🚀' },
  { id: 5, text: 'Implementar feature X', status: 'completed', statusText: 'Concluído', icon: '✅' }
];

const statusColors = {
  active: { bg: '#d4edda', text: '#155724' },
  pending: { bg: '#fff3cd', text: '#856404' },
  completed: { bg: '#cce5ff', text: '#004085' },
  cancelled: { bg: '#f8d7da', text: '#721c24' }
};

new VanillaSmartSelect('#tasks', {
  data: tasksData,
  placeholder: 'Selecione as tasks...',
  multiple: true,
  maximumSelectionLength: 4,
  templateResult: (item) => {
    const div = document.createElement('div');
    div.style.display = 'flex';
    div.style.alignItems = 'center';
    div.style.justifyContent = 'space-between';
    div.style.gap = '12px';
    const colors = statusColors[item.status];
    div.innerHTML = `
      <span style="font-size: 20px;">${item.icon}</span>
      <span style="flex: 1;">${item.text}</span>
      <span style="padding: 3px 10px; border-radius: 12px; font-size: 11px; 
                   font-weight: 600; background: ${colors.bg}; color: ${colors.text};">
        ${item.statusText}
      </span>
    `;
    return div;
  },
  templateSelection: (item) => {
    return `${item.icon} ${item.text} - ${item.statusText}`;
  }
});

Categorias com Contadores

Template simplificado na seleção, detalhado no dropdown.

Ver código

HTML

<select id="categories"></select>

JavaScript

const categoriesData = [
  { id: 1, text: 'Documentos', icon: '📄', count: 127 },
  { id: 2, text: 'Imagens', icon: '🖼️', count: 543 },
  { id: 3, text: 'Vídeos', icon: '🎬', count: 89 },
  { id: 4, text: 'Músicas', icon: '🎵', count: 234 },
  { id: 5, text: 'Planilhas', icon: '📊', count: 67 }
];

new VanillaSmartSelect('#categories', {
  data: categoriesData,
  placeholder: 'Selecione uma categoria...',
  allowClear: true,
  templateResult: (item) => {
    const div = document.createElement('div');
    div.style.display = 'flex';
    div.style.alignItems = 'center';
    div.style.gap = '10px';
    div.innerHTML = `
      <span style="font-size: 24px;">${item.icon}</span>
      <div style="flex: 1;">
        <span style="font-weight: 500;">${item.text}</span>
        <span style="font-size: 11px; color: #666; background: #e9ecef; 
                     padding: 2px 6px; border-radius: 10px; margin-left: 8px;">
          ${item.count} itens
        </span>
      </div>
    `;
    return div;
  },
  templateSelection: (item) => {
    return `${item.icon} ${item.text}`;
  }
});

Como Funcionam os Templates

📋 Conceitos Principais:
  • templateResult: Controla a aparência dos itens no dropdown (lista suspensa)
  • templateSelection: Controla a aparência do item selecionado (campo de seleção)
  • Retorno: Pode retornar string HTML ou elemento DOM (createElement)
  • Emojis nativos: Funcionam em todos os navegadores modernos, sem imagens externas
  • CSS inline: Estilos aplicados diretamente nos elementos para simplicidade

Técnicas e Boas Práticas

📋 Dicas para Templates Eficientes:
  • createElement vs innerHTML: Use createElement para maior segurança e performance
  • Fallback de dados: Sempre verifique se propriedades existem antes de usar
  • CSS inline vs classes: Inline é mais simples para exemplos, classes são melhores para produção
  • Performance: Templates são renderizados para cada item visível - evite operações pesadas
  • Teste com volume: Verifique performance com 100+ itens no select
  • Mantenha simples na seleção: templateSelection deve ser conciso
  • Detalhes no dropdown: templateResult pode ter mais informações e elementos visuais
📌 Recomendações de Acessibilidade:
  • Contraste: Mantenha contraste adequado entre texto e fundo (WCAG AA)
  • Tamanhos consistentes: Use tamanhos consistentes de ícones e elementos visuais
  • Use emojis nativos: Funcionam bem em leitores de tela e não dependem de recursos externos
  • Mobile responsive: Templates devem funcionar bem em telas pequenas
  • Loading states: Forneça feedback visual para carregamento de dados remotos
← Validação i18n →