Skip to main content English Español Claro Oscuro Sistema

Board

<gstock-board> | GstockBoard

Ejemplos

Inicio Usuarios Configuración Ayuda
<gstock-board>
  <gstock-board-item value="home">
    <gstock-icon slot="prefix" name="home"></gstock-icon>
    Inicio
  </gstock-board-item>
  <gstock-board-item value="users">
    <gstock-icon slot="prefix" name="users"></gstock-icon>
    Usuarios
  </gstock-board-item>
  <gstock-board-item value="settings">
    <gstock-icon slot="prefix" name="settings"></gstock-icon>
    Configuración
  </gstock-board-item>
  <gstock-board-item value="help">
    <gstock-icon slot="prefix" name="help-circle"></gstock-icon>
    Ayuda
  </gstock-board-item>
</gstock-board>

Deshabilitado

Use el atributo disabled para deshabilitar la funcionalidad de arrastrar y soltar en toda la lista.

Elemento 1 (Lista deshabilitada) Elemento 2 (Lista deshabilitada) Elemento 3 (Lista deshabilitada)
<gstock-board disabled>
  <gstock-board-item value="item-1">Elemento 1 (Lista deshabilitada)</gstock-board-item>
  <gstock-board-item value="item-2">Elemento 2 (Lista deshabilitada)</gstock-board-item>
  <gstock-board-item value="item-3">Elemento 3 (Lista deshabilitada)</gstock-board-item>
</gstock-board>

Posicionamiento

Sistema inteligente que elimina posiciones duplicadas: cada elemento solo muestra líneas de inserción en posiciones únicas.

1 Primer elemento 2 Segundo elemento 3 Tercer elemento 4 Cuarto elemento 5 Quinto elemento (último)
🎯 Lógica sin redundancia:
  • Elementos 1-4: Solo muestran línea de inserción arriba
  • Último elemento (5): Solo muestra línea de inserción abajo
  • Resultado: Cada posición de inserción es única, sin redundancia
Orden actual:
🧪 Pruebas sugeridas:
  1. Arrastra el elemento 4 sobre el elemento 2 → debería ir a posición 2
  2. Arrastra el elemento 1 al final → solo podrás soltarlo abajo del elemento 5
  3. Observa que no hay duplicidad de posiciones
<gstock-board id="no-redundancy-test">
  <gstock-board-item value="item-1">
    <span class="item red">1</span>
    Primer elemento
  </gstock-board-item>
  <gstock-board-item value="item-2">
    <span class="item orange">2</span>
    Segundo elemento
  </gstock-board-item>
  <gstock-board-item value="item-3">
    <span class="item yellow">3</span>
    Tercer elemento
  </gstock-board-item>
  <gstock-board-item value="item-4">
    <span class="item green">4</span>
    Cuarto elemento
  </gstock-board-item>
  <gstock-board-item value="item-5">
    <span class="item blue">5</span>
    Quinto elemento (último)
  </gstock-board-item>
</gstock-board>

<div class="note">
  <strong>🎯 Lógica sin redundancia:</strong>
  <ul class="note__list">
    <li>
      <strong>Elementos 1-4:</strong>
      Solo muestran línea de inserción
      <em>arriba</em>
    </li>
    <li>
      <strong>Último elemento (5):</strong>
      Solo muestra línea de inserción
      <em>abajo</em>
    </li>
    <li>
      <strong>Resultado:</strong>
      Cada posición de inserción es única, sin redundancia
    </li>
  </ul>
</div>

<div class="order-block">
  <strong>Orden actual:</strong>
  <div id="current-order-no-redundancy" class="order-block__value"></div>
</div>

<div class="tips-block">
  <strong>🧪 Pruebas sugeridas:</strong>
  <ol class="tips-block__list">
    <li>Arrastra el elemento 4 sobre el elemento 2 → debería ir a posición 2</li>
    <li>Arrastra el elemento 1 al final → solo podrás soltarlo abajo del elemento 5</li>
    <li>Observa que no hay duplicidad de posiciones</li>
  </ol>
</div>

<script type="module">
  const list = document.getElementById('no-redundancy-test');
  const orderDisplay = document.getElementById('current-order-no-redundancy');

  function updateOrderDisplay() {
    const items = list.querySelectorAll('gstock-board-item');
    const order = Array.from(items).map(item => item.getAttribute('value'));
    orderDisplay.textContent = order.join(' → ');
  }

  // Initial display
  updateOrderDisplay();

  // Listen for sort events
  list.addEventListener('gstock-sort', e => {
    console.log('🔄 Sort sin redundancia:', e.detail);
    updateOrderDisplay();
  });

  list.addEventListener('gstock-drag-start', e => {
    console.log('🚀 Drag start:', e.detail.item.value);
  });

  list.addEventListener('gstock-drag-end', e => {
    console.log('🏁 Drag end:', e.detail.item.value);
  });
</script>

<style>
  .item {
    color: white;
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    font-weight: bold;
    margin-right: 0.5rem;
  }

  .item.red {
    background: #ef4444;
  }

  .item.orange {
    background: #f97316;
  }

  .item.yellow {
    background: #eab308;
  }

  .item.green {
    background: #22c55e;
  }

  .item.blue {
    background: #3b82f6;
  }

  .note {
    margin-top: 1rem;
    padding: 1rem;
    background: #fef3c7;
    border-radius: 4px;
    border-left: 4px solid #f59e0b;
  }

  .note__list {
    margin: 0.5rem 0 0 1.5rem;
    line-height: 1.6;
  }

  .order-block {
    margin-top: 1rem;
    padding: 1rem;
    background: #f3f4f6;
    border-radius: 4px;
  }

  .order-block__value {
    font-family: monospace;
    margin-top: 0.5rem;
    font-weight: bold;
  }

  .tips-block {
    margin-top: 1rem;
    padding: 1rem;
    background: #e0f2fe;
    border-radius: 4px;
  }

  .tips-block__list {
    margin: 0.5rem 0 0 1.5rem;
    line-height: 1.6;
  }
</style>

Lista Horizontal

Use el atributo orientation="horizontal" para crear una lista que se ordena horizontalmente.

Tab 1 Tab 2 Tab 3 Tab 4
<gstock-board orientation="horizontal">
  <gstock-board-item value="item-1">Tab 1</gstock-board-item>
  <gstock-board-item value="item-2">Tab 2</gstock-board-item>
  <gstock-board-item value="item-3">Tab 3</gstock-board-item>
  <gstock-board-item value="item-4">Tab 4</gstock-board-item>
</gstock-board>

<style>
  gstock-board[orientation='horizontal'] {
    display: flex;
    gap: 0.5rem;
  }

  gstock-board[orientation='horizontal'] gstock-board-item {
    min-width: 120px;
    text-align: center;
  }
</style>

Con Handle Personalizado

Use el atributo handle en los elementos para especificar un área específica como el controlador de arrastre.

Elemento con handle personalizado 1 Elemento con handle personalizado 2 Elemento con handle personalizado 3
<gstock-board>
  <gstock-board-item value="item-1" handle=".drag-handle">
    <gstock-icon slot="prefix" class="drag-handle" name="drag-indicator"></gstock-icon>
    Elemento con handle personalizado 1
  </gstock-board-item>
  <gstock-board-item value="item-2" handle=".drag-handle">
    <gstock-icon slot="prefix" class="drag-handle" name="drag-indicator"></gstock-icon>
    Elemento con handle personalizado 2
  </gstock-board-item>
  <gstock-board-item value="item-3" handle=".drag-handle">
    <gstock-icon slot="prefix" class="drag-handle" name="drag-indicator"></gstock-icon>
    Elemento con handle personalizado 3
  </gstock-board-item>
</gstock-board>

<style>
  .drag-handle {
    cursor: grab;
  }
</style>

Eventos

La lista emite eventos cuando los elementos son reordenados, arrastramos elementos o terminamos de arrastrar.

Elemento 1 Elemento 2 Elemento 3 Elemento 4

Log de eventos:

Limpiar log
<gstock-board>
  <gstock-board-item value="item-1">Elemento 1</gstock-board-item>
  <gstock-board-item value="item-2">Elemento 2</gstock-board-item>
  <gstock-board-item value="item-3">Elemento 3</gstock-board-item>
  <gstock-board-item value="item-4">Elemento 4</gstock-board-item>
</gstock-board>

<div class="board-events-section">
  <h4>Log de eventos:</h4>
  <div id="event-log"></div>
  <gstock-button id="clear-log" size="small" variant="outline">Limpiar log</gstock-button>
</div>

<script type="module">
  customElements.whenDefined('gstock-board').then(() => {
    
    const board = document.querySelector('gstock-board');
    const eventLog = document.getElementById('event-log');
    const clearLogBtn = document.getElementById('clear-log');

    function addLog(event, message) {
      const timestamp = new Date().toLocaleTimeString();
      const logEntry = document.createElement('div');
      logEntry.className = 'log-entry';
      logEntry.innerHTML = `<div><span class="timestamp">[${timestamp}]</span><strong>${event}</strong>:<span class="message">${message}</span></div>`;

      eventLog.appendChild(logEntry);
      eventLog.scrollTop = eventLog.scrollHeight;
    }

    board.addEventListener('gstock-sort-event', event => {
      addLog(
        'gstock-sort-event',
        `Element "${event.detail.item.value}" moved from ${event.detail.from} to ${event.detail.to}\n`,
      );
    });

    board.addEventListener('gstock-drag-start-event', event => {
      addLog('gstock-drag-start-event', `Start drag from "${event.detail.item.value}"\n`);
    });

    board.addEventListener('gstock-drag-end-event', event => {
      addLog('gstock-drag-end-event', `End drag from "${event.detail.item.value}"\n`);
    });

    clearLogBtn.addEventListener('click', () => {
      eventLog.innerHTML = '';
    });
  });
</script>

<style>
  .board-events-section {
    margin-top: 1rem;
  }

  h4 {
    margin: 0 0 0.5rem 0;
    color: var(--gstock-legacy-color-grayscale-700);
  }

  #event-log {
    border: 1px solid var(--gstock-legacy-color-grayscale-300);
    border-radius: var(--gstock-border-radius-sm);
    padding: 1rem;
    height: 150px;
    overflow-y: auto;
    background-color: var(--gstock-legacy-color-grayscale-50);
    font-family: var(--gstock-legacy-font-mono);
    font-size: var(--gstock-legacy-font-size-sm);
    margin-bottom: 0.5rem;
  }

  .log-entry {
    margin-bottom: 0.25rem;
    line-height: 1.4;
  }

  .timestamp {
    color: var(--gstock-legacy-color-grayscale-500);
    font-weight: 500;
  }

  .message {
    color: var(--gstock-legacy-color-grayscale-700);
  }

  #event-log:empty::before {
    color: var(--gstock-legacy-color-grayscale-400);
    font-style: italic;
  }
</style>

Accesibilidad

El componente incluye soporte completo para navegación por teclado usando las teclas de flecha, Space y Enter para reordenar elementos.

Use las teclas de flecha para navegar Presione Space o Enter para seleccionar Use las flechas para mover cuando esté seleccionado Presione Space o Enter para confirmar la nueva posición
Instrucciones de accesibilidad:
  • Use Tab para navegar a la lista
  • Use para navegar entre elementos
  • Presione Space o Enter para entrar en modo de reordenamiento
  • Use para mover el elemento seleccionado
  • Presione Space o Enter para confirmar la nueva posición
  • Presione Escape para cancelar el reordenamiento
<gstock-board>
  <gstock-board-item value="item-1">
    <gstock-icon slot="prefix" name="keyboard"></gstock-icon>
    Use las teclas de flecha para navegar
  </gstock-board-item>
  <gstock-board-item value="item-2">
    <gstock-icon slot="prefix" name="mouse-pointer"></gstock-icon>
    Presione Space o Enter para seleccionar
  </gstock-board-item>
  <gstock-board-item value="item-3">
    <gstock-icon slot="prefix" name="move"></gstock-icon>
    Use las flechas para mover cuando esté seleccionado
  </gstock-board-item>
  <gstock-board-item value="item-4">
    <gstock-icon slot="prefix" name="check"></gstock-icon>
    Presione Space o Enter para confirmar la nueva posición
  </gstock-board-item>
</gstock-board>

<div class="board-accessibility-info">
  <strong>Instrucciones de accesibilidad:</strong>
  <ul>
    <li>
      Use
      <kbd>Tab</kbd>
      para navegar a la lista
    </li>
    <li>
      Use
      <kbd></kbd>
      <kbd></kbd>
      para navegar entre elementos
    </li>
    <li>
      Presione
      <kbd>Space</kbd>
      o
      <kbd>Enter</kbd>
      para entrar en modo de reordenamiento
    </li>
    <li>
      Use
      <kbd></kbd>
      <kbd></kbd>
      para mover el elemento seleccionado
    </li>
    <li>
      Presione
      <kbd>Space</kbd>
      o
      <kbd>Enter</kbd>
      para confirmar la nueva posición
    </li>
    <li>
      Presione
      <kbd>Escape</kbd>
      para cancelar el reordenamiento
    </li>
  </ul>
</div>

<style>
  .board-accessibility-info {
    margin-top: 1rem;
    padding: 1rem;
    background: #e3f2fd;
    border-radius: 4px;
  }
  .board-accessibility-info ul {
    margin: 0.5rem 0 0 1.5rem;
  }
</style>

Depuración del Reordenamiento

Ejemplo para probar y depurar el funcionamiento del reordenamiento con feedback visual en tiempo real.

1 Primer elemento 2 Segundo elemento 3 Tercer elemento 4 Cuarto elemento 5 Quinto elemento
Orden actual:
🧪 Prueba de reordenamiento:
  1. Arrastra el elemento 3 antes del elemento 1
  2. Arrastra el elemento 5 entre el 2 y el 4
  3. Observa que el orden se actualiza correctamente abajo
<gstock-board id="test-list">
  <gstock-board-item value="item-1">
    <span class="board-debug-badge board-debug-badge--red">1</span>
    Primer elemento
  </gstock-board-item>
  <gstock-board-item value="item-2">
    <span class="board-debug-badge board-debug-badge--orange">2</span>
    Segundo elemento
  </gstock-board-item>
  <gstock-board-item value="item-3">
    <span class="board-debug-badge board-debug-badge--yellow">3</span>
    Tercer elemento
  </gstock-board-item>
  <gstock-board-item value="item-4">
    <span class="board-debug-badge board-debug-badge--green">4</span>
    Cuarto elemento
  </gstock-board-item>
  <gstock-board-item value="item-5">
    <span class="board-debug-badge board-debug-badge--blue">5</span>
    Quinto elemento
  </gstock-board-item>
</gstock-board>

<div class="board-debug-order">
  <strong>Orden actual:</strong>
  <div id="current-order" class="board-debug-order__value"></div>
</div>

<div class="board-debug-tips">
  <strong>🧪 Prueba de reordenamiento:</strong>
  <ol>
    <li>Arrastra el elemento 3 antes del elemento 1</li>
    <li>Arrastra el elemento 5 entre el 2 y el 4</li>
    <li>Observa que el orden se actualiza correctamente abajo</li>
  </ol>
</div>

<script type="module">
  const list = document.getElementById('test-list');
  const orderDisplay = document.getElementById('current-order');

  function updateOrderDisplay() {
    const items = list.querySelectorAll('gstock-board-item');
    const order = Array.from(items).map(item => item.getAttribute('value'));
    orderDisplay.textContent = order.join(' → ');
  }

  // Initial display
  updateOrderDisplay();

  // Listen for sort events
  list.addEventListener('gstock-sort', e => {
    console.log('Sort event:', e.detail);
    updateOrderDisplay();
  });
</script>

<style>
  .board-debug-badge {
    color: white;
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    font-weight: bold;
    margin-right: 0.5rem;
  }
  .board-debug-badge--red {
    background: #f87171;
  }
  .board-debug-badge--orange {
    background: #fb923c;
  }
  .board-debug-badge--yellow {
    background: #fbbf24;
  }
  .board-debug-badge--green {
    background: #34d399;
  }
  .board-debug-badge--blue {
    background: #60a5fa;
  }
  .board-debug-order {
    margin-top: 1rem;
    padding: 1rem;
    background: #f3f4f6;
    border-radius: 4px;
  }
  .board-debug-order__value {
    font-family: monospace;
    margin-top: 0.5rem;
  }
  .board-debug-tips {
    margin-top: 1rem;
    padding: 1rem;
    background: #fef3c7;
    border-radius: 4px;
    border-left: 4px solid #f59e0b;
  }
  .board-debug-tips ol {
    margin: 0.5rem 0 0 1.5rem;
  }
</style>