Tabs, Pills y Accordion para Angular | ng-hub-ui-panels

Componente de paneles de contenido para Angular que se renderiza como tabs, pills o accordion, con routing, formularios reactivos, navegación por teclado y variables CSS.

Referencia API

Aquí tienes el contrato completo de panels: todo lo que puedes enlazar, escuchar, proyectar y personalizar, reunido en un solo sitio. Enlaza lo que necesites y dale el estilo que quieras — es standalone y reactivo con signals.

Inputs

Ajusta panels a tu gusto con 40 inputs. Se enlazan como cualquier @Input de Angular.

NombreTipoPor defectoDescripción
type'tabs' | 'pills' | 'accordion' | 'card''tabs'Visualización del contenedor: tabs subrayadas, pills redondeadas, paneles de accordion apilados o cards siempre visibles y sin marco.
verticalbooleanfalseApila la tira de cabeceras verticalmente junto al contenido (vistas tabs / pills).
justifiedbooleanfalseEstira las cabeceras para repartir equitativamente el ancho disponible.
scrollablebooleanfalseAñade botones de desplazamiento hacia atrás/adelante cuando la tira de cabeceras desborda.
isKeysAllowedbooleantrueHabilita la navegación con teclado (flechas / Home / End / Delete).
multiplebooleanfalsePermite que varios paneles estén activos a la vez. En la vista de accordion todos se expanden; en las vistas de tabs/pills cada cabecera activa inicia un bloque de panel visible y las cabeceras inactivas siguientes permanecen agrupadas encima de ese bloque hasta que la siguiente cabecera activa inicia uno nuevo. El valor del formulario pasa a ser un array.
flushbooleanfalseVista de accordion: paneles de borde a borde sin bordes exteriores ni radio.
togglePosition'start' | 'end''end'En <hub-panels> (vista accordion): en qué lado de la fila de cabecera se sitúa el chevron de despliegue. "end" (por defecto) lo deja detrás del encabezado; "start" lo pone delante. Solo cambia el orden visual — el DOM no se toca — y los desplazamientos son lógicos, así que "start" es el borde izquierdo en LTR y el derecho en RTL. Fija el valor por defecto de toda la app con HubPanelsConfig.togglePosition.
variantHubPanelVariant | stringundefinedhub-panels: acento semántico de la tira de navegación — lo siguen el tab activo y su hover, la pill activa y la cabecera de accordion activa. Los valores integrados ('primary' | 'success' | 'danger' | 'warning' | 'info') usan los tintes del design system, pero se acepta cualquier string: la tira lee --hub-sys-color-<variant> de tu aplicación. Por defecto, primary.
bindValuestringundefinedRuta en notación de puntos aplicada al valor de cada panel para obtener el valor de formulario emitido (p. ej. 'meta.key').
compareWith(a: unknown, b: unknown) => boolean(a, b) => a === bIgualdad utilizada para comparar los valores de formulario con los valores de los paneles.
headingstringundefinedhub-panel: cabecera de texto plano. Se ignora cuando se proporciona una plantilla hubPanelHeading.
appearance'card' | 'alert''card'hub-panel: apariencia visual de un panel independiente — 'card' (por defecto) o un aviso semántico 'alert'. Se ignora en las vistas de tabs/pills/accordion.
variantHubPanelVariant | stringundefinedhub-panel: acento semántico del panel — colorea un alert y tiñe una card entera (reflejado como data-variant). Los valores integrados ('primary' | 'success' | 'danger' | 'warning' | 'info') usan los tintes del design system, pero se acepta cualquier string: el panel lee --hub-sys-color-<variant> de tu aplicación. Omítelo para un panel neutro.
fillbooleanfalseSolo panel card: llena la altura del padre y deja que el cuerpo haga scroll, de modo que una región interna flex:1/min-height:0 (p. ej. una tira de pestañas + panel con scroll) quede acotada. El padre debe ser una columna flex.
standaloneboolean (static attribute)falseSolo panel card, atributo estático: excluye un <hub-panel> suelto de un grupo tabs/pills/accordion ancestro en la misma plantilla, de modo que se renderice como una card normal en lugar de ser capturado como una pestaña oculta.
idstring'hub-panel-<n>'hub-panel: id usado para el emparejamiento ARIA entre un tab y su panel (o entre una cabecera de accordion y su región). Se genera automáticamente como hub-panel-<n>; asígnalo cuando necesites ids estables, para un enlace profundo o un aria-controls propio.
valueunknownidhub-panel: valor aportado cuando el contenedor se usa como control de formulario.
activeboolean (model)falsehub-panel: estado active/expanded con binding bidireccional.
disabledbooleanfalsehub-panel: impide que el panel pueda activarse.
removablebooleanfalsehub-panel: muestra un control ✕ y habilita la eliminación con la tecla Delete.
removeLabelstring'Remove panel'hub-panel: nombre accesible (aria-label) que se anuncia para el botón ✕ de eliminación; sobrescríbelo para localizar el control.
routerLinkstring | string[]undefinedhub-panel: convierte el panel en un panel enrutado respaldado por un <router-outlet>.
queryParamsParamsundefinedhub-panel: parámetros de consulta añadidos al navegar a routerLink.
pathMatch'route' | 'full''route'hub-panel: comparación de URL utilizada para marcar como activo un panel enrutado.
customClassstringundefinedhub-panel: clases CSS adicionales aplicadas tanto al elemento del nav como al panel.
itemsHubTabNavItem[][]Las pestañas seleccionables de un <hub-tab-nav>, en orden de renderizado. Cada elemento es un descriptor ligero { value, label, disabled?, id? } — la tira no posee contenido, así que value es lo que emite cuando se elige la pestaña.
activeunknown (model)undefinedValor seleccionado con enlace bidireccional de un <hub-tab-nav>. Establécelo para preseleccionar una pestaña y léelo de vuelta a través de activeChange; el elemento coincidente es aquel cuyo value es igual a este.
appearance'tabs' | 'pills''tabs'Aspecto visual de la tira <hub-tab-nav>: 'tabs' clásicas con subrayado (por defecto) o 'pills' redondeadas.
justifiedbooleanfalseCuando es true, las pestañas del <hub-tab-nav> se estiran para repartir el ancho disponible por igual.
verticalbooleanfalseCuando es true, la tira <hub-tab-nav> apila sus pestañas en vertical en lugar de disponerlas en una fila.
modeHubSidePanelMode'side'<hub-side-panel>: 'side' acopla el panel y estrecha el contenido para hacerle sitio; 'over' lo hace flotar sobre el borde del contenido sin backdrop, bloqueo de scroll ni trampa de foco.
positionHubSidePanelPosition'end'<hub-side-panel>: borde lógico del contenedor en el que se sitúa el panel — 'end' es el borde derecho en LTR y el izquierdo con dir="rtl".
openboolean (model)false<hub-side-panel>: estado de apertura bidireccional. Cerrar oculta el panel sin destruir su contenido proyectado, así que un chat o un formulario dentro conserva su estado.
closeOnEscapebooleantrue<hub-side-panel>: si pulsar Escape dentro del panel lo cierra. El Escape pulsado en la página nunca se captura, y un control que ya consumió la tecla mantiene el panel abierto.
breakpointnumber768<hub-side-panel>: ancho del contenedor en px por debajo del cual un panel side se renderiza como over, porque un panel acoplado en una pantalla estrecha aplastaría el contenido. 0 lo mantiene acoplado a cualquier ancho.
autoFocusbooleanfalse<hub-side-panel>: si al abrir se mueve el foco dentro del panel — al primer elemento [autofocus], si no al primero tabulable, si no al propio panel. Desactivado por defecto.
roleHubSidePanelRole'complementary'<hub-side-panel>: rol de landmark — 'complementary' junto al contenido principal de la página, 'region' cuando el panel está dentro de él.
ariaLabelstringundefined<hub-side-panel>: nombre accesible del landmark. Indica este o ariaLabelledBy.
ariaLabelledBystringundefined<hub-side-panel>: id del elemento que da nombre al landmark, normalmente el título de la cabecera.

Outputs

Reacciona a lo que hace panels: 7 eventos a los que enganchar tu lógica.

NombreTipoDescripción
panelChangeOutputEmitterRef<PanelChangeEvent>hub-panels: se emite cuando el usuario activa (abre) un panel diferente. Proporciona { current, prev }.
selectPanelOutputEmitterRef<HubPanelComponent>hub-panel: se emite cuando el panel pasa a estar activo.
deselectPanelOutputEmitterRef<HubPanelComponent>hub-panel: se emite cuando el panel deja de estar activo.
removedOutputEmitterRef<HubPanelComponent>hub-panel: se emite cuando el panel se elimina mediante el botón ✕ o la tecla Delete.
activeChangeOutputEmitterRef<boolean>hub-panel: mitad de cambio del model bidireccional active, emitida con el nuevo estado activo/expandido del panel.
activeChangeOutputEmitterRef<unknown>Emitido por <hub-tab-nav> cada vez que cambia el valor seleccionado (la mitad de cambio del modelo bidireccional active), transportando el value del elemento recién seleccionado.
openChangeOutputEmitterRef<boolean><hub-side-panel>: mitad de cambio del modelo bidireccional open; se emite con el nuevo estado lo cambie quien lo cambie (binding, Escape, toggle() o close()).

Métodos

Controla panels desde el código — 6 métodos en su superficie programática.

NombreFirmaDevuelveDescripción
HubPanelsComponent.selectPanelselectPanel(panel: HubPanelComponent): void—Activa un panel como lo haría un clic: lo marca activo, navega si el panel está enrutado y emite panelChange. Con paneles deshabilitados no hace nada.
HubPanelsComponent.togglePaneltogglePanel(panel: HubPanelComponent): void—Alterna un panel en la vista accordion, respetando multiple: sin multiple, abrir uno colapsa el resto.
HubPanelsComponent.removePanelremovePanel(panel: HubPanelComponent, options?: { reselect?: boolean; emit?: boolean }): void—Elimina un panel del grupo. reselect decide si otro panel ocupa su lugar; emit, si la eliminación se notifica por panelChange.
HubPanelsComponent.removePanelAndRefocusremovePanelAndRefocus(panel: HubPanelComponent): void—Elimina un panel y pasa el foco de teclado a la cabecera más cercana que quede, de modo que un borrado nunca deja el foco en el body. Es lo que llaman el botón ✕ y la tecla Delete.
HubSidePanelComponent.toggletoggle(force?: boolean): void—Abre o cierra el panel; pasa true o false para forzar un estado en lugar de alternarlo.
HubSidePanelComponent.closeclose(): void—Cierra el panel. Si el foco estaba dentro, vuelve al elemento que lo tenía cuando se abrió el panel.

Templates

Hazlo tuyo — 3 plantillas para proyectar tu propio marcado.

NombreDescripciónEjemplo
hubPanelHeadingMarca un <ng-template> dentro de un hub-panel como la cabecera personalizada de ese panel (enlace de la tira en tabs/pills, botón de despliegue en accordion), reemplazando el input de cabecera de texto plano.<hub-panel> <ng-template hubPanelHeading> <i class="fa-solid fa-gear"></i> Settings <hub-badge color="primary" shape="rounded">3</hub-badge> </ng-template> Panel content </hub-panel>
hubPanelHeader / hubPanelFooterMarca un elemento dentro de un hub-panel como banda de cabecera/pie de contenido del panel. Se renderiza en todas las vistas (tabs, pills, accordion, card), distinto de hubPanelHeading.<hub-panel> <div hubPanelHeader>Card title</div> Card content <div hubPanelFooter>Actions</div> </hub-panel>
type="card"La visualización en tarjeta sin cromo: sin tira de navegación, todos los paneles siempre visibles. Un hub-panel también puede usarse de forma independiente, fuera de cualquier hub-panels, donde se renderiza como tarjeta.<hub-panels type="card"> <hub-panel>…</hub-panel> <hub-panel>…</hub-panel> </hub-panels>