Erase una vez …que un cliente pidió un cambio de diseño en una web casi terminada y con fecha de lanzamiento. Deseaba agregar (muy pertinentemente) un panel de pestañas con información sobre su producto.

El problema

Teniendo un día para implementar diseño, maquetación y backend, como sabemos, los componentes de pestañas no funcionan muy bien en mobile. El diseño mostraba un acordeón para la versión mobile.

 

La solución inmediata

Decidí construir dos componentes separados, uno de pestañas para vistas tablet a más, y uno de acordeón para celulares.

 

La vida real

Esta solución no nos gustaba, de hecho, con más tiempo, hubiera buscado la forma de destruir el componente de pestañas para vistas mobile y reconstruirlo en JavaScript para celulares en forma de acordeón.

Es así, que un día mostrando los proyectos desarrollados , una alumna revisó esa web, y me dijo “profesor su web tiene un pequeño error, el estado de la pestaña activa no refresca cuando cambio el tamaño de la pantalla!” Los más duchos ya se habrán dado cuenta del problema, eran dos componentes y no había ningun relación entre ellos… (y claro, no habíamos usado ni JS, era una época pre React). Expliqué a mi alumna la misma historia que les he contado ahora, sobre los tiempos del proyecto, la deuda tecnológica, y las realidades del desarrollo cuando hay clientes y presupuestos.

Sin embargo, me quedé pensando en que todo eso eran excusas, esa deuda no se pagó nunca y me quedé con la espina clavada de hacerlo bien.

La solución actual

Preguntándome como haría esto hoy en día, con las nuevas propiedades de CSS, los nuevos frameworks de JavaScript y demás, me puse a pensar como podría hacer que mi panel de tabs se convierta o tome la forma de un acordeón cuando pase a la vista móvil y mantenga la pestaña activa correspondiente, sin necesidad de tener dos componentes por separado, el detalle es que yo no domino mucho JavaScript avanzado, así que terminé encontrando una solución sencilla basada en flexbox que consigue cumplir los resultados.

 

Les dejo un demo y el código:

El HTML



<div class="aco">
  <a href="#uno"><span>&#9730;</span> Uno</a>
  <div id="uno">
    <h2>Uno</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Omnis magni laborum error fugiat veniam sunt officia mollitia ipsam dolores quas perferendis qui eius maiores, doloribus dolor quo deleniti tenetur! Sequi.</p>
  </div>
  <a href="#dos"><span>&#9742;</span> Dos</a>
  <div id="dos">
    <h2>Dos</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Omnis magni laborum error fugiat veniam sunt officia mollitia ipsam dolores quas perferendis qui eius maiores, doloribus dolor quo deleniti tenetur! Sequi.</p>
  </div>
  <a href="#tres"><span>&#9883;</span> Tres</a>
  <div id="tres">
    <h2>Uno</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Omnis magni laborum error fugiat veniam sunt officia mollitia ipsam dolores quas perferendis qui eius maiores, doloribus dolor quo deleniti tenetur! Sequi.</p>
  </div>
  <a href="#cuatro"><span>&#9992;</span> Cuatro</a>
  <div id="cuatro">
    <h2>Cuatro</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Omnis magni laborum error fugiat veniam sunt officia mollitia ipsam dolores quas perferendis qui eius maiores, doloribus dolor quo deleniti tenetur! Sequi.</p>
  </div>
</div>

un poco de CSS


.aco{
  border: solid 1px #000;
}
  .aco a{
    display: block;
    padding: 10px;
    color: #fff;
    background-color: #000;
    text-decoration: none;
    transition: background .4s;
  }
  .aco a.active{
    background-color: purple;
  }
  .aco div{
    padding: 10px;
    display: none;
  }
  
 
 @media screen and (min-width: 800px){
   .aco{
     display: flex;
     flex-wrap: wrap;
   }
   .aco div{
     border-top: solid 10px purple;
   }
   .aco a{
      order: -1;
      flex-grow: 1;
      text-align: center;
    }
    .aco a span{
      display: block;
      font-size: 30px;
    }
    .aco a:hover{
      background-color: purple;
    }
 }

Por último el JS



(function(){
	var $links = document.querySelectorAll(".aco a");
  var $targets = document.querySelectorAll(".aco div");



  for	(var i=0; i< $links.length; i++){
    $links[i].addEventListener("click", showContent);
  }

  function deActiveLinks(){
    for	(var i=0; i<$links.length; i++){
      $links[i].classList.remove("active");
    }
  }

  function hideTargets(){
    for	(var i=0; i<$targets.length; i++){
      $targets[i].style.display = "none";
    }
  }

  function showContent(){
    var $this = this;
    var anchor = this.hash;
    var $target = document.querySelector(anchor);
    deActiveLinks();
    $this.classList.add("active");
    hideTargets();
    $target.style.display = "block";
  }
  $links[0].click();


})()