Skip to content

Tabs

1. Descripción General

Componente de interfaz de usuario que renderiza una lista de pestañas y muestra contenido dinámico asociado a cada una. Está diseñado para ser reutilizable y responsivo.

2. Estructura de Uso

Para utilizar el componente en una vista puedes seguir el siguiente ejemplo, donde se utilizan los componentes de los Tabs y los métodos disponibles en su composable:

<script setup lang="ts">
import { tabCardList } from "@/mocks/tabsCard";
const { tabComponents, getComponentName } = useTabs(ref(tabCardList));
</script>
<template>
<UiTabsMainTabs :tabs="tabCardList" v-slot="{ activeTab }">
<component :tabContent="activeTab" :is="tabComponents[getComponentName(activeTab)]" />
</UiTabsMainTabs>
</template>

3. Interfaz Tab

  • Descripción: La interfaz que utilizan los Tabs que se vayan a crear viene definida en @/interfaces/api/common.ts
  • Estructura:
    • id (number): Identificador de cada Tab
    • label (string): Nombre que mostrará el Tab a la hora de usarlo
    • component (string): Componente que invocará dicha Tab

Ejemplos de Tabs

export const tabCardList = [
{
id: 0,
label: "Tab 1",
component: "TabsAccount",
},
{
id: 1,
label: "Tab 2",
component: "TabsAccount",
},
{
id: 2,
label: "Tab 3",
component: "TabsAccount",
},
];

4. Componente


MainTabs.vue

  • Descripción: Componente principal que se encarga de cargar los componentes necesarios para los Tabs
  • v-slot: Le llega, por medio de v-slot, el índice correspondiente al contenido del Tab activo
  • Props:
    • tabs (Tabs[]): Array de todos los Tabs a mostrar en la página donde se utilicen
  • <component/>:
    • tabContent (number): Indexa el contenido que se va a mostrar según la Tab activa
    • is (tabComponents[getComponentName(activeTab)]): Indica cual es el componente a cargar en base al que viene definido en el campo component: de cada Tab
  • Ejemplo de Uso:
    <template>
    // ...
    <UiTabsMainTabs :tabs="tabCardList" v-slot="{ activeTab }">
    <component :tabContent="activeTab" :is="tabComponents[getComponentName(activeTab)]" />
    </UiTabsMainTabs>
    // ...
    </template>

5. Creación de Tabs

Para agregar nuevos Tabs a una página, se deberá crear un componente que contenga todo el contenido de los Tabs. Los components que tengan el contenido de los Tabs, deberán ir definidos dentro de una carpeta, la cual tendrá, de nombre, el nombre de la página donde se quiera acceder. Esta carpeta deberá crearse en @/components/ui/tabs.

Dentro de estos deberá definirse el prop de tabContent, el cual le indicará al componente cual es la sección de contenido que debe mostrar por medio de v-if y v-else-if. Todo el contenido deberá ser introducido en una sección, ya sea la importación de un código, el uso de markdown o el uso de HTML.

Todas estas secciones deberán ir dentro de la etiqueta Transition cuyas características serán las siguientes:

  • name: Nombre de la animación que se utilizará al cambiar de Tab (definidas en @/assets/styles/vueTransitions.css)
  • mode (opcional): Indica el modo en el que se empleará la animación (se recomienda out-in)

Ejemplo de creación

Creación de las carpetas para las páginas account y videos-3d-formacion-dental

/
└─components/
└─ui/
└─tabs/
├── MainTabs.vue
├── account/
│ ├── ComponentTest.vue
│ └── TabsAccount.vue
└── videos-3d-formacion-dental/
└── TabsVideo.vue

Dentro de TabsAccount.vue y TabsVideo.vue va todo el contenido de los Tabs separado en sections.

<script setup>
const props = defineProps({
tabContent: Number,
});
const { getSanitizedDescription } = useMarkdownParser(); // Para el uso de markdown
const { sanitizedDescription } = getSanitizedDescription(
"## Bienvenido al Tab 2 \n Esto es un ejemplo de markdown: \n - Item 1 \n - Item 2 \n - Item 3"
);
</script>
<template>
<Transition name="fade-tab" mode="out-in">
<section v-if="props.tabContent === 0">
<h2>Bienvenido al Tab 1</h2>
</section>
<section v-else-if="props.tabContent === 1" v-html="sanitizedDescription"></section>
<section v-else-if="props.tabContent === 2">
<UiTabsAccountComponentTest />
</section>
</Transition>
</template>

6. Composable

useTabs

Composable que administra un sistema de tabs dinámico, cargando componentes asociados de manera automática según la ruta actual.

Parámetros

ParámetroTipoDescripción
dataTabsRef<Tab[]>Lista reactiva de objetos Tab que representan las pestañas.

Funciones

getComponentName(index: number): string

Retorna el nombre del componente asociado al tab en el índice dado.

  • Parámetros: index - índice del tab.
  • Retorno: string - Nombre del componente o cadena vacía si no existe.
loadComponents()

Carga de manera dinámica los componentes de tabs relevantes a la página actual.

  • Acciones:
    • Filtra los archivos Vue ubicados bajo @/components/ui/tabs/{paginaActual}.
    • Importa los componentes encontrados.
    • Actualiza el estado tabComponents con los componentes cargados.
  • Retorno: Promise<void>

Retorno

Un objeto con las siguientes propiedades y funciones:

PropiedadTipoDescripción
dataTabsRef<Tab[]>Lista reactiva de tabs disponibles.
activeTabRef<number>Índice del tab actualmente activo.
tabRefsRef<HTMLButtonElement[]>Referencias a los botones de las pestañas.
tabsWrapperRefRef<HTMLElement | null>Referencia al contenedor de las pestañas.
tabIndicatorStylesComputedRef<{ width: string; transform: string }>Estilos CSS dinámicos para el indicador visual del tab activo.
tabComponentsShallowRef<Record<string, Component>>Componentes cargados dinámicamente asociados a las pestañas.
getComponentName(index: number) => stringRetorna el nombre del componente asociado a un índice de tab.
currentPageComputedRef<string>Nombre de la página actual basado en la ruta activa.
loadComponents() => Promise<void>Función que carga dinámicamente los componentes correspondientes a los tabs según la página actual.

Funcionamiento

  • Tab activo: Se controla con activeTab (índice).
  • TabRefs: Referencias directas a los elementos HTML de cada tab, para obtener dimensiones y posición.
  • TabIndicator: Computa el tamaño y la posición del indicador visual del tab activo.
  • Carga de componentes: Al montar el composable o cambiar de página, se buscan y cargan dinámicamente los componentes Vue asociados a los tabs específicos de esa página.
  • Ruta actual: Usa useRoute() para determinar en qué “página” se encuentra el usuario y filtrar la carga de componentes.

Uso básico

<script setup lang="ts">
import { tabCardList } from "@/mocks/tabsCard";
const { tabComponents, getComponentName } = useTabs(ref(tabCardList));
</script>
<template>
<UiTabsMainTabs :tabs="tabCardList" v-slot="{ activeTab }">
<component :tabContent="activeTab" :is="tabComponents[getComponentName(activeTab)]" />
</UiTabsMainTabs>
</template>

Notas

  • El sistema espera que los componentes estén en la ruta @/components/ui/tabs/{pageName}/, es decir, la carpeta anteriormente creada con el nombre de la página.
  • El nombre del componente debe coincidir con el component del objeto Tab.
  • La función loadComponents se ejecuta automáticamente en el onMounted y cuando cambia la ruta.