Skip to content

[Bug] Nested button elements causing hydration error in FileBrowserDialog #150

@cabana8471-arch

Description

@cabana8471-arch

Bug: Nested button elements causing hydration error in FileBrowserDialog

Description

The FileBrowserDialog component contains nested <button> elements, which is invalid HTML and causes a React hydration error. Specifically, a "remove from recent" button is rendered as a child of a folder/project button.

Error Message

In HTML, <button> cannot be a descendant of <button>.
This will cause a hydration error.

Stack Trace

at button (<anonymous>:null:null)
at FileBrowserProvider (src/contexts/file-browser-context.tsx:71:7)
at Home (src/app/page.tsx:230:5)

Code Frame

  69 |     <FileBrowserContext.Provider value={{ openFileBrowser }}>
  70 |       {children}
> 71 |       <FileBrowserDialog
     |       ^
  72 |         open={isOpen}
  73 |         onOpenChange={handleOpenChange}
  74 |         onSelect={handleSelect}

Component Tree

The issue occurs in the following structure:

<button onClick={...} className="group flex items-center gap-1..." disabled={true}>
  <Folder />
  <span>...</span>
  <!-- Invalid: button nested inside button -->
  <button onClick={...} className="ml-0.5 opacity-0 group-hover:opacity-100..." title="Remove from recent">
    ...
  </button>
</button>

Expected Behavior

Interactive elements should not be nested. The "Remove from recent" action should be implemented without nesting a button inside another button.

Suggested Fix

Replace the nested button structure with one of the following approaches:

Option 1: Use a <div> or <span> with role="button" for the outer element

<div
  role="button"
  tabIndex={0}
  onClick={handleFolderClick}
  onKeyDown={handleKeyDown}
  className="group flex items-center gap-1..."
>
  <Folder />
  <span>{folderName}</span>
  <button onClick={handleRemove} title="Remove from recent">
    <X className="h-3 w-3" />
  </button>
</div>

Option 2: Use event.stopPropagation() with sibling elements

<div className="group flex items-center gap-1...">
  <button onClick={handleFolderClick} className="flex items-center gap-1">
    <Folder />
    <span>{folderName}</span>
  </button>
  <button
    onClick={(e) => { e.stopPropagation(); handleRemove(); }}
    title="Remove from recent"
  >
    <X className="h-3 w-3" />
  </button>
</div>

Environment

  • Next.js version: 16.0.10 (Turbopack)
  • React version: (check package.json)
  • Browser: All browsers (HTML validation issue)

Impact

  • Severity: Medium
  • Affects: User experience, accessibility, SSR hydration
  • Causes console errors on every render
  • May cause unexpected click behavior due to event bubbling
  • Violates HTML5 specification and accessibility guidelines

Labels

bug, accessibility, hydration, html-validation

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions