Saltar al contenido
EspañolEnglish
Todos los componentes (204)

Navegación lateral

Navegación · SideNav · .amset-nav

Qué es y cuándo usarlo

El menú lateral de una aplicación, con el diseño del menú de AMSET: cada entrada es un icono en su baldosa con el nombre en versalitas y una línea que dice qué hay ahí; la página actual se enciende con el acento (degradado, filo, barra luminosa en el borde y la baldosa iluminada); los grupos se despliegan bajo su cabecera, y plegado queda la columna de baldosas con lo pendiente en un globo.

Cuándo usarlo

  • Como menú principal de un panel de gestión, a la izquierda y siempre a la vista.
  • description en un enlace o un grupo para la línea de debajo del nombre («Por preparar y enviados»): orienta a quien llega nuevo sin tener que entrar.
  • Un grupo ({ key, label, icon, links: [...] } en lugar de href) para juntar pantallas hermanas bajo una cabecera que se despliega, como «Marketing» con sus campañas y sus cupones. Si la página actual está dentro, sale abierto.
  • counter en un enlace para lo que espera a alguien (pedidos por preparar, facturas vencidas).
  • collapsed cuando la pantalla necesita el ancho: quedan las baldosas, cada una con su nombre y su tooltip, y el contador sube a un globo con el número. Con onCollapsedChange el menú lleva su propio botón de plegar y desplegar en la cabecera; el estado lo sigue llevando quien lo monta.
  • header y footer como función (({ collapsed }) => …) para pintar la marca entera abierto y solo su sello en baldosas. collapsed llega también en true en una pantalla estrecha, donde el menú se queda en baldosas él solo: así el nombre no sale recortado.
  • onNavigate con enrutadores como Next o React Router: recibe la clave y el href del enlace pulsado y se llama en lugar de seguir el enlace (el clic del navegador se cancela). Con Ctrl, Cmd, Mayúsculas, Alt o el botón central el enlace se abre en otra pestaña o ventana, como cualquier otro, y onNavigate no se llama. Si la aplicación ya pone el RouterProvider de la biblioteca en la raíz, los enlaces navegan con él y onNavigate sobra.

Cuándo no

  • Para los enlaces principales de una web pública, arriba y en horizontal: TopBar.
  • Para la ruta hasta la pantalla actual: Breadcrumbs.
  • Para el índice de una página larga: TableOfContents.

Teclado: Tab recorre los enlaces y las cabeceras de grupo en orden. Intro sigue un enlace (con onNavigate, Intro también lo lleva el enrutador); Intro o Espacio abren y cierran un grupo, y el siguiente Tab entra en sus enlaces. Un enlace con disabled no coge el foco y se anuncia como no disponible. Plegado, el tooltip con el nombre sale también al llegar con el teclado.

Accesibilidad: es un nav con nombre obligatorio (label), con listas de verdad y un h2 por título de sección. La página actual lleva aria-current="page" además del fondo y la barra; la cabecera del grupo que la contiene se marca, pero sin aria-current, que es solo del enlace. La cabecera de un grupo es un <button> con aria-expanded y aria-controls. La descripción se anuncia como descripción (aria-describedby), no dentro del nombre. El nombre de cada enlace lleva también su contador, con el número escrito en el idioma y en singular o plural («Pedidos 4 pendientes», «Avisos 1 pendiente»), abierto y plegado: plegado, la etiqueta queda oculta a la vista pero sigue siendo el nombre (sin aria-label, que taparía el contador), y los títulos de sección siguen ahí, ocultos. Los iconos son decorativos; sin icono, plegado enseña la inicial.

Aspecto fino: variables CSS --amset-nav-*: -accent (el color de todo el menú, por defecto el acento del tema), -background (y -fade-color, el mismo color liso, que tapa el resplandor de «queda menú debajo» al llegar al final), -width, -padding, -gap, -radius, -icon-box y -icon-size (la baldosa y su icono), -font y -description-font, y la letra del nombre: -label-transform (uppercase; none para quitar las versalitas), -label-spacing y -label-weight. El tamaño (size) mueve el ancho (13, 16 o 19 rem), la baldosa, el relleno, el hueco y el cuerpo de letra. Por debajo de 40rem de pantalla el menú se queda en baldosas aunque no lleve collapsed.

Cómo se ve

const [activo, setActivo] = useState('pedidos')
const [plegado, setPlegado] = useState(false)

<SideNav
  label="Menú principal"
  active={activo}
  onNavigate={(clave) => setActivo(clave)}
  collapsed={plegado}
  onCollapsedChange={setPlegado}
  header={({ collapsed }) => (collapsed ? <Sello /> : <Marca />)}
  footer={({ collapsed }) => (collapsed ? <Cara /> : <Usuaria />)}
  sections={[
    { key: 'tienda', title: 'Tienda', links: [
      { key: 'inicio', label: 'Inicio', description: 'Resumen del día', href: '/', icon: <LayoutDashboardIcon /> },
      { key: 'pedidos', label: 'Pedidos', description: 'Por preparar y enviados', href: '/pedidos', icon: <CartIcon />, counter: 4 },
      { key: 'marketing', label: 'Marketing', description: 'Campañas y cupones', icon: <MegaphoneIcon />, links: [
        { key: 'campanas', label: 'Campañas', href: '/campanas', icon: <MailIcon /> },
        { key: 'cupones', label: 'Cupones', href: '/cupones', icon: <TagIcon /> },
      ] },
    ] },
  ]}
/>

Props

Se importa con import { SideNav } from '@amset/ui'. Las obligatorias van marcadas.

PropTipoPara qué sirve
labelobligatoriastringQue navegacion es esta. Obligatorio: en una pagina puede haber varias.
sectionsobligatoriareadonly NavSection[]—
activestringClave del enlace de la pagina actual.
classNamestringSe une a las clases de la biblioteca, no las sustituye.
collapsedbooleanSolo iconos. La etiqueta pasa al tooltip y al nombre accesible.
footerNavSlotAbajo del todo: el usuario, cerrar sesion, la version. Como funcion, igual que `header`.
headerNavSlotEncima de los enlaces: el logotipo, un selector de empresa. Como funcion recibe `{ collapsed }` -tambien `true` en pantalla estrecha, donde el menu se queda en baldosas el solo- para pintar solo el sello en vez de recortar el nombre.
onCollapsedChange(collapsed: boolean) => voidSi se pasa, el menu lleva su boton de plegar y desplegar en la cabecera, y aqui llega lo que se pide. El estado lo sigue llevando quien monta el menu, con `collapsed`.
onNavigate(key: string, href: string) => voidPara que navegue el enrutador del proyecto (Next, React Router) y no el navegador. Si se pasa, el clic normal y el Intro llaman aqui **en lugar de** seguir el enlace: el clic del navegador se cancela. Con Ctrl, Cmd, Mayusculas o Alt, o con el boton central, el enlace se abre en otra pestaña o ventana como cualquier otro y aqui no se llama. Si la aplicacion ya pone el `RouterProvider` de la biblioteca en la raiz, los enlaces navegan con el sin esto.
size"sm" | "md" | "lg"El ancho y el cuerpo de letra: 13, 16 o 19 rem. Por debajo de 40rem de pantalla el menu se queda en iconos pase lo que pase, que es lo unico que cabe al lado del contenido.

Acepta además los atributos del elemento que pinta: className, style, data-*, aria-* y sus eventos.

Mandos

Estas variables CSS son la forma de adaptarlo. Se declaran sobre el selector del componente, no en :root: la hoja las redeclara en la propia regla y una declaración en el mismo elemento gana siempre.

VariablePor defecto
--amset-nav-width16rem
--amset-nav-paddingvar(--amset-space-2)
--amset-nav-gapvar(--amset-space-3)
--amset-nav-fontvar(--amset-text-xs)
--amset-nav-description-fontvar(--amset-text-sm)
--amset-nav-icon-box2.375rem
--amset-nav-icon-size1.125rem
--amset-nav-label-transformuppercase
--amset-nav-label-spacing0.08em
--amset-nav-label-weightvar(--amset-weight-bold)
--amset-nav-accentvar(--amset-accent)
--amset-nav-backgroundvar(--amset-surface)
--amset-nav-fade-colorvar(--amset-surface)
--amset-nav-radiusvar(--amset-radius-lg)

Cómo se cambia

.amset-nav {
  --amset-nav-width: ...;
  --amset-nav-padding: ...;
}

En el banco de pruebas

Cada estado y cada variante, para tocarlos de uno en uno, en su ficha de ui.amset.tech: