1. Home
  2. ChevronRightLayout
  3. ChevronRightNavbar

Navbar

Barra de navegación superior que contiene la marca del sitio, elementos de pestañas y acciones de búsqueda.

El componente Navbar muestra logos del sitio, enlaces de navegación, pestañas de documentación y disparadores de búsqueda.


ImportaciónLink

import { Navbar } from 'boltdocs/primitives'

Ejemplo de Navbar ComponibleLink

Usando la primitiva Navbar y sus subcomponentes, puedes diseñar una barra de navegación completamente personalizada. El siguiente ejemplo muestra cómo construir un encabezado con coincidencia de pestaña activa, disparadores de búsqueda, integraciones sociales y alternancia de temas:

// docs/components/CustomNavbar.tsx
import React, { useState } from 'react'
import { Navbar } from 'boltdocs/primitives'
import { useNavbar, useTheme, useSearch } from 'boltdocs/client'

export default function CustomNavbar() {
  const { links, theme, logo, title } = useNavbar()
  const { toggleTheme } = useTheme()
  const { openSearch } = useSearch()
  const [mobileOpen, setMobileOpen] = useState(false)

  return (
    <Navbar className="bg-white/80 dark:bg-black/80 backdrop-blur-md border-b border-subtle">
      <Navbar.Content>
        {/* Sección Izquierda: Marca */}
        <Navbar.Left>
          {logo && <Navbar.Logo src={logo} alt={title} href="/" />}
          <Navbar.Title className="font-bold text-lg">{title}</Navbar.Title>
        </Navbar.Left>

        {/* Sección Central: Enlaces de Navegación Principales */}
        <Navbar.Center>
          {links.map((link) => (
            <Navbar.Link
              key={link.href}
              href={link.href}
              label={link.label}
              className={link.active ? 'text-primary font-medium' : 'text-muted'}
            />
          ))}
        </Navbar.Center>

        {/* Sección Derecha: Acciones */}
        <Navbar.Right>
          {/* Disparador de Diálogo de Búsqueda Personalizado */}
          <Navbar.SearchTrigger onPress={openSearch} />

          {/* Botón de Alternancia de Tema */}
          <Navbar.Theme
            theme={theme}
            onThemeChange={(isDark) => toggleTheme()}
          />

          {/* Botón Social de Github */}
          <Navbar.Socials icon="github" link="https://github.com/myorg/myrepo" />

          {/* Disparador de Cajón Móvil (Icono Más Vertical) */}
          <Navbar.More onPress={() => setMobileOpen(true)} className="lg:hidden" />
        </Navbar.Right>
      </Navbar.Content>

      {/* Menú Cajón Móvil Responsivo */}
      <Navbar.MobileMenu isOpen={mobileOpen} onClose={() => setMobileOpen(false)}>
        {links.map((link) => (
          <Navbar.MobileLink
            key={link.href}
            href={link.href}
            label={link.label}
            onPress={() => setMobileOpen(false)}
            className="text-lg py-2"
          />
        ))}
      </Navbar.MobileMenu>
    </Navbar>

Referencia de Producción del Mundo RealLink

A continuación se muestra una implementación de referencia completa y lista para producción que demuestra cómo construir una barra de navegación con todas las funcionalidades (similar al navbar del tema integrado). Integra menús desplegables de cambio de versión, selectores de traducción de idioma, alternancia de sidebar responsiva, menús de sub-enlaces, modos de tema y un menú móvil responsivo:

// docs/components/ProductionNavbar.tsx
import React, { useState } from 'react'
import { Navbar, Menu, Button } from 'boltdocs/primitives'
import {
  useNavbar,
  useTheme,
  useSearch,
  useVersion,
  useI18n,
  useUI,
  useLocation,
  useLocalizedTo
} from 'boltdocs/client'
import { Menu as MenuIcon, X, ChevronDown, Languages } from 'lucide-react'

export default function ProductionNavbar() {
  const { links, title, logo, logoProps, github, social, config } = useNavbar()
  const { theme, toggleTheme } = useTheme()
  const { openSearch } = useSearch()
  const { isSidebarOpen, toggleSidebar } = useUI()
  const { pathname } = useLocation()
  const [mobileOpen, setMobileOpen] = useState(false)

  // 1. Menú Desplegable de Cambio de Versión
  const { currentVersionLabel, availableVersions, handleVersionChange } = useVersion()
  const VersionDropdown = availableVersions.length > 0 && (
    <Menu.Trigger>
      <Button className="flex items-center gap-1.5 px-3 py-1.5 border rounded-xl text-xs bg-surface font-semibold text-body hover:bg-zinc-50 dark:hover:bg-zinc-900 transition-all">
        <span>{currentVersionLabel}</span>
        <ChevronDown size={14} className="opacity-60" />
      </Button>
      <Menu.Root className="w-40 bg-white dark:bg-zinc-900 border border-subtle rounded-xl p-1.5 shadow-md flex flex-col gap-0.5">
        <Menu.Section items={availableVersions}>
          {(version) => (
            <Menu.Item
              key={version.value}
              onPress={() => handleVersionChange(version.value)}
              className="px-3 py-2 text-xs rounded-lg hover:bg-zinc-100 dark:hover:bg-zinc-800 cursor-pointer outline-none"
            >
              {version.label}
            </Menu.Item>
          )}
        </Menu.Section>
      </Menu.Root>
    </Menu.Trigger>
  )

  // 2. Selector de Idioma/i18n Desplegable
  const { currentLocale, availableLocales, handleLocaleChange } = useI18n()
  const LocaleDropdown = availableLocales.length > 0 && (
    <Menu.Trigger>
      <Button className="flex items-center gap-1.5 px-3 py-1.5 border border-subtle bg-surface rounded-xl text-xs font-semibold text-body hover:bg-zinc-50 dark:hover:bg-zinc-900 transition-all">
        <Languages size={14} className="text-primary-500" />
        <span className="uppercase">{currentLocale}</span>
        <ChevronDown size={14} className="opacity-60" />
      </Button>
      <Menu.Root className="w-40 bg-white dark:bg-zinc-900 border border-subtle rounded-xl p-1.5 shadow-md flex flex-col gap-0.5">
        <Menu.Section items={availableLocales}>
          {(locale) => (
            <Menu.Item
              key={locale.value}
              onPress={() => handleLocaleChange(locale.value)}
              className="px-3 py-2 text-xs rounded-lg hover:bg-zinc-100 dark:hover:bg-zinc-800 cursor-pointer outline-none"
            >
              {locale.label}
            </Menu.Item>
          )}
        </Menu.Section>
      </Menu.Root>
    </Menu.Trigger>
  )

  return (
    <Navbar className="bg-main/80 backdrop-blur-md border-b border-subtle">
      <Navbar.Content>
        
        {/* Sección Izquierda: Alternador de sidebar móvil, Logo, Título y Selección de Versión */}
        <Navbar.Left>
          {pathname.startsWith('/docs') && (
            <Button
              onPress={toggleSidebar}
              className="mr-2 lg:hidden p-1.5 text-muted hover:text-body rounded-lg hover:bg-surface transition-colors"
            >
              {isSidebarOpen ? <X size={20} /> : <MenuIcon size={20} />}
            </Button>
          )}

          {logo && <Navbar.Logo src={logo} alt={logoProps?.alt || title} href="/" />}
          <Navbar.Title href="/">{title}</Navbar.Title>
          
          <div className="hidden sm:block">
            {VersionDropdown}
          </div>
        </Navbar.Left>

        {/* Sección Central: Barra disparadora de diálogo de búsqueda */}
        <Navbar.Center>
          <Navbar.SearchTrigger onPress={openSearch} />
        </Navbar.Center>

        {/* Sección Derecha: Enlaces de Navegación, interruptor i18n, alternancia de tema, estrellas de Github y redes sociales */}
        <Navbar.Right>
          {/* Enlaces Principales de Escritorio */}
          <Navbar.Links>
            {links.map((link) => {
              const localizedHref = useLocalizedTo(link.href || '')
              const active = pathname === localizedHref || pathname.startsWith(localizedHref + '/')
              const hasItems = link.items && link.items.length > 0

              if (hasItems) {
                return (
                  <Navbar.Dropdown
                    key={link.href}
                    label={
                      <span className={`px-2 py-1 font-medium transition-colors cursor-pointer ${
                        active ? 'text-primary' : 'text-muted hover:text-body'
                      }`}>
                        {link.label}
                      </span>
                    }
                  >
                    {link.items?.map((sub) => (
                      <Navbar.DropdownItem
                        key={sub.href}
                        href={useLocalizedTo(sub.href || '')}
                        label={sub.label}
                      />
                    ))}
                  </Navbar.Dropdown>
                )
              }

              return (
                <Navbar.Link
                  key={link.href}
                  href={localizedHref}
                  label={link.label}
                  active={active}
                  className={active ? 'text-primary font-semibold' : 'text-muted hover:text-body'}
                />
              )
            })}
          </Navbar.Links>

          {/* Configuraciones de utilidad de escritorio */}
          <div className="hidden sm:flex items-center gap-2">
            {LocaleDropdown}
            <Navbar.Split className="bg-subtle" />
          </div>

          <Navbar.Theme theme={theme} onThemeChange={toggleTheme} />

          {/* Conexiones sociales (por ejemplo, botón de enlace de GitHub) */}
          {github && (
            <Navbar.Socials icon="github" link={github} />
          )}

          {/* Disparador "Más" para cajones móviles */}
          <Navbar.More onPress={() => setMobileOpen(true)} className="lg:hidden" />
        </Navbar.Right>
      </Navbar.Content>

      {/* Superposición de menú cajón móvil */}
      <Navbar.MobileMenu isOpen={mobileOpen} onClose={() => setMobileOpen(false)}>
        <div className="flex flex-col gap-1">
          {links.map((link) => {
            const localizedHref = useLocalizedTo(link.href || '')
            const active = pathname === localizedHref

            return (
              <Navbar.MobileLink
                key={link.href}
                href={localizedHref}
                label={link.label}
                active={active}
                onPress={() => setMobileOpen(false)}
                className="text-lg py-2"
              />
            )
          })}
        </div>

        {/* Lista unificada de selección de versiones e idiomas en vista móvil */}
        <div className="mt-6 border-t border-subtle pt-6 flex flex-col gap-4">
          <div className="flex justify-between items-center px-4">
            <span className="text-xs text-muted font-semibold uppercase">Versión</span>
            {VersionDropdown}
          </div>
          <div className="flex justify-between items-center px-4">
            <span className="text-xs text-muted font-semibold uppercase">Idioma</span>
            {LocaleDropdown}
          </div>
        </div>
      </Navbar.MobileMenu>
    </Navbar>
  )
}

Subcomponentes ComponiblesLink

La primitiva Navbar proporciona los siguientes subcomponentes para la personalización de la estructura:

ComponenteEtiqueta HTMLDescripciónProps
Navbar.Root / Navbar<header>Contenedor principal exterior del navbar.ComponentBaseProps
Navbar.Content<div>Contenedor de diseño centrado que contiene los elementos flex internos.ComponentBaseProps
Navbar.Left / Navbar.Center / Navbar.Right<div>Zonas de alineación de fila flex para logos, enlaces de navegación y botones de acción.ComponentBaseProps
Navbar.Logo<img> envuelto en <a>Renderiza un logo de imagen de marca envuelto en un enlace Router del cliente.Navbar.Logo Props
Navbar.Title<span>Renderiza una etiqueta de marca tipográfica de texto plano.ComponentBaseProps
Navbar.Link<a>Renderiza un enlace de anclaje optimizado a una ruta de página.Navbar.Link Props
Navbar.SearchTrigger<button>Un botón totalmente accesible para activar el diálogo de búsqueda.Navbar.SearchTrigger Props
Navbar.Theme<button>Renderiza un botón de icono para alternar modo claro/oscuro.Navbar.Theme Props
Navbar.Socials<a>Un acceso rápido a enlace social con icono (por ejemplo, GitHub, Discord, Twitter).Navbar.Socials Props
Navbar.MobileMenu<div> (Modal)Superposición de cajón modal responsivo deslizante para pantallas móviles.Navbar.MobileMenu Props
Navbar.MobileLink<a>Elementos de navegación dimensionados diseñados para menús de cajón móvil.Navbar.MobileLink Props

Props del ComponenteLink

ComponentBaseProps (Común)Link

PropiedadTipoPredeterminadoDescripción
childrenReactNodeundefinedElementos de contenido hijos.
classNamestringundefinedClases CSS utilitarias personalizadas.
styleCSSPropertiesundefinedConfiguraciones de estilo en línea.
PropiedadTipoPredeterminadoDescripción
srcstringRequeridoRuta al archivo de imagen del logo.
altstringRequeridoTexto alternativo de accesibilidad.
hrefstring'/'Ruta de destino al hacer clic en el logo.
widthnumber24Dimensión de ancho de la imagen.
heightnumber24Dimensión de alto de la imagen.
PropiedadTipoPredeterminadoDescripción
labelReactNodeRequeridoTexto del contenido de la etiqueta a mostrar.
hrefstringRequeridoRuta de destino de enrutamiento.
to'internal' | 'external''internal'Si la navegación es de enrutamiento interno o un enlace externo.

Props de Navbar.SearchTriggerLink

PropiedadTipoPredeterminadoDescripción
onPress() => voidRequeridoCallback de acción del disparador de presión.

Props de Navbar.ThemeLink

PropiedadTipoPredeterminadoDescripción
theme'dark' | 'light'RequeridoSelección del tema activo.
onThemeChange(isSelected: boolean) => voidRequeridoCallback de cambio de alternancia de tema.

Props de Navbar.SocialsLink

PropiedadTipoPredeterminadoDescripción
icon'github' | 'discord' | 'twitter'RequeridoIcono gráfico de la red social de destino.
linkstringRequeridoRuta del enlace URL.

Props de Navbar.MobileMenuLink

PropiedadTipoPredeterminadoDescripción
isOpenbooleanfalseEstado de visibilidad deslizante activa.
onClose() => voidRequeridoCallback del disparador de cierre.
childrenReactNodeRequeridoCeldas de contenido del menú del cajón móvil.

Hereda todas las Props de Navbar.Link más:

PropiedadTipoPredeterminadoDescripción
onPress() => voidundefinedCallback personalizado al hacer clic (por ejemplo, para cerrar cajones automáticamente).
Last updated on July 27, 2026

Was this page helpful?