Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
4b29638
fix: resolve element selection getting stuck on busy pages
aidenybai Apr 9, 2026
da29b1e
fix: reduce flaky E2E tests
aidenybai Apr 9, 2026
64dc9e7
refactor: inline onIdle into nativeRequestAnimationFrame and extract …
aidenybai Apr 9, 2026
8c9e55d
perf: use setTimeout over rAF for element detection scheduling
aidenybai Apr 9, 2026
3e6e660
docs: document why setTimeout is used for element detection scheduling
aidenybai Apr 9, 2026
e05242b
fix: exclude replaced elements from decorative overlay filter
aidenybai Apr 9, 2026
4296c13
refactor: allowlist DIV/SPAN instead of blocklisting replaced elements
aidenybai Apr 9, 2026
4c13a24
refactor: replace isDecorativeOverlay with hasVisualContent check
aidenybai Apr 9, 2026
4aee8e3
fix: check background-image and box-shadow in hasVisualContent
aidenybai Apr 9, 2026
f0138bf
refactor: prefer smallest element instead of content heuristics
aidenybai Apr 9, 2026
9859c2a
style: remove em dash from comment
aidenybai Apr 9, 2026
7b47026
perf: use clientWidth/clientHeight instead of getBoundingClientRect
aidenybai Apr 9, 2026
a46c348
perf: use clientWidth/clientHeight in isFullViewportOverlay
aidenybai Apr 9, 2026
7a8ec6e
docs: add perf-learnings.md from Inferno/Solid/ivi/pretext audit
aidenybai Apr 9, 2026
55c4f03
docs: add prehit.md design for pre-indexed element hit testing
aidenybai Apr 9, 2026
2a47185
docs: add DOM filtering to prehit indexing phase
aidenybai Apr 9, 2026
96bb15e
feat: add prehit spatial index infrastructure (not yet wired)
aidenybai Apr 9, 2026
0ffd2d8
fix: clear element references on prehit index destroy
aidenybai Apr 9, 2026
afacfee
fix: destroy prehit index on dispose to prevent memory leaks
aidenybai Apr 9, 2026
d10858b
refactor: use IntersectionObserver for prehit rect collection
aidenybai Apr 9, 2026
a037c70
feat: wire prehit spatial index into the detection hot path
aidenybai Apr 9, 2026
3153664
fix: check overflow-x/overflow-y independently and handle contain:paint
aidenybai Apr 9, 2026
592a161
fix: address code review findings from AGENTS.md audit
aidenybai Apr 9, 2026
da93bcc
refactor: rename vendor files to algorithm names
aidenybai Apr 9, 2026
28727d5
docs: fix markdown table formatting in prehit.md
aidenybai Apr 9, 2026
f4661f1
style: remove header comment from stacking-context-comparator
aidenybai Apr 9, 2026
5793094
refactor: remove dead code and simplify prehit clip check
aidenybai Apr 9, 2026
7bef6a5
refactor: move hilbert-r-tree from vendor/ to utils/
aidenybai Apr 9, 2026
d9a32d9
perf: optimize freeze system activation and deactivation
aidenybai Apr 9, 2026
0713003
fix: skip zero-area inline elements in smallest-area comparison
aidenybai Apr 9, 2026
6bde5fc
fix: consistent area metric and contain shorthand in prehit
aidenybai Apr 9, 2026
1fde798
fix: handle inline elements and public freeze() API
aidenybai Apr 10, 2026
1e7541c
refactor: extract getElementArea helper for inline element fallback
aidenybai Apr 10, 2026
2dee7a5
refactor: rename prehit to spatial-index and delete docs/
aidenybai Apr 10, 2026
296259e
refactor: rename spatial-index to element-at-point-index
aidenybai Apr 10, 2026
3038d97
feat: use stacking order for z-index-aware element selection
aidenybai Apr 10, 2026
83d79a3
fix: offscreen pointer, flex stacking context, consistent selection
aidenybai Apr 10, 2026
f84d8e8
fix: viewport boundary off-by-one and revert animation caching
aidenybai Apr 10, 2026
abc7d38
fix: hilbert function reads modified levelC in levelD computation
aidenybai Apr 10, 2026
05f9caf
fix: handle sticky position and grid items in stacking context detection
aidenybai Apr 10, 2026
b74155c
fix: validate prehit result and snapshot elements array
aidenybai Apr 10, 2026
a34a57a
fix: use CSS property names in will-change stacking context regex
aidenybai Apr 10, 2026
de5ffe6
fix: skip position:fixed elements in spatial index
aidenybai Apr 10, 2026
ff4875c
fix: restore smallest-area fallback and exclude decorative overlays f…
aidenybai Apr 11, 2026
eb5d3ce
perf: cache fixed element rects and clip state, add stacking context …
aidenybai Apr 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 248 additions & 0 deletions apps/e2e-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,242 @@ const PointerUpModalSection = () => {
);
};

const OverflowClippingSection = () => {
return (
<section className="border rounded-lg p-4" data-testid="overflow-clipping-section">
<h2 className="text-lg font-bold mb-4">Overflow Clipping</h2>
<div className="space-y-4">
<div
className="overflow-hidden w-40 h-20 border-2 border-red-400 relative"
data-testid="overflow-hidden-container"
>
<div className="absolute w-80 h-10 bg-blue-200 p-2" data-testid="overflow-clipped-wide">
Wide clipped content
</div>
<div className="p-2 bg-green-200" data-testid="overflow-visible-child">
Visible child
</div>
</div>

<div
className="overflow-auto w-40 h-24 border-2 border-orange-400"
data-testid="overflow-auto-container"
>
<div className="w-80 h-40 bg-yellow-100 p-2">
<span data-testid="overflow-auto-inner">Scrollable inner content</span>
</div>
</div>

<div
className="overflow-hidden border-2 border-purple-400"
style={{ width: "200px", height: "40px" }}
data-testid="overflow-nested-outer"
>
<div
className="overflow-hidden border border-purple-200"
style={{ width: "150px", height: "30px" }}
data-testid="overflow-nested-inner"
>
<div
className="bg-purple-100 p-1"
style={{ width: "300px", height: "60px" }}
data-testid="overflow-nested-content"
>
Nested clipped content
</div>
</div>
</div>
</div>
</section>
);
};

const ContainPaintSection = () => {
return (
<section className="border rounded-lg p-4" data-testid="contain-paint-section">
<h2 className="text-lg font-bold mb-4">CSS Containment</h2>
<div className="space-y-4">
<div
style={{ contain: "paint", width: "150px", height: "40px" }}
className="border-2 border-teal-400 relative"
data-testid="contain-paint-container"
>
<div
className="absolute bg-teal-200 p-2"
style={{ width: "300px", height: "30px" }}
data-testid="contain-paint-clipped"
>
Paint-contained clipped
</div>
</div>

<div
style={{ contain: "strict", width: "150px", height: "40px" }}
className="border-2 border-cyan-400 relative"
data-testid="contain-strict-container"
>
<div className="bg-cyan-200 p-2" data-testid="contain-strict-child">
Strict contained
</div>
</div>

<div
style={{ contain: "content", width: "150px", height: "40px" }}
className="border-2 border-sky-400 relative"
data-testid="contain-content-container"
>
<div className="bg-sky-200 p-2" data-testid="contain-content-child">
Content contained
</div>
</div>
</div>
</section>
);
};

const StackingOrderSection = () => {
return (
<section className="border rounded-lg p-4" data-testid="stacking-order-section">
<h2 className="text-lg font-bold mb-4">Stacking Order</h2>
<div className="relative" style={{ height: "120px" }}>
<div
className="absolute bg-red-300 p-4"
style={{ top: "0", left: "0", width: "200px", height: "100px", zIndex: 1 }}
data-testid="stacking-bottom"
>
Bottom (z-index: 1)
</div>
<div
className="absolute bg-green-300 p-4"
style={{ top: "20px", left: "20px", width: "200px", height: "100px", zIndex: 2 }}
data-testid="stacking-middle"
>
Middle (z-index: 2)
</div>
<div
className="absolute bg-blue-300 p-4"
style={{ top: "40px", left: "40px", width: "200px", height: "100px", zIndex: 3 }}
data-testid="stacking-top"
>
Top (z-index: 3)
</div>
</div>

<div className="relative mt-8" style={{ height: "80px" }}>
<div
className="absolute bg-amber-200 p-4"
style={{ top: "0", left: "0", width: "250px", height: "60px" }}
data-testid="stacking-large-behind"
>
Large element behind
</div>
<div
className="absolute bg-amber-500 text-white p-2"
style={{ top: "10px", left: "10px", width: "100px", height: "40px", zIndex: 1 }}
data-testid="stacking-small-front"
>
Small in front
</div>
</div>
</section>
);
};

const DecorativeOverlaySection = () => {
return (
<section className="border rounded-lg p-4" data-testid="decorative-overlay-section">
<h2 className="text-lg font-bold mb-4">Decorative Overlays</h2>
<div className="relative" style={{ height: "80px" }}>
<div className="bg-indigo-200 p-4" data-testid="decorative-content">
This content should be selectable
</div>
<div
className="absolute inset-0"
style={{ pointerEvents: "none" }}
data-testid="decorative-empty-overlay"
/>
</div>

<div className="relative mt-4" style={{ height: "80px" }}>
<p className="bg-pink-200 p-4" data-testid="decorative-text-content">
Text content under a positioned empty div
</p>
<div
className="absolute"
style={{ top: "0", left: "0", width: "100%", height: "100%" }}
data-testid="decorative-positioned-empty"
/>
</div>
</section>
);
};

const InlineElementsSection = () => {
return (
<section className="border rounded-lg p-4" data-testid="inline-elements-section">
<h2 className="text-lg font-bold mb-4">Inline Elements</h2>
<p className="mb-2" data-testid="inline-paragraph">
This paragraph has <span data-testid="inline-span">an inline span</span> and{" "}
<a href="#" data-testid="inline-link" className="text-blue-500 underline">
an inline link
</a>{" "}
and <em data-testid="inline-em">emphasized text</em> and{" "}
<strong data-testid="inline-strong">strong text</strong> inside it.
</p>
<p className="mb-2">
<code className="bg-gray-100 px-1" data-testid="inline-code">
inline code element
</code>
</p>
</section>
);
};

const TransformStackingSection = () => {
return (
<section className="border rounded-lg p-4" data-testid="transform-stacking-section">
<h2 className="text-lg font-bold mb-4">Transform & Opacity Stacking</h2>
<div className="space-y-4">
<div
className="bg-rose-200 p-4"
style={{ transform: "translateZ(0)" }}
data-testid="transform-element"
>
Transformed element (creates stacking context)
</div>

<div className="bg-violet-200 p-4" style={{ opacity: 0.99 }} data-testid="opacity-element">
Opacity element (creates stacking context)
</div>

<div className="relative" style={{ height: "80px" }}>
<div
className="absolute bg-lime-200 p-4"
style={{ top: "0", left: "0", width: "200px", height: "60px" }}
data-testid="transform-behind"
>
Behind
</div>
<div
className="absolute bg-lime-500 text-white p-2"
style={{
top: "10px",
left: "10px",
width: "120px",
height: "40px",
transform: "scale(1)",
zIndex: 1,
}}
data-testid="transform-front"
>
Front (transform)
</div>
</div>
</div>
</section>
);
};

const HiddenToggleSection = () => {
const [isVisible, setIsVisible] = useState(true);
const elementRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -648,6 +884,18 @@ export default function App() {

<PointerUpModalSection />

<OverflowClippingSection />

<ContainPaintSection />

<StackingOrderSection />

<DecorativeOverlaySection />

<InlineElementsSection />

<TransformStackingSection />

<HiddenToggleSection />

<div
Expand Down
Loading
Loading