Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

nav: hamburger icon pops in late on first load (toggle is portalled after hydration)

Cerrado Apto para principiantes
#322 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
76/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
next.js, react, typescript
Área
frontend

Línea de trabajo

Lee components/layout/MobileMenu.tsx y el estado de navegación relacionado en Chrome; después, inspecciona la salida prerenderizada de pnpm build. Haz que .mm-toggle esté presente en el renderizado inicial y conserva el comportamiento actual del menú móvil; verifica que el HTML exportado lo incluya y que la superposición y el panel sigan abriéndose correctamente.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug

Symptom

On a cold load below 1280px the top-right menu icon (the `.mm-toggle` hamburger) is missing from the first paint and appears only once the JS bundle has downloaded and hydrated. On a real phone on a real network that is a visible pop-in next to a wordmark that was there from the first frame.

Confirmed

Served the fresh export (pnpm build on main @ 736bdfb) from a local static server and loaded it in headless Chromium (Playwright 1.56, 390×844 viewport) with JS chunk responses delayed 400 ms to widen the pre-hydration window, recording MutationObserver events on <html> from the first script tick plus a screenshot every ~100 ms.

  • The prerendered HTML contains no mm-toggle at all: grep -c mm-toggle out/index.html → 0, and the live page gives the same: curl -sL https://decdn.org/ | grep -c mm-toggle → 0.
  • First mutations after hydration (t ≈ 861 ms in this run):
    add <button .mm-toggle>        parent <body>
    add <div .mm-overlay>          parent <body>
    add <aside .mm-panel #mm-panel> parent <body>
    
  • Frame at 831 ms: wordmark only, empty top-right. Frame at 945 ms: hamburger present. Nothing else in the nav changes between those frames.
  • Same mutation sequence at 1440×900; there the toggle is display: none via the @media (min-width: 1280px) gate in globals.css, so desktop is unaffected.

Cause

components/layout/MobileMenu.tsx renders the toggle, overlay and panel through createPortal(..., document.body) and gates the whole subtree on a useSyncExternalStore hydration flag (server snapshot false), so the prerender emits nothing and the client mounts all three only after hydration. Introduced with the drawer in #56. The portal exists so the toggle can sit above the panel (z-65 > z-60) while the wordmark stays in the nav — see the comment above const drawer in that file.

Not the cause (checked)

  • Favicon: Chromium requests only /icon.svg (never favicon.ico), and the .ico frames and the SVG are the same artwork on a white rounded tile, so there is no tab-icon flash in Chrome.
  • The wordmark-light.svg / wordmark-dark.svg pair is requested at t ≈ 28 ms and both stay mounted, so the logo does not flash.
  • The try-it SelectMenu also swaps at hydration (NativeSelect → listbox), but it is below the fold and by design renders the same face in both.

Possible direction

Prerender the <button class="mm-toggle"> so it is in the static HTML from the first byte (e.g. render it inline in the nav, or portal it with a server-rendered fallback), and keep the hydration gate only for the overlay and panel, which are invisible until opened anyway. The toggle's data-tone and data-open come from Chrome state that already prerenders deterministically (intro / closed), so there should be no hydration mismatch.

Lenguaje dominante
TypeScript
Estrellas
3
Forks
0
Merge medio
12 h 41 min
PR fusionados (30 d)
70

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de decdn/website

Todos los issues de decdn/website

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.