Skip to content

allow cell selection on non-interactive marimo elements#9399

Merged
mscolnick merged 2 commits into
mainfrom
sham/fix-lazy-cell-highlighting
Apr 28, 2026
Merged

allow cell selection on non-interactive marimo elements#9399
mscolnick merged 2 commits into
mainfrom
sham/fix-lazy-cell-highlighting

Conversation

@Light2Dark

@Light2Dark Light2Dark commented Apr 27, 2026

Copy link
Copy Markdown
Member

📝 Summary

Closes #9189 and #9386.

  • isInteractiveTarget used target.closest('…, marimo-ui-element'), which wrongly suppressed selection for mo.lazy (it's a UIElement wrapped in ) and couldn't see inside the plugin's Shadow DOM.
  • Walk event.nativeEvent.composedPath() from target to cell instead, piercing shadow roots.
  • Skip passive content wrappers (marimo-lazy, marimo-routes) so their inner content is selectable, while still detecting any real interactive widget further along the path.
image

📋 Pre-Review Checklist

  • For large changes, or changes that affect the public API: this change was discussed or approved through an issue, on Discord, or the community discussions (Please provide a link if applicable).
  • Any AI generated code has been reviewed line-by-line by the human PR author, who stands by it.
  • Video or media evidence is provided for any visual changes (optional).

✅ Merge Checklist

  • I have read the contributor guidelines.
  • Documentation has been updated where applicable, including docstrings for API changes.
  • Tests have been added for the changes made.
@vercel

vercel Bot commented Apr 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview, Comment Apr 27, 2026 5:28pm

Request Review

@Light2Dark Light2Dark added the bug Something isn't working label Apr 27, 2026
@Light2Dark Light2Dark marked this pull request as ready for review April 27, 2026 16:22
Copilot AI review requested due to automatic review settings April 27, 2026 16:22

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Architecture diagram
sequenceDiagram
    participant User
    participant Hook as useCellRangeSelection
    participant DOM as Browser DOM
    participant Logic as isInteractiveTarget()

    Note over User, Logic: Runtime Cell Selection Flow

    User->>Hook: Mouse Down on Table Cell Target
    Hook->>Logic: Check if interaction should be ignored
    
    Logic->>DOM: target.closest(INTERACTIVE_SELECTOR)
    DOM-->>Logic: interactiveAncestor
    
    alt No interactive ancestor found
        Logic-->>Hook: return false (ALLOW selection)
    else Ancestor is standard HTML (input, button, etc.)
        Logic-->>Hook: return true (BLOCK selection)
    else Ancestor is "marimo-ui-element"
        Logic->>DOM: Get first child element
        DOM-->>Logic: innerElement (e.g. marimo-lazy, marimo-slider)
        
        alt NEW: innerElement is CONTENT_WRAPPER (marimo-lazy | marimo-routes)
            Note right of Logic: These are non-interactive containers
            Logic-->>Hook: return false (ALLOW selection)
        else innerElement is functional widget (marimo-slider, etc.)
            Logic-->>Hook: return true (BLOCK selection)
        end
    end

    alt Selection ALLOWED
        Hook->>Hook: Update range selection state
    else Selection BLOCKED
        Hook->>Hook: Do nothing (let component handle interaction)
    end
Loading

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts data-table cell range selection behavior so clicks on non-interactive Marimo UI wrappers (notably mo.lazy / marimo-lazy) no longer suppress cell selection, addressing selection/highlight issues reported for lazy-rendered content.

Changes:

  • Refines isInteractiveTarget() to treat certain <marimo-ui-element> wrappers (whose first child is a “content-wrapper” tag) as non-interactive.
  • Adds unit tests covering passive content-wrapper tags vs. interactive UIElement tags.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
frontend/src/components/data-table/range-focus/use-cell-range-selection.ts Updates interactivity detection logic to allow selection through specific wrapper UIElements.
frontend/src/components/data-table/range-focus/tests/use-cell-range-selection.test.ts Adds regression tests for passive wrapper tags and interactive Marimo UI elements.
Comment thread frontend/src/components/data-table/range-focus/use-cell-range-selection.ts Outdated
@Light2Dark Light2Dark marked this pull request as draft April 27, 2026 16:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

@Light2Dark

Copy link
Copy Markdown
Member Author

@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review

@Light2Dark I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Architecture diagram
sequenceDiagram
    participant User
    participant Hook as useCellRangeSelection
    participant Logic as isInteractiveTarget()
    participant DOM as DOM / Shadow Tree

    User->>Hook: mousedown (on cell content)
    Hook->>Logic: check if interaction should block selection
    
    Note over Logic, DOM: CHANGED: Use composedPath() to pierce Shadow DOM
    Logic->>DOM: get nativeEvent.composedPath()
    DOM-->>Logic: [target, ..., cell]

    loop For each Node in Path (until currentTarget)
        alt Standard Interactive Tag (input, button, a, etc.)
            Logic-->>Hook: return true (Selection Blocked)
        else NEW: Node is <marimo-ui-element>
            alt Child is passive wrapper (marimo-lazy, marimo-routes)
                Note over Logic: NEW: Skip wrapper to check inner content
                Logic->>Logic: continue loop
            else Child is stateful widget (e.g. slider)
                Logic-->>Hook: return true (Selection Blocked)
            end
        else Node matches role="checkbox" or role="button"
            Logic-->>Hook: return true (Selection Blocked)
        end
    end

    alt No interactive elements found in path
        Logic-->>Hook: return false (Selection Allowed)
        Hook->>Hook: CHANGED: Update cell range selection state
    end
Loading

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@Light2Dark Light2Dark marked this pull request as ready for review April 28, 2026 12:17

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Architecture diagram
sequenceDiagram
    participant User
    participant Hook as useCellRangeSelection
    participant Logic as isInteractiveTarget()
    participant DOM as DOM / Shadow Tree

    User->>Hook: mousedown (on cell content)
    Hook->>Logic: check if interaction should block selection
    
    Note over Logic, DOM: CHANGED: Use composedPath() to pierce Shadow DOM
    Logic->>DOM: get nativeEvent.composedPath()
    DOM-->>Logic: [target, ..., cell]

    loop For each Node in Path (until currentTarget)
        alt Standard Interactive Tag (input, button, a, etc.)
            Logic-->>Hook: return true (Selection Blocked)
        else NEW: Node is <marimo-ui-element>
            alt Child is passive wrapper (marimo-lazy, marimo-routes)
                Note over Logic: NEW: Skip wrapper to check inner content
                Logic->>Logic: continue loop
            else Child is stateful widget (e.g. slider)
                Logic-->>Hook: return true (Selection Blocked)
            end
        else Node matches role="checkbox" or role="button"
            Logic-->>Hook: return true (Selection Blocked)
        end
    end

    alt No interactive elements found in path
        Logic-->>Hook: return false (Selection Allowed)
        Hook->>Hook: CHANGED: Update cell range selection state
    end
Loading
@mscolnick mscolnick merged commit adcbaa5 into main Apr 28, 2026
42 checks passed
@mscolnick mscolnick deleted the sham/fix-lazy-cell-highlighting branch April 28, 2026 17:25
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Development release published. You may be able to view the changes at https://marimo.app?v=0.23.4-dev21

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

3 participants