Skip to content

Add .parent modifier for x-intersect#4839

Merged
calebporzio merged 3 commits into
alpinejs:mainfrom
kevinruscoe:main
Jun 27, 2026
Merged

Add .parent modifier for x-intersect#4839
calebporzio merged 3 commits into
alpinejs:mainfrom
kevinruscoe:main

Conversation

@kevinruscoe

Copy link
Copy Markdown
Contributor

This pull request adds support for using a parent element as the viewport for x-intersect in Alpine.js, instead of the default browser viewport. This allows elements to be observed relative to their parent container, which is useful for more complex layouts. Documentation has also been updated to explain the new .parent modifier.

Feature: Support for parent viewport in IntersectionObserver

  • packages/intersect/src/index.js: Added logic to set the root option to the parent element when the parent modifier is present, enabling intersection observation relative to the parent container.

Documentation update

Copilot AI review requested due to automatic review settings May 29, 2026 16:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a .parent modifier to the x-intersect plugin so the underlying IntersectionObserver can use the element’s parent as the observation root, and documents the new modifier.

Changes:

  • Add root configuration to IntersectionObserver options when .parent is used.
  • Document the new .parent modifier in the intersect plugin docs.

Reviewed changes

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

File Description
packages/intersect/src/index.js Adds support for .parent by setting IntersectionObserver’s root to the element’s parent.
packages/docs/src/en/plugins/intersect.md Documents the new .parent modifier and provides an example.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Allows for the underlying `IntersectionObserver` to use the viewport of the parent element, rather than the default, which is the browser.

```alpine
<div x-intersect.parent="shown = true">...</div> // Mark as shown when element is moves inside it's parents viewport.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please update this.

Comment thread packages/docs/src/en/plugins/intersect.md Outdated
@joshhanley joshhanley changed the title Add parent modifier for x-intersect and update documentation Add .parent modifier for x-intersect Jun 1, 2026

@joshhanley joshhanley left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@kevinruscoe thanks for the PR! Can you please add some tests? Can you also address Copilot's second concern regarding the grammar in the comment. Thanks!

Add a Cypress test that verifies x-intersect.parent observes the element
relative to its parent (the IntersectionObserver root) rather than the
browser viewport, and reword the docs for accuracy/grammar.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@calebporzio

Copy link
Copy Markdown
Collaborator

Pushed a follow-up commit (6704f82) to get this over the line on the review feedback:

1. Added a test (tests/cypress/integration/plugins/intersect.spec.js)

Added a .parent test that proves the modifier actually re-roots the IntersectionObserver at the parent rather than the viewport. The scroll container is pushed far below the fold (height: 200vh spacer), so a window-rooted observer would never fire — the count only increments when the content is scrolled into view within the container:

test('.parent observes the element relative to its parent, not the viewport', ...
    get('span').should(haveText('0'))
    get('#container').scrollTo(0, 250, {duration: 100}) // scroll within the parent, not the page
    get('span').should(haveText('1'))

I verified end-to-end in a real browser that the same markup gives 1 with .parent and 0 without it, so the test genuinely depends on the feature rather than passing incidentally. Ran the full spec locally — all 9 tests pass:

✓ .threshold (290ms)
✓ .parent observes the element relative to its parent, not the viewport (285ms)
9 passing (5s)

2. Fixed the docs (addressing both Copilot notes Josh flagged)

  • Fixed the grammar in the example comment (element is moves inside it's parentsthe element scrolls into view within its parent).
  • Reworded the description, which previously said the default root "is the browser." IntersectionObserver defaults to the top-level viewport (root: null), so the copy now says the element is observed "against the browser's viewport" and explains that .parent sets the observer's root to the parent element.

I left the <a name="parent"> anchor in place since every other modifier section in this doc uses the same pattern.

(Pushed directly to the branch via maintainer edits — thanks @kevinruscoe!)

@calebporzio

Copy link
Copy Markdown
Collaborator

thanks!

@calebporzio calebporzio merged commit a4cfe57 into alpinejs:main Jun 27, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants