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 activais(tabComponents[getComponentName(activeTab)]): Indica cual es el componente a cargar en base al que viene definido en el campocomponent: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.vueDentro 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 markdownconst { 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ámetro | Tipo | Descripción |
|---|---|---|
dataTabs | Ref<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
tabComponentscon los componentes cargados.
- Filtra los archivos Vue ubicados bajo
- Retorno:
Promise<void>
Retorno
Un objeto con las siguientes propiedades y funciones:
| Propiedad | Tipo | Descripción |
|---|---|---|
dataTabs | Ref<Tab[]> | Lista reactiva de tabs disponibles. |
activeTab | Ref<number> | Índice del tab actualmente activo. |
tabRefs | Ref<HTMLButtonElement[]> | Referencias a los botones de las pestañas. |
tabsWrapperRef | Ref<HTMLElement | null> | Referencia al contenedor de las pestañas. |
tabIndicatorStyles | ComputedRef<{ width: string; transform: string }> | Estilos CSS dinámicos para el indicador visual del tab activo. |
tabComponents | ShallowRef<Record<string, Component>> | Componentes cargados dinámicamente asociados a las pestañas. |
getComponentName | (index: number) => string | Retorna el nombre del componente asociado a un índice de tab. |
currentPage | ComputedRef<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
componentdel objetoTab. - La función
loadComponentsse ejecuta automáticamente en elonMountedy cuando cambia la ruta.