Elastic Design Studio

NavPill

Navegación flotante en forma de píldora, único elemento de navegación global

stable v4.0.1

Preview, desktop

Componente real en iframe (es position:fixed; montarlo suelto taparía esta página). Arriba a la izquierda, indicador deslizante en hover/focus, smart-hide al hacer scroll dentro del recuadro.

Preview, mobile

A <768px la píldora va abajo, centrada y con ancho intrínseco, y solo lleva los items. El logo sale de ella y queda fijo arriba a la izquierda, sin fondo. Baja hasta la banda negra: al subir un poco, el logo reaparece en blanco sobre ella y vuelve a negro al salir. Sigue bajando hasta el footer para ver cómo se oculta la píldora.

Props

PropTipoNota
logostringRequerida. Ruta al símbolo; <img> en caja fija 30×30 (evita reflow). El asset llega listo: debe ser legible sobre --nav-bg tal cual; el componente no lo re-colorea. En móvil es la variante del logo fijo sobre fondo oscuro.
logoOnLightstringOpcional (4.0). Variante del logo legible sobre fondo claro, solo para el logo fijo en móvil. Sin ella, logo se usa sobre cualquier fondo: válido para logos fotográficos, no para un logo solo blanco, que desaparecería en las páginas claras.
logoAltstringOpcional. alt del <img>, por defecto ''. Solo SEO de imagen y fallback: el aria-label del enlace ("Inicio") es el nombre accesible.
items{ key, href, label, icon?, isActive }[]Mín 2; máx: los que quepan a 375px con labels visibles. icon es SVG inline opcional.
locale'es' | 'en'Default 'es'. Labels de accesibilidad.
homeUrlstringDefault '/'. Destino del símbolo.

Tokens

PropiedadValorToken
Background#000000, ambos modos de color (excepción deliberada: máximo contraste, invariante al tema)--nav-bg
Texto#FFFFFF--nav-text
Border-radius16px, deriva de la escala: var(--radius-lg)--nav-radius
Altura52px--nav-height
Sombra0 8px 24px -4px rgba(0,0,0,0.15)--nav-shadow
TipografíaGeorama 14px / 600--text-nav
Item padding8px 12px (desktop) / 6px 8px (móvil)--nav-item-padding (desktop)
Gap entre itemsspace-sm (desktop) / space-xs (móvil)n/a
Item radius8px, deriva de la escala: var(--radius-md)--nav-item-radius
Fondo activo (indicador en reposo)rgba(255,255,255,0.12)--nav-active-bg
Fondo hover (indicador)rgba(255,255,255,0.2)--nav-hover-bg

Estados, indicador deslizante

Un único elemento (.nav-pill__indicator) hace de highlight: los items no tienen fondo propio. Sigue al item con hover o focus y descansa sobre el item activo (aria-current="page"). Sin item activo, se oculta. Todos los items siempre a opacidad completa.

EstadoTratamiento
InactivoTexto blanco, sin fondo. Opacidad completa.
Hover / focusEl indicador se desliza bajo el item apuntado.
Activo (reposo)El indicador descansa bajo el item con aria-current.
Sin item activoIndicador oculto (opacity 0).

El indicador se posiciona con getBoundingClientRect; salta sin transición en el primer paint y bajo prefers-reduced-motion, y se recalcula en document.fonts.ready y en resize. Al salir puntero y foco del nav, vuelve al item activo.

Logo fijo en móvil

A <768px el logo no está dentro de la píldora. Es un enlace a la home aparte, fijo arriba a la izquierda y sin fondo. El logo de 30×30 queda alineado con la columna de texto (--site-padding-x más el área segura del dispositivo); el enlace que lo rodea es un cuadrado transparente de 52px, que es el área táctil. Opacidad 0.7, completa en hover y en la home.

El logo fijo elige la variante del logo según lo que tiene debajo:

Debajo del logoVariante
Sección con data-nav-tone="dark" (VideoHero la trae de serie)logo (claro)
Sección con data-nav-tone="light"logoOnLight (oscuro)
Nada marcado, esquema clarologoOnLight
Nada marcado, esquema oscurologo

Manda el ancestro con data-nav-tone más cercano al elemento que está bajo el centro del logo (elementsFromPoint, recalculado en scroll y resize). Antes de que cargue el JS, el CSS aplica ya el esquema de color, así que no hay parpadeo. El anillo de foco acompaña: blanco sobre oscuro, negro sobre claro.

Un sitio que pinte fondos oscuros fuera de VideoHero los marca con data-nav-tone="dark". Con un esquema oscuro, una sección clara se marca con "light".

Posición

ViewportPosiciónComportamiento
Desktop (≥768px)Top, izquierdaSmart scroll: se oculta al bajar (>80px), aparece al subir. translateY, 0.3s ease-out.
Mobile (<768px)Bottom, centradoFijo, ancho intrínseco. Se desliza fuera mientras el <footer> está en pantalla (IntersectionObserver) para no tapar sus links; sin footer en la página, nunca se oculta.
Logo fijo (<768px)Top, izquierdaFija, sin fondo, tono según lo que tiene debajo. Smart scroll: se oculta al bajar (>80px), aparece al subir. Ignora el footer.

Restricciones

  • Mínimo 2 items; máximo, los que quepan a 375px con todos los labels visibles (en la práctica 3–4 cortos). El invariante es el fit, no el número.
  • Labels siempre visibles. Nunca solo iconos. Sin truncar, sin scroll, sin menú overflow.
  • Sin dropdowns.
  • Sin selector de idioma (el Footer lo maneja).
  • Sin theme toggle. Sin badges ni contadores.
  • El logo llega listo: el componente nunca lo re-colorea. Para el logo fijo en móvil, el sitio da las dos variantes.
  • En móvil el logo nunca va dentro de la píldora, y el logo fijo no tiene fondo propio.

Decisiones

DecisiónPor qué
Alineado a la izquierda en desktopCon 2-3 items, centrar deja espacio muerto
Se oculta al bajar (smart scroll)Sitio narrativo: nav fijo roba espacio de lectura
Centrado abajo en mobileAccesible al pulgar. Ancho auto evita estiramiento
Radio 16px, no pill completoMás suave, menos aspecto de app
Sin opacity dimmingItems a 0.5 de opacidad parecían rotos. Background fill es más limpio.
Hover bg > active bgTres estados claros sin tocar la opacidad del texto
Ocultarse en el footer (móvil)La píldora fija abajo tapaba los links del footer justo cuando el lector llegaba a ellos (promovido de elastic)
Máximo por fit, no por número"Máx 3" era la estimación inicial; elastic y teresa demostraron que 4 labels cortos caben. El invariante real es caber a 375px.
Sin re-colorear el logo (v3)El brightness/invert asumía iconos monocromos oscuros y destrozaba logos fotográficos (teresa necesitó un fork !important). El sitio provee el asset listo.
Logo fijo sin fondo en móvil (4.0)El logo ocupaba ancho de la píldora justo donde el ancho es la restricción, y un enlace a la home no necesita estar bajo el pulgar. Se probó con un cuadrado negro detrás y se descartó: se leía como un botón suelto, no como marca. Sin fondo hacen falta dos variantes y saber qué hay debajo. Las secciones declaran su tono en vez de que el componente lo adivine: mix-blend-mode: difference daba colores fuera de marca (cian sobre rojo) e invertía los logos fotográficos, y leer el background-color falla sobre imagen y vídeo.