Saltar al contenido

Componentes

Navegación y secciones

Segmentos inset, navegación y calendarios con lanes y cards compartidas.

Prueba sin guardar cambios

Cargando ejemplo…

Header y hero de landings públicas

Las landings de producto usan ProductLandingHeader: máximo de 1148 px, igual al ancho máximo del marco exterior de la captura del hero de CRM, centrado, a 12 px del borde superior. Al hacer scroll conserva su expansión a todo el ancho. El hero empieza a 47 px del inicio de la página, detrás de la mitad inferior del header (68 px de contenido más 2 px de borde).

El contenedor de página usa 12 px de padding superior y el header reserva 35 px en el flujo. ProductLandingHeroFrame y ProductScrollHero no añaden padding superior; conservan el margen inferior de 12 px en móvil y 20 px desde sm. El contenido deja espacio para la navegación superpuesta. Estas opciones son los valores compartidos por defecto, también para futuras landings. Las variantes con carrusel conservan sus transiciones y navegación.

La demo «Header y hero de producto» muestra la relación de tamaños dentro de un contenedor responsive. Forms aún no tiene una landing comercial propia.

Shell compartido entre módulos

Los encabezados sin tarjeta usan PageHeader, sin margen superior negativo. Cuando abre el contenido, desde xl añade 16 px de padding superior para alinear el título con el interior de la tarjeta de identidad del lateral. Las páginas con tarjeta de cabecera conservan su posición. En Account, el enlace de retorno al módulo aparece encima del título, dentro del contenido y fuera del lateral; ese bloque recibe el mismo inset de 16 px. En móvil se conserva el padding normal del contenido. La demo «Encabezado sin tarjeta» compara ambas alturas.

El lateral ocupa 100dvh con tres zonas: identidad del workspace fija arriba, card central que ocupa todo el alto libre con scroll interno y usuario fijo al pie. Mantiene 312 px de ancho y 336 px desde 2xl; no tiene modo colapsado ni cabecera superior de módulo. Por debajo de xl, un botón flotante inferior izquierdo abre el mismo lateral en un drawer, con cierre accesible y respeto de las áreas seguras. El borde redondeado del card central permanece visible durante el scroll. CRM ya no incluye los bloques de Principales leads ni Equipo. La navegación del proyecto permanece siempre desplegada, sin control de colapso bajo su título. El cambio de proyecto se abre desde el botón de flechas en direcciones contrarias junto al nombre, al lado del engranaje de configuración visible en hover o foco; ambos miden 24 px y se alinean al borde derecho, centrados verticalmente con el título del proyecto sin incluir la etiqueta de categoría. El nombre admite varias líneas sin truncarse. No hay botón superior independiente.

En CRM, cada encabezado de sección («Mi CRM», «Operaciones», «Productos / Servicios», «Adquisición» y «Finanzas») permite plegar y desplegar sus opciones de forma independiente. ModuleTimelineNavigation activa este comportamiento con collapsibleSections; por defecto mantiene los encabezados estáticos para los demás consumidores. CRM utiliza autoExpandDelayMs={500}: las secciones empiezan colapsadas y se expanden juntas 500 ms después de que el documento alcance readyState=complete y autoExpandReady indique que la navegación, los proyectos y las vistas guardadas terminaron de cargar. La espera se cancela si vuelve la carga o se desmonta el menú. La apertura automática ocurre una sola vez por montaje; después cada sección se controla manualmente. El estado es local al menú y se reinicia al recargar o volver a montar el drawer móvil. Los botones funcionan con Enter y Espacio, exponen aria-expanded y aria-controls, y conservan el foco visible y una flecha de estado. El contenido oculto usa inert y aria-hidden para salir del recorrido de teclado sin desmontarse. Altura y opacidad se animan durante 300 ms con una transición suave en ambos sentidos; prefers-reduced-motion elimina la animación. Un ResizeObserver mantiene el marcador alineado durante la transición. La demo permite repetir la entrada automática y probar cada sección.

El pill del módulo abre el selector existente. En hover o foco mantiene su ancho y muestra un hexágono (PiHexagonBold), símbolo de los módulos, junto a «Cambiar de módulo» en texto de 9 px, sin cubrir el logo; un toque lo abre sin requerir hover. Las transiciones respetan movimiento reducido.

El footer agrupa notificaciones y tema, en ese orden, encima de la identidad, con botones de texto de 32 px sin relieve, separados entre sí por una línea vertical inset mediante CrmInsetSurface. Conserva el separador gris a su izquierda. El rol aparece como chip a la derecha de la identidad, centrado verticalmente con el botón de configuración. El correo no se trunca: puede ocupar varias líneas si es largo. El engranaje del perfil mide 24 px, se acerca al borde derecho y no tiene relieve. La preview utiliza todo el ancho libre de la fila, sin margen reservado a la izquierda, sin desplazar el tema ni el usuario. La identidad abre su menú compacto hacia arriba dentro del mismo footer, en un panel CrmInsetSurface del ancho disponible, con filas de 36 px, iconos antes del texto y opciones alineadas a la izquierda. Funciona igual en escritorio y en el drawer móvil. El engranaje sigue abriendo la edición del perfil. Mientras el menú está abierto, la fila de notificaciones/tema desaparece y el panel de notificaciones se cierra. Al cerrar el menú vuelve la fila de controles. La identidad permanece abajo; la navegación central cede el espacio necesario. La altura y opacidad del menú se animan durante 280 ms con movimiento reducido. Tiene scroll interno en pantallas bajas, foco inicial en la primera acción, Tab normal, cierre con Escape, otro clic en la identidad o clic fuera, y retorno de foco al trigger sin interferir con los modales abiertos por las acciones. Las opciones indican el foco con el fondo de control, sin aro ni offset blanco al abrir el menú o navegar con teclado. La campana muestra el estado activo azul mientras el panel está abierto y expande el footer hacia arriba en desktop y móvil: las notificaciones aparecen en un panel CrmInsetSurface integrado. La altura y opacidad se animan durante 280 ms tanto al abrir como al cerrar, respetando movimiento reducido. Cada notificación compacta el asunto, combina actor y detalle en hasta dos líneas y coloca tipo y fecha en una misma fila inferior. El panel tiene altura limitada al viewport, scroll propio sin reservar ancho para la barra y «Marcar todo como leído» fijo arriba. Los ítems ocupan todo el ancho interior, respetando el padding del panel. La navegación central cede espacio; los controles y la identidad siguen visibles. Otro clic en la campana, un clic fuera, Escape o navegar cierran el panel con la misma animación. No usa una capa flotante ni reinicia el proveedor ni añade suscripciones, polling o conexiones.

ModuleSidebarFrame comparte estructura y admite un footer explícito; ModuleSwitchTrigger es el control visual sin acceso a datos. SidebarProfile recibe identidad y callbacks. La demo los compone con datos ficticios y acciones locales: no consulta tenants ni notificaciones, y no cambia el perfil real.

Componentes visibles

La demo muestra pestañas CrmInsetTabSwitcher, un indicador CrmInsetStepper con acciones Anterior/Siguiente y el recorrido vertical HeroAreaNavigation. Cada muestra conserva su propio estado local.

Cuándo usar

Usa CrmInsetTabSwitcher para pocas vistas o categorías relacionadas. El consumidor controla la vista activa; la navegación de páginas debe mantener URL e historial cuando corresponda.

Propiedades y variantes

PropiedadContrato
tabsLista con value, label y disabled opcional.
value / onChangeValor activo y callback de selección.
ariaLabelNombre accesible del conjunto.
onOverflowChangeInforma cuando las opciones desbordan el contenedor.

Estados y accesibilidad

Mantén nombres legibles y prueba teclado, selección y desbordamiento en móvil. Distingue selección de contexto de navegación a otra página.

Evitar

No recrees grupos de píldoras con recetas locales ni ocultes secciones sin actualizar el contexto visible.

Submenú de landings de producto

ProductLandingHeader presenta la cabecera principal y reserva su espacio. ProductLandingSubmenu se coloca después del hero completo, incluido su carrusel al hacer scroll, y antes de las secciones. Ambos se importan desde @modules/marketing/product-landing-layout.

El submenú conserva su superficie oscura, navegación activa y menú móvil. Tiene 24 px de margen vertical (40 px desde sm) y se adhiere a 68 px del borde superior, debajo del header principal. Mantén hero, submenú y secciones como hermanos en el contenedor de la página; un wrapper corto limitaría el recorrido de sticky.

La barra mide 80 px en reposo y se compacta a 56 px, con una transición de 300 ms, cuando alcanza la cabecera. Al volver hacia el hero recupera su altura. El frame reserva 80 px para evitar saltos de contenido durante la animación; su zona transparente deja pasar los clics. El estado depende del anclaje real del submenú, no del scroll inicial de la página. Con movimiento reducido la transición es inmediata. Los enlaces de sección descuentan la altura compacta de destino.

ProductLandingHeroFrame ocupa como mínimo el alto disponible de la primera pantalla: descuenta únicamente 16 px del contenedor, 80 px de la cabecera y 24 px de padding vertical (40 px desde sm). Conserva un mínimo de 600 px y permite que el contenido crezca en móvil. El submenú y su margen empiezan después de ese bloque; no se descuentan del hero ni asoman parcialmente al cargar.

TSTypeScriptSolo lectura
<div>
  <ProductLandingHeader
    productLabel="Finance"
    docsHref="/docs"
    docsVersion="v1.0"
  />
  <ProductLandingHeroFrame>
    <div className="relative lg:h-full">Contenido del hero</div>
  </ProductLandingHeroFrame>
  <ProductLandingSubmenu
    productLabel="Finance"
    navItems={financeNavItems}
    docsHref="/docs"
  />
  <MarketingFeatureGrid {...featureProps} />
</div>

En MarketingShell, pasa el hero por la prop hero; el shell coloca automáticamente el submenú entre ese hero y children cuando recibe navItems y moduleLabel. Este patrón se comparte entre CRM, Platform, Finance, HR y Events.

Carrusel fijado con transiciones completas

CrmScrollHero activa screenshotTransition="scroll" en ProductScrollHero. Se conserva el recorrido sticky original: 240 svh en móvil, 270 svh desde sm y 300 svh en escritorio para mantener el carrusel fijo durante los tres slides. La posición dentro del recorrido selecciona un índice entero. Cada cambio de índice anima la captura hasta su destino durante 500 ms; los píxeles recorridos con el scroll no mueven parcialmente la imagen. Tras 180 ms sin desplazamiento ni gesto activo, se alinea con el siguiente screenshot al bajar o el anterior al subir. La alineación se completa con una animación de 280 ms controlada por frames y puede interrumpirse con un nuevo gesto; no dispara un segundo avance al terminar. Se conserva la dirección ante eventos tardíos del trackpad, aunque no generen desplazamiento adicional. El scroll real activa el ajuste sin exigir un evento wheel previo; una posición intermedia restaurada se alinea al centro más cercano.

El índice seleccionado anima el MotionValue de CrmHeroCarousel.scrollPosition, sin vincular la posición de la imagen a cada píxel del scroll. Los extremos del recorrido dejan reposar la primera y última imagen, y los botones de área llevan al centro de cada screenshot. El contador, área seleccionada y textos laterales siguen la imagen predominante. El ajuste solo actúa dentro del tramo fijado y entre centros de screenshots: los extremos quedan libres para entrar y salir del carrusel. Respeta rueda, trackpad, teclado y gestos táctiles; los clics de navegación conservan su destino. Con movimiento reducido la alineación y los cambios de imagen son inmediatos. La variante por defecto sigue siendo fade; Finance y HR conservan su presentación actual.

TSTypeScriptSolo lectura
<ProductScrollHero
  slides={crmHeroSlides}
  areas={crmHeroAreas}
  editorials={editorialSlides}
  productLabel="CRM"
  screenshotTransition="scroll"
>
  <div>Introducción del producto</div>
</ProductScrollHero>

Timeline vertical del carrusel CRM

CrmHeroCarousel usa areaLayout="vertical" en el recorrido de CRM. Reutiliza HeroAreaNavigation para mostrar las vistas de reportes y pipeline en una columna a la izquierda del screenshot, unidos de arriba hacia abajo y con una flecha que refuerza el sentido del recorrido. El paso activo sigue la diapositiva seleccionada; cada botón conserva su navegación directa y declara aria-current="step" cuando aplica.

En móvil, la columna ocupa 48 px y muestra iconos con nombres accesibles. Desde sm ocupa 144 px y muestra cada icono centrado con su etiqueta centrada debajo. La línea y la flecha comparten ese eje central; las etiquetas cubren la línea para mantener la legibilidad. El screenshot conserva el marco compartido y se adapta al espacio disponible, sin superponerse al timeline. Ambos paneles comparten una fila de grid con estiramiento vertical: sus bordes superior e inferior coinciden. El timeline distribuye los pasos en filas de igual altura y la línea conecta sus centros, adaptándose al alto del screenshot. Las variantes centered y split mantienen la navegación horizontal existente. La demo interactiva de esta página permite seleccionar los tres pasos verticales.

Al cargar CRM, la captura aparece centrada, con el título, contador y timeline ocultos. Pasados 36 px de scroll, se desplaza a la derecha durante 700 ms; el título y timeline aparecen durante 500 ms con 300 ms de retraso. Volver al inicio revierte la transición. El marco mantiene su tamaño y el hero conserva sus márgenes exteriores, con 144 px de superposición del carrusel. CrmHeroCarousel.areaNavigationVisible controla esta presentación y se propaga a HeroAreaNavigation.visible: mientras está oculto, el timeline es inert y queda fuera del árbol accesible. Movimiento reducido elimina las transiciones y su retraso. La demo permite alternar la visibilidad para comprobar esos estados.

TSTypeScriptSolo lectura
<HeroAreaNavigation
  areas={crmHeroAreas}
  activeIndex={activeIndex}
  onSelect={selectSlide}
  label="Áreas de CRM"
  layout="vertical"
/>

El recorrido CRM aprovecha la altura liberada por el timeline horizontal: el bloque sticky comienza a 88 px (cabecera más separación) y calcula el tamaño del screenshot con el alto de pantalla disponible, reservando solo título, contador, marco y pista de scroll. En escritorio, los textos laterales y el carrusel usan columnas de grid independientes para ampliar la imagen sin solapar contenido. La imagen conserva su proporción; timeline y marco mantienen el mismo alto. El bloque de captura, título, timeline y pista de scroll usa el mismo centrado vertical desde el inicio, sobre el mismo eje que los textos laterales. No cambia de alineación al alcanzar o abandonar el tramo sticky. useScrollHeroLayout mide el espacio superior de ese centrado y lo descuenta del margen del track, conservando los 144 px de superposición inicial. Se actualiza al cambiar el tamaño del contenido o de la pantalla, sin medir en cada evento de scroll. En móvil, los textos compactos reservan su espacio mientras están ocultos e inertes para que su aparición tampoco cambie la posición de la captura.

Acciones del dashboard de proyecto

La grilla compartida adapta su distribución al ancho del contenedor. En consulta, entre 768 y 1279 px, agrupa los widgets en filas de izquierda a derecha siguiendo su orden visual guardado, sin conservar huecos ni desplazamientos laterales. Cada fila toma la altura de su tarjeta más alta. Bajo 768 px se apilan en una columna; desde 1280 px se conserva la composición de escritorio. La adaptación no guarda cambios. El modo de edición conserva las coordenadas personalizadas. La demo de navegación incluye tres tarjetas para comprobar esta transición.

La tarjeta de bienvenida precede a los breadcrumbs, sin repetir el nombre del proyecto como título. La fila conserva 16 px de separación arriba y abajo; la rejilla de widgets no agrega padding vertical al margen inferior. Los breadcrumbs y las acciones comparten fila: breadcrumbs a la izquierda y controles del panel a la derecha. «Nuevo Lead» aparece dentro del widget «Leads por etapa», antes del filtro de fechas. Es un enlace directo a la creación de leads del proyecto, sin dropdown. WidgetPanel.leadingAction permite colocar esta acción antes del control de rango compartido. El bloque «Panel de Reporte Comercial», su autor debajo y los tres puntos se alinea al extremo derecho. El título conserva acceso a las vistas guardadas sin mostrar una flecha; los tres puntos adyacentes abren las opciones del panel.

El menú presenta una sola fila «+ Widget | S/ | ✎ Panel», con separadores verticales grises visibles. Debajo, una línea horizontal separa los paneles guardados, cada uno con su autor. La sección «Plantillas predeterminadas» siempre ofrece Panel Operaciones, Panel Comercial y Panel Gerencia, incluso sin paneles personalizados. Primero aparece el «Panel predeterminado» del proyecto con el propietario del espacio; le siguen los paneles guardados o «Aún no hay paneles guardados» y finalmente las plantillas predeterminadas, sin candados. Ambos menús comparten el mismo contenido; avatares e iconos ocupan una columna de 20 px alineada con la primera línea del título. Seleccionar una plantilla abre su contenido; «Panel» permite personalizarla y guardar una copia con nombre mediante el modal global. La plantilla original permanece disponible. La lista permite seleccionar una vista o volver al panel predeterminado. El símbolo refleja la moneda activa y abre un dropdown PEN/USD. «Panel» activa la edición existente y conserva guardar, descartar y ordenar. DashboardViewHeader.actions admite acciones propias sin modificar los controles de guardado ni el comportamiento predeterminado de otros módulos. La demo utiliza el menú real con estado local y datos de ejemplo.

En escritorio (xl), la tarjeta superior del lateral y la bienvenida del proyecto comparten una altura de 138 px. ModuleDashboardSummaryHeader.alignWithSidebar compacta padding, saludo y fecha; conserva el mensaje inferior. Las métricas usan cuatro columnas amplias desde 64rem de ancho disponible en la tarjeta y solo pasan a dos por dos compactas cuando falta espacio. El resumen CRM no muestra el texto de último registro. Por debajo de xl recupera altura natural para acomodar el contenido y el drawer.

TSTypeScriptSolo lectura
<ModuleDashboardSummaryHeader
  greetingSource="project"
  alignWithSidebar
  metrics={metrics}
  footer={activityMessage}
/>

Las tarjetas del lateral y la bienvenida usan CrmRaisedSurface con elevation="raised", radio de 24 px y la sombra compartida --vee-shadow-raised.

Los separadores del menú de opciones del panel usan la superficie inset compartida, con trazo de 2 px, extremos redondeados y opacidad reducida: 60% en claro y 35% en oscuro.

La entrada del dashboard del proyecto en Operaciones se llama «Panel de Reportes»; conserva su ruta, permisos y submenú de vistas guardadas.

Las previews de notificación del lateral usan esquinas suaves de 12 px al expandirse, con una silueta rectangular; el icono cerrado conserva su forma circular. Los iconos de notificaciones y tema se muestran al 75% en reposo y recuperan su tamaño completo mientras la preview se expande horizontalmente. La transición de 280 ms respeta movimiento reducido. Los botones ocupan 24 × 24 px en reposo, sin padding adicional; el botón de tema recupera 32 × 32 px durante la preview. La fila mide 24 px de alto y deja 2 px antes del separador en reposo; durante la preview recupera los 40 px de alto y 8 px de separación anteriores, con la misma transición. El footer ocupa así 22 px menos mientras no hay preview. El contador de no leídas que alterna con la campana usa 10 px en el lateral, proporcionado al icono compacto; la demo muestra tres pendientes en reposo. Un separador horizontal inset separa estos controles de los datos del usuario. Ambos separadores del footer usan un trazo de 1 px, con opacidad de 100% en claro y 70% en oscuro para mantener un relieve fino y visible. El horizontal se oculta junto con los controles al abrir el menú de usuario. La demo permite simular la preview.

La fila de breadcrumbs y panel replica el margen horizontal de la rejilla de widgets según su ancho disponible: 0 px bajo 768 px, 12 px desde 768 px y 16 px desde 1280 px, para alinear sus bordes con las tarjetas inferiores.

Carga del panel comercial

CrmProjectDashboardSkeleton reproduce la composición vigente: bienvenida primero (138 px en escritorio), métricas amplias o compactas según el ancho disponible, breadcrumbs a la izquierda y título/autor del panel a la derecha en la misma fila. Mantiene 16 px entre bloques y el espaciado horizontal del grid. El primer widget reserva sus controles, métricas y columnas de etapas. No muestra el título de proyecto ni las acciones retiradas. Usa los tonos compartidos, no consulta datos y desactiva el pulso con movimiento reducido. La demo permite mostrarlo y ocultarlo.

Filtros temporales y edición

Cambiar el periodo, el filtro de leads o el ajuste de ancho de etapas no activa la edición del dashboard. En consulta son cambios locales de la vista actual, que se descartan al recargar o cambiar de panel. En edición forman parte del borrador y se conservan al guardar el panel mediante el flujo existente. El ajuste de ancho usa funnelFitContainer, compatible con los paneles guardados.

Porcentajes en las métricas del resumen

ModuleDashboardSummaryHeader admite valueSuffix junto al valor principal y valueDescription para explicar la relación (por ejemplo, «57 ganados de 1113 leads»). El sufijo conserva su visibilidad en el layout compacto y queda centrado verticalmente con el número. valueSuffixTone admite positive (verde) y negative (rojo), con variantes para modo oscuro; CRM los usa para ganados y perdidos respectivamente. La demo muestra los porcentajes de ganados y perdidos sobre el total, con un decimal como máximo. En CRM, «Interesados» comprende las etapas abiertas excepto la primera; no depende del nivel de interés HOT.

Acciones del selector de espacio de trabajo

TenantSwitcherCard usa glass grafito translúcido con matiz azul grisáceo, texto e iconos blancos y reflejo tenue para destacar el espacio activo, con texto y transparencia adaptados al tema. Mantiene el nombre a la izquierda y muestra plan y usuarios en reposo. Al hover o foco, esa información cede su sitio a dos acciones de texto: icono de edificio + «Configurar» y flechas arriba/abajo + «Cambiar». Los mismos iconos permanecen montados y visibles: se desplazan hacia la izquierda al expandir sus etiquetas mientras el plan y los usuarios se desvanecen. Ambas conservan el gris --vee-text-muted del selector, sin borde visible ni sombra. Cada opción muestra un fondo gris claro --vee-workspace al hover; el foco de teclado se indica con un contorno. No hay botones anidados ni variación de altura; las transiciones respetan movimiento reducido. En dispositivos sin hover o de puntero táctil, las acciones permanecen visibles. El nombre también abre el selector.

«Configurar» se muestra al propietario o superadministrador, fuera de impersonación, y navega a la configuración del tenant activo en Account usando el origen del entorno y el contexto de retorno al módulo. La página conserva su autorización de servidor. «Cambiar» abre el modal existente. Durante el cambio de módulo ambas acciones están deshabilitadas. El componente recibe datos y callbacks; la demo del shell reproduce el comportamiento sin navegar ni consultar sesión. La variante compacta identity-card conserva su comportamiento anterior.

Radios del shell y las pestañas

Las cards del lateral, footer y bienvenida comparten --vee-radius-card (24 px). El selector de tenant y los encabezados plegables usan --vee-radius-control (14 px). El selector de módulo usa también el radio de control: ModuleSwitchTrigger aplica --vee-radius-control al rectángulo de fondo del SVG, al botón y al estado «Cambiar de módulo». Así presenta esquinas suaves de selector en lugar de extremos semicirculares. El SVG identifica únicamente su fondo mediante data-module-pill-surface, sin modificar los iconos ni el texto. La demo del lateral permite compararlo con el selector de tenant y activar hover/foco. Las pestañas usan el radio de control; el contenedor suma sus 6 px de padding para conservar la relación entre las curvas interiores y exteriores.

Lateral de solo iconos

El control pequeño de menú y flecha está junto al borde derecho del lateral, a la altura del encabezado. En escritorio alterna el ancho completo y un rail de 104 px: módulo, empresa, navegación y usuario se reducen juntos y el contenido principal ocupa el espacio liberado. Los iconos conservan etiquetas accesibles. Al abrir el menú de usuario o las notificaciones, el lateral se expande para mostrar su panel completo. El drawer móvil conserva sus etiquetas.

La demo del shell usa el mismo control; las variantes compactas de ModuleSwitchTrigger y TenantSwitcherCard mantienen sus callbacks. El estado pertenece al shell y se conserva al navegar dentro de él.

Altura compacta del onboarding

CubeStepTransition compact reduce la altura de la pantalla de apariencia a un rango de 26–32 rem. El resto de pasos conserva su altura habitual, foco después de la transición, contenido saliente inerte y movimiento reducido. El progreso muestra siempre el número real de pasos del flujo.

Pills de módulo glass

Los pills de módulo usan el mismo fondo, reflejo tenue, borde y elevación de los campos, mediante los tokens glass globales. El SVG conserva iconos, separador y color de texto; su superficie inset se oculta únicamente en la interfaz viva. ModuleSwitchTrigger mantiene glass también en hover y en la variante compacta, con el radio de control del shell. Los pills fuera del selector conservan su forma semicircular y la exportación SVG para correo mantiene su arte estático.

En la cabecera, module-switch-surface integra el pill con fondo glass tenue, sin sombra, borde mínimo, texto gris grafito y separador atenuado. Conserva el color del icono y aplica el mismo material en hover y en tema oscuro.

CrmInsetTabSwitcher usa activeChipTone="primary" por defecto y los tokens de grafito del botón primary para el segmento activo, con texto blanco en ambos temas. Incluye Kanban/Tabla y Todos/Personas/Empresas/Oportunidades. activeChipTone="default" permite un acento personalizado explícito. La página activa del menú utiliza CRM_PRIMARY_ACTIVE_SURFACE_CLASS_NAME en todos los módulos (CRM, Finance, CMS, HR, Forms y menús compartidos), incluidos submenús y navegación colapsada. Texto e iconos seleccionados son blancos y comparten el mismo grafito.

SidebarCollapseButton aparece a la derecha del toggle de tema en el footer. Permite colapsar y expandir el lateral, sin tooltip ni efecto visual de hover; conserva cursor y nombre accesible. En modo compacto, tema y expansión comparten fila. El drawer móvil no ofrece colapso. ModuleSwitchTrigger queda dedicado al cambio de módulo, manteniendo el ancho original del pill.

Widgets alineados con tablas y secciones

ResponsiveDashboardGrid y su motor CrmResponsiveDashboardGrid admiten flushEdges (opcional, false por defecto). Actívalo cuando los widgets deben alinearse con una tabla o card que ya ocupa todo el ancho del contenedor: elimina los 16 px exteriores en desktop y 12 px en tablet, conservando las separaciones entre widgets y el apilado móvil. El resumen de socios HR y la demo de distribución adaptable lo utilizan; las demás vistas conservan su margen actual.

Calendario con lanes y cards

PlatformCalendarLanes y PlatformCalendarDayLane comparten la vista de agenda creada en HR y reutilizada por CRM. Cada semana conserva siete columnas con un ancho mínimo conjunto de 1400 px y desplazamiento horizontal accesible. El calendario mensual distribuye las fechas en filas de siete días y usa compact para reducir la altura mínima, sin ocultar actividades.

Las lanes usan CrmInsetSurface; PlatformCalendarCard usa la superficie elevada global, título y subtítulo, selección, contenido y footer. Las acciones están fuera del botón principal para evitar botones anidados. interactionProps permite conectar los bindings de arrastre desde el módulo sin acoplar el componente compartido a una biblioteca DnD.

PlatformCalendarTimeRange muestra inicio, duración y fin. PlatformCalendarPeople reutiliza UserAvatar con hasta cuatro personas y un contador de excedentes. HR mantiene su zona horaria del tenant; CRM conserva la zona del navegador. El consumidor entrega fechas civiles YYYY-MM-DD, agrupa eventos y administra permisos, creación, selección y reprogramación. No se infieren permisos desde la apariencia ni se hacen peticiones en las primitivas visuales.

La demo Calendario compartido permite seleccionar una tarjeta, alternar la altura semanal/mensual y comprobar el desplazamiento horizontal.

Work

Work reutiliza ModuleSidebarFrame, ModuleTenantSelectorCard, ModuleMainMenuCard y ModuleTimelineNavigation, el mismo componente de navegación de CRM. Su única aplicación inicial es Correo. El pill Work añade un sobre al catálogo global, conservando los tokens glass y estados activos. La demo del shell permite alternar CRM/Work sin consultar permisos ni cuentas.

CrmHorizontalScrollNavigator reutiliza segmentos, arrastre y teclado para contenidos anchos. Recibe scrollContainerRef, segments y ariaLabel. La presentación predeterminada placement="floating" se conserva en Tabla y Kanban. Usa placement="inline" dentro del footer fijo de un modal para mantenerlo accesible mientras el cuerpo se desplaza verticalmente. Activa enabled cuando el modal esté abierto. El control aparece sólo si hay desbordamiento y sincroniza su indicador con el scroll del contenido y sus cambios de tamaño. Admite flechas, PageUp/PageDown y Home/End. La demo Navegación incluye siete etapas con la variante en flujo.