Skip to main content English Español Light Dark System

List Picker

<gstock-list-picker> | GstockListPicker

Examples

Básico

El componente List Picker permite seleccionar elementos de una lista con funcionalidad de búsqueda integrada.

<gstock-list-picker label="Selecciona una fruta"></gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('gstock-list-picker');

    picker.items = [
      { value: '1', label: 'Manzana' },
      { value: '2', label: 'Banana' },
      { value: '3', label: 'Naranja' },
      { value: '4', label: 'Fresa' },
      { value: '5', label: 'Uva' },
    ];
  });
</script>

Selección Múltiple

Utilice el atributo multiple para habilitar la selección de múltiples elementos.

<gstock-list-picker id="multiple-picker" label="Programming languages" multiple></gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('#multiple-picker');

    picker.items = [
      { value: '1', label: 'JavaScript' },
      { value: '2', label: 'TypeScript' },
      { value: '3', label: 'Python' },
      { value: '4', label: 'Java' },
      { value: '5', label: 'C#' },
      { value: '6', label: 'Go' },
      { value: '7', label: 'Rust' },
      { value: '8', label: 'PHP' },
    ];
  });
</script>

Tamaños

Utilice el atributo size para cambiar el tamaño de los controles internos. Para controlar la altura del componente, use la custom property --height (por defecto fit-content, que se adapta al contenido).

<div class="sizes-demo">
  <div>
    <gstock-list-picker id="small-picker" label="Small (200px)" size="small" class="height-small"></gstock-list-picker>
  </div>
  <div>
    <gstock-list-picker id="medium-picker" label="Medium (350px)" size="medium" class="height-medium"></gstock-list-picker>
  </div>
  <div>
    <gstock-list-picker id="large-picker" label="Large (500px)" size="large" class="height-large"></gstock-list-picker>
  </div>
</div>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const items = [
      { value: '1', label: 'Item 1' },
      { value: '2', label: 'Item 2' },
      { value: '3', label: 'Item 3' },
      { value: '4', label: 'Item 4' },
      { value: '5', label: 'Item 5' },
    ];

    document.querySelector('#small-picker').items = items;
    document.querySelector('#medium-picker').items = items;
    document.querySelector('#large-picker').items = items;
  });
</script>

<style>
  .sizes-demo {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: var(--gstock-space-gap-lg);
  }

  .height-small {
    --height: 200px;
  }

  .height-medium {
    --height: 350px;
  }

  .height-large {
    --height: 500px;
  }
</style>

Con Valores Preseleccionados

Puede establecer valores preseleccionados mediante el atributo value.

<div class="preselected-demo">
  <gstock-list-picker label="Selección Simple" id="preselected-single" value="2"></gstock-list-picker>

  <gstock-list-picker label="Selección Múltiple" id="preselected-multiple" multiple></gstock-list-picker>
</div>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const items = [
      { value: '1', label: 'Rojo' },
      { value: '2', label: 'Verde' },
      { value: '3', label: 'Azul' },
      { value: '4', label: 'Amarillo' },
    ];

    document.querySelector('#preselected-single').items = items;

    const multiplePicker = document.querySelector('#preselected-multiple');
    multiplePicker.items = items;
    multiplePicker.value = ['1', '3'];
  });
</script>

<style>
  .preselected-demo {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: var(--gstock-space-gap-lg);
  }

  .preselected-demo h4 {
    margin-top: 0;
    margin-bottom: var(--gstock-space-gap-sm);
    color: var(--gstock-color-text-primary);
  }
</style>

Placeholder Personalizado

Utilice el atributo placeholder para personalizar el texto del buscador.

<gstock-list-picker id="placeholder-picker" placeholder="Buscar ciudades..."></gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('#placeholder-picker');

    picker.items = [
      { value: '1', label: 'Madrid' },
      { value: '2', label: 'Barcelona' },
      { value: '3', label: 'Valencia' },
      { value: '4', label: 'Sevilla' },
      { value: '5', label: 'Bilbao' },
    ];
  });
</script>

Label y Help Text

Utilice los atributos label y help-text para añadir contexto al componente.

<gstock-list-picker id="list-picker-label" label="Selecciona un país" help-text="Elige tu país de residencia" placeholder="Buscar países..." size="medium"></gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const listPicker = document.querySelector('#list-picker-label');

    const countries = [
      { value: 'es', label: 'España' },
      { value: 'fr', label: 'Francia' },
      { value: 'de', label: 'Alemania' },
      { value: 'it', label: 'Italia' },
      { value: 'pt', label: 'Portugal' },
      { value: 'uk', label: 'Reino Unido' },
      { value: 'us', label: 'Estados Unidos' },
      { value: 'ca', label: 'Canadá' },
      { value: 'mx', label: 'México' },
      { value: 'br', label: 'Brasil' },
      { value: 'ar', label: 'Argentina' },
      { value: 'cl', label: 'Chile' },
    ];

    listPicker.items = countries;
  });
</script>

Label y Help Text con Slots

También puede usar slots para personalizar el label y help text con HTML.

Idiomas preferidos Puedes seleccionar múltiples idiomas
<gstock-list-picker id="list-picker-slots" placeholder="Buscar idiomas..." size="medium">
  <span slot="label" class="custom-label">
    <gstock-icon name="globe"></gstock-icon>
    Idiomas preferidos
  </span>
  <span slot="help-text" class="custom-help">
    <gstock-icon name="info"></gstock-icon>
    Puedes seleccionar múltiples idiomas
  </span>
</gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const listPicker = document.querySelector('#list-picker-slots');

    const languages = [
      { value: 'es', label: 'Español' },
      { value: 'en', label: 'Inglés' },
      { value: 'fr', label: 'Francés' },
      { value: 'de', label: 'Alemán' },
      { value: 'it', label: 'Italiano' },
      { value: 'pt', label: 'Portugués' },
      { value: 'zh', label: 'Chino' },
      { value: 'ja', label: 'Japonés' },
      { value: 'ko', label: 'Coreano' },
      { value: 'ar', label: 'Árabe' },
    ];

    listPicker.items = languages;
    listPicker.multiple = true;
  });
</script>

<style>
  .custom-label {
    display: flex;
    align-items: center;
    gap: var(--gstock-space-100);
    color: var(--gstock-color-text-primary);
    font-weight: var(--gstock-typography-font-weight-semibold);
  }

  .custom-help {
    display: flex;
    align-items: center;
    gap: var(--gstock-space-100);
    color: var(--gstock-color-text-secondary);
  }
</style>

Validación en Formularios

El componente soporta validación nativa de formularios HTML con el atributo required.

Enviar
<form class="form-container">
  <gstock-list-picker name="country" label="País de residencia" help-text="Este campo es obligatorio" placeholder="Selecciona un país..." required size="medium"></gstock-list-picker>

  <gstock-button type="submit" variant="primary">Enviar</gstock-button>
</form>

<div id="result" class="result-container"></div>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const form = document.querySelector('form');
    const listPicker = document.querySelector('gstock-list-picker');
    const result = document.querySelector('#result');

    const countries = [
      { value: 'es', label: 'España' },
      { value: 'fr', label: 'Francia' },
      { value: 'de', label: 'Alemania' },
      { value: 'it', label: 'Italia' },
      { value: 'pt', label: 'Portugal' },
      { value: 'uk', label: 'Reino Unido' },
      { value: 'us', label: 'Estados Unidos' },
      { value: 'ca', label: 'Canadá' },
      { value: 'mx', label: 'México' },
      { value: 'br', label: 'Brasil' },
    ];

    listPicker.items = countries;

    form.addEventListener('submit', event => {
      event.preventDefault();

      if (!listPicker.checkValidity()) {
        listPicker.reportValidity();
        return;
      }

      const formData = new FormData(form);
      const selectedCountry = formData.get('country');

      if (selectedCountry) {
        const countryLabel =
          countries.find(c => c.value === selectedCountry)?.label || selectedCountry;
        result.innerHTML = `
          <div class="success-message">
            ✓ Formulario enviado correctamente<br>
            País seleccionado: <strong>${countryLabel}</strong>
          </div>
        `;
      }
    });

    listPicker.addEventListener('gstock-change-event', () => {
      result.innerHTML = '';
    });
  });
</script>

<style>
  .form-container {
    display: flex;
    flex-direction: column;
    gap: var(--gstock-space-gap-xl);
  }

  .result-container {
    margin-top: var(--gstock-space-gap-xl);
  }

  .success-message {
    padding-block: var(--gstock-space-padding-block-lg);
    padding-inline: var(--gstock-space-padding-inline-lg);
    background-color: var(--gstock-color-background-success);
    color: var(--gstock-color-text-success);
    border-radius: var(--gstock-border-radius-md);
    border: var(--gstock-border-width) solid var(--gstock-color-border-success);
  }
</style>

Items Deshabilitados

Los items pueden estar deshabilitados individualmente.

<gstock-list-picker id="disabled-items-picker"></gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('#disabled-items-picker');

    picker.items = [
      { value: '1', label: 'Disponible' },
      { value: '2', label: 'No disponible', disabled: true },
      { value: '3', label: 'Disponible' },
      { value: '4', label: 'Agotado', disabled: true },
      { value: '5', label: 'Disponible' },
    ];
  });
</script>

Componente Deshabilitado

Utilice el atributo disabled para deshabilitar todo el componente.

<gstock-list-picker id="disabled-picker" disabled></gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('#disabled-picker');

    picker.items = [
      { value: '1', label: 'Item 1' },
      { value: '2', label: 'Item 2' },
      { value: '3', label: 'Item 3' },
    ];
  });
</script>

Búsqueda

El componente incluye un buscador integrado que filtra los items localmente.

<gstock-list-picker id="search-picker" placeholder="Buscar países..."></gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('#search-picker');

    picker.items = [
      { value: '1', label: 'España' },
      { value: '2', label: 'Francia' },
      { value: '3', label: 'Italia' },
      { value: '4', label: 'Alemania' },
      { value: '5', label: 'Portugal' },
      { value: '6', label: 'Reino Unido' },
      { value: '7', label: 'Países Bajos' },
      { value: '8', label: 'Bélgica' },
      { value: '9', label: 'Suiza' },
      { value: '10', label: 'Austria' },
    ];
  });
</script>

Scroll Virtual con Muchos Items

El componente utiliza scroll virtual para manejar eficientemente grandes cantidades de datos.

<gstock-list-picker id="virtual-scroll-picker" multiple placeholder="Buscar en 1000 items..."></gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('#virtual-scroll-picker');

    picker.items = Array.from({ length: 1000 }, (_, i) => ({
      value: `${i + 1}`,
      label: `Item ${i + 1}`,
    }));
  });
</script>

<style>
  gstock-list-picker {
    --height: 400px;
  }
</style>

Modo Asíncrono

Utilice el atributo async para cargar datos desde un servidor. El componente emitirá el evento gstock-search-event cada vez que el usuario escriba en el buscador.

<gstock-list-picker id="async-picker" async debounce-delay="300" placeholder="Buscar usuarios (simulado)..."></gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('#async-picker');

    const allUsers = [
      { value: '1', label: 'Ana García' },
      { value: '2', label: 'Juan Martínez' },
      { value: '3', label: 'María López' },
      { value: '4', label: 'Carlos Rodríguez' },
      { value: '5', label: 'Laura Fernández' },
      { value: '6', label: 'Pedro Sánchez' },
      { value: '7', label: 'Carmen Jiménez' },
      { value: '8', label: 'David Torres' },
    ];

    picker.addEventListener('gstock-search-event', e => {
      const query = e.detail.search.toLowerCase();
      picker.loading = true;

      setTimeout(() => {
        if (query) {
          picker.items = allUsers.filter(user => user.label.toLowerCase().includes(query));
        } else {
          picker.items = allUsers;
        }
        picker.loading = false;
      }, 500);
    });

    picker.items = allUsers;
  });
</script>

Eventos

El componente emite eventos cuando cambia la selección.

Log de Eventos:

<div>
  <gstock-list-picker id="events-picker" multiple></gstock-list-picker>

  <div class="event-log">
    <h4>Log de Eventos:</h4>
    <div id="event-output"></div>
  </div>
</div>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('#events-picker');
    const output = document.querySelector('#event-output');

    picker.items = [
      { value: '1', label: 'Option A' },
      { value: '2', label: 'Option B' },
      { value: '3', label: 'Option C' },
      { value: '4', label: 'Option D' },
    ];

    function logEvent(eventName, detail) {
      const entry = document.createElement('div');
      entry.className = 'event-entry';
      entry.innerHTML = `<strong>${eventName}</strong>: ${JSON.stringify(detail)}`;
      output.insertBefore(entry, output.firstChild);

      if (output.children.length > 5) {
        output.removeChild(output.lastChild);
      }
    }

    picker.addEventListener('gstock-change-event', () => {
      logEvent('gstock-change-event', picker.value);
    });

    picker.addEventListener('gstock-clear-event', () => {
      logEvent('gstock-clear-event', 'Selección limpiada');
    });
  });
</script>

<style>
  .event-log {
    margin-top: var(--gstock-space-gap-lg);
    padding: var(--gstock-space-padding-md);
    background-color: var(--gstock-color-background-secondary);
    border-radius: var(--gstock-border-radius-md);
  }

  .event-log h4 {
    margin-top: 0;
    margin-bottom: var(--gstock-space-gap-sm);
    color: var(--gstock-color-text-primary);
  }

  #event-output {
    font-family: monospace;
    font-size: 0.875rem;
  }

  .event-entry {
    padding: var(--gstock-space-padding-xs);
    margin-bottom: var(--gstock-space-gap-xs);
    background-color: var(--gstock-color-background-primary);
    border-radius: var(--gstock-border-radius-sm);
  }

  .event-entry strong {
    color: var(--gstock-color-text-primary);
  }
</style>

Límite de Chips Visibles

Utilice el atributo max-chips-visible para controlar cuántos chips se muestran en el footer antes de colapsar.

Máximo 2 chips visibles:

<div>
  <h4>Máximo 2 chips visibles:</h4>
  <gstock-list-picker id="chips-limit-picker" multiple max-chips-visible="2"></gstock-list-picker>
</div>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('#chips-limit-picker');

    picker.items = [
      { value: '1', label: 'Tag 1' },
      { value: '2', label: 'Tag 2' },
      { value: '3', label: 'Tag 3' },
      { value: '4', label: 'Tag 4' },
      { value: '5', label: 'Tag 5' },
    ];

    picker.value = ['1', '2', '3', '4', '5'];
  });
</script>

<style>
  h4 {
    margin-top: 0;
    margin-bottom: var(--gstock-space-gap-sm);
    color: var(--gstock-color-text-primary);
  }
</style>

Sin Seleccionar Todo

Utilice show-select-all="false" para ocultar el checkbox de seleccionar todo en modo múltiple.

<gstock-list-picker id="no-select-all-picker" multiple show-select-all="false"></gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('#no-select-all-picker');

    picker.items = [
      { value: '1', label: 'Item 1' },
      { value: '2', label: 'Item 2' },
      { value: '3', label: 'Item 3' },
      { value: '4', label: 'Item 4' },
    ];
  });
</script>

Slot Personalizado para Estado Vacío

Puede personalizar el mensaje cuando no hay resultados usando el slot empty.

No se encontraron resultados

Intenta con otros términos de búsqueda

<gstock-list-picker search="xyz">
  <div slot="empty" class="custom-empty">
    <gstock-icon name="search"></gstock-icon>
    <p>No se encontraron resultados</p>
    <p class="empty-hint">Intenta con otros términos de búsqueda</p>
  </div>
</gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('gstock-list-picker');

    picker.items = [
      { value: '1', label: 'Apple' },
      { value: '2', label: 'Banana' },
      { value: '3', label: 'Cherry' },
    ];
  });
</script>

<style>
  .custom-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--gstock-space-padding-2xl);
    text-align: center;
  }

  .custom-empty gstock-icon {
    font-size: 3rem;
    opacity: 0.3;
    margin-bottom: var(--gstock-space-gap-md);
  }

  .custom-empty p {
    margin: var(--gstock-space-gap-xs) 0;
    color: var(--gstock-color-text-primary);
  }

  .empty-hint {
    font-size: 0.875rem;
    color: var(--gstock-color-text-secondary);
  }
</style>

Altura de Item Personalizada

Si necesita items más altos, ajuste el atributo item-height.

<gstock-list-picker id="custom-height-picker" item-height="60"></gstock-list-picker>

<script type="module">
  customElements.whenDefined('gstock-list-picker').then(() => {
    
    const picker = document.querySelector('#custom-height-picker');

    picker.items = [
      { value: '1', label: 'Item con altura de 60px' },
      { value: '2', label: 'Item con altura de 60px' },
      { value: '3', label: 'Item con altura de 60px' },
      { value: '4', label: 'Item con altura de 60px' },
    ];
  });
</script>