Skip to content

Component TheTabs

¡Bienvenido a la documentación del componente TheTabs! 🚀

Este componente está diseñado para ser flexible, reactivo y fácil de usar, permitiéndote crear interfaces de usuario complejas con muy poco esfuerzo.

Para usar TheTabs, necesitas dos cosas principales:

  1. Una lista de pestañas (un array de objetos).
  2. Contenido para cada una de esas pestañas, que se pasará a través de slots.

Imagina que quieres crear tres pestañas: “Perfil”, “Cuenta” y “Ajustes”.

<script setup lang="ts">
import type { TabOption } from '@/interfaces/api/common';
const tabList: TabOption[] = [
{ id: 'profile', title: 'Perfil' },
{ id: 'account', title: 'Cuenta' },
{ id: 'settings', title: 'Ajustes' },
];
const handleTabChange = (tabId: string) => console.log(`Pestaña activa: ${tabId}`);
</script>
<template>
<UiTabsTheTabs :list="tabList" @tab-change-action="handleTabChange">
<template #profile>
<p>Aquí va el contenido del perfil de usuario.</p>
</template>
<template #account>
<p>Aquí puedes gestionar la información de tu cuenta.</p>
</template>
<template #settings>
<p>Configura tus preferencias y ajustes aquí.</p>
</template>
</UiTabsTheTabs>
</template>

Paso 1: Define tus pestañas

Crea un array de objetos TabOption. Cada objeto debe tener un id (único) y un title (el texto que se mostrará).

Paso 2: Pasa los datos al componente

Usa la prop :list para pasar tu array de pestañas al componente <TheTabs>.

Paso 3: Añade el contenido

Para cada pestaña, crea un <template> con un slot nombrado. El nombre del slot DEBE coincidir con el id de la pestaña. Por ejemplo, #profile para la pestaña con id: 'profile'.

Paso 4: Escucha los cambios

Puedes escuchar el evento @tab-change-action para ejecutar una función cada vez que el usuario cambie de pestaña.


Aquí tienes todos los detalles técnicos que necesitas saber.

El componente acepta las siguientes propiedades:

PropTipoRequeridoDescripción
listTabOption[]Un array de objetos para definir las pestañas.

La interfaz TabOption tiene la siguiente estructura:

interface TabOption {
id: string; // Identificador único para la pestaña y el slot
title: string; // Texto visible en la cabecera de la pestaña
}

Los slots son la forma de “inyectar” contenido dentro del componente.

SlotDescripción
idUn slot dinámico nombrado. Debes proporcionar un slot por cada id en tu list de pestañas.

El componente emite los siguientes eventos:

EventoPayloadDescripción
tabChangeActionid: stringSe dispara cuando el usuario hace clic en una pestaña, enviando el id de la misma.

¿Quieres saber cómo funciona el componente por dentro? ¡Presta atención!

Lógica Principal

  1. Props y Emits: Se definen las props (list) y los emits (tabChangeAction) usando las APIs de Composition de Vue.

  2. Reactividad:

    • activeTab: Un ref que almacena el id de la pestaña activa. Se inicializa con el id del primer elemento de la list.
    • tabUnderlineStyles: Un ref que contiene los estilos CSS (width y transform) para la línea animada que subraya la pestaña activa.
  3. Manejo de Eventos:

    • selectActiveTab(id): Esta función asíncrona es el núcleo de la interactividad.
      • Actualiza activeTab.value con el nuevo id.
      • Emite el evento tabChangeAction.
      • Usa nextTick() para esperar a que el DOM se actualice (Vue necesita un momento para aplicar la clase --active).
      • Llama a changeUnderlineStyles para mover el subrayado.
  4. Animación del Subrayado:

    • changeUnderlineStyles(element): Esta función recibe el elemento HTML de la pestaña activa.
      • Mide su offsetWidth (ancho) y offsetLeft (posición desde la izquierda).
      • Calcula los nuevos valores para width y transform: translateX() y los guarda en tabUnderlineStyles. Los valores se convierten a em para que sean relativos al tamaño de la fuente.
  5. Ciclo de Vida y Watchers:

    • onMounted(): Cuando el componente se monta, se llama a changeUnderlineStyles para posicionar el subrayado inicial debajo de la primera pestaña.
    • watch(props, ...): Si la list de pestañas cambia desde el componente padre, este watcher se asegura de que la primera pestaña de la nueva lista se seleccione automáticamente.

Estructura HTML

  • Lista de Pestañas:

    • Se usa v-for para iterar sobre la lista y renderizar un <button> por cada pestaña.
    • La clase tabs__item--active se aplica dinámicamente si el id de la pestaña coincide con el activeTab actual.
    • El evento @click llama a selectActiveTab(id).
  • El Subrayado:

    • Hay un div (tabs__indicator) cuya propiedad style está vinculada al ref tabUnderlineStyles.
    • Cuando tabUnderlineStyles cambia en el script, Vue actualiza automáticamente los estilos de este div, creando una transición suave y animada.
  • Contenido de las Pestañas:

    • Se vuelve a iterar sobre la list para crear una sección por cada pestaña.
    • Dentro de cada sección, se usa v-if="activeTab === id" para mostrar únicamente el contenido de la pestaña activa.
    • El componente <slot :name="id" /> es el lugar donde se renderizará el contenido que pasaste desde el padre a través de los templates nombrados (ej: <template #profile>).
    • Todo está envuelto en un componente <Transition> de Vue para añadir un efecto de fundido (fade-tab) al cambiar de pestaña.

Estilos con SCSS

  • Metodología BEM: Las clases siguen la nomenclatura BEM (Bloque__Elemento—Modificador), como tabs__item y tabs__item--active. Esto mantiene el CSS organizado y previene colisiones de estilos.
  • Variables CSS: Se usan variables (var(--c-primary)) para los colores, lo que facilita la tematización y el mantenimiento.
  • Scroll Horizontal: En dispositivos móviles, si las pestañas no caben en la pantalla, se activa un scroll horizontal para que el usuario pueda desplazarse por ellas.
  • Estilos Responsivos: Se utiliza un mixin @include responsive() para adaptar la apariencia en diferentes tamaños de pantalla.