mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Add invisible hover buffer around the before/after demo
Ported the homepage's padding-margin trick: .split-comparison now has 20px of padding around the visible box, with a matching negative top/bottom margin so the padding does not affect layout flow. The pointer event listeners move from .split-container to .split-comparison so the hover tracking engages inside the buffer and only resets when the mouse leaves the full padded area. Percentage math still reads .split-container.getBoundingClientRect() so the divider position stays aligned with the visible box. This matches how the landing-page split demo feels: graze the edge and the divider holds; leave the box entirely and it eases back.
This commit is contained in:
@@ -997,8 +997,13 @@ main#main {
|
||||
.split-comparison {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
margin: 0 0 clamp(2rem, 4vw, 3rem);
|
||||
max-width: 540px;
|
||||
/* 20px padding acts as an invisible hover buffer so the divider does
|
||||
not immediately snap back when the pointer grazes the box edge.
|
||||
Negative top/bottom margins collapse the padding out of layout flow
|
||||
so the demo still sits at its intended rhythm in the page. */
|
||||
padding: 20px;
|
||||
margin: -20px 0 calc(clamp(2rem, 4vw, 3rem) - 20px);
|
||||
}
|
||||
|
||||
.split-container {
|
||||
|
||||
+21
-15
@@ -116,17 +116,20 @@ ${bodyHtml}
|
||||
});
|
||||
|
||||
// Before/after split-compare: drag on touch, hover OR drag on mouse.
|
||||
// On mouse-leave the divider eases back to the default position.
|
||||
// Pointer events attach to the padded .split-comparison wrapper so
|
||||
// there is a ~20px invisible buffer around the visible box. The
|
||||
// divider only snaps back when the pointer leaves that outer buffer.
|
||||
(function initSplitCompare() {
|
||||
const containers = document.querySelectorAll('.split-container');
|
||||
if (containers.length === 0) return;
|
||||
const wrappers = document.querySelectorAll('.split-comparison');
|
||||
if (wrappers.length === 0) return;
|
||||
const hasHover = matchMedia('(hover: hover)').matches;
|
||||
const DEFAULT_POSITION = 50;
|
||||
|
||||
for (const container of containers) {
|
||||
const splitAfter = container.querySelector('.split-after');
|
||||
const splitDivider = container.querySelector('.split-divider');
|
||||
if (!splitAfter || !splitDivider) continue;
|
||||
for (const wrapper of wrappers) {
|
||||
const container = wrapper.querySelector('.split-container');
|
||||
const splitAfter = wrapper.querySelector('.split-after');
|
||||
const splitDivider = wrapper.querySelector('.split-divider');
|
||||
if (!container || !splitAfter || !splitDivider) continue;
|
||||
|
||||
const tanAngle = Math.tan(10 * Math.PI / 180);
|
||||
let skewOffset = 8;
|
||||
@@ -168,6 +171,9 @@ ${bodyHtml}
|
||||
|
||||
paint(DEFAULT_POSITION);
|
||||
|
||||
// Percentage is always relative to the VISIBLE .split-container,
|
||||
// not the padded .split-comparison wrapper. The pointer event
|
||||
// target is the wrapper but the clip-path math uses the inner box.
|
||||
const pctFromClientX = (clientX) => {
|
||||
const rect = container.getBoundingClientRect();
|
||||
return ((clientX - rect.left) / rect.width) * 100;
|
||||
@@ -176,19 +182,19 @@ ${bodyHtml}
|
||||
let hovering = false;
|
||||
let dragging = false;
|
||||
|
||||
container.addEventListener('pointerenter', (e) => {
|
||||
wrapper.addEventListener('pointerenter', (e) => {
|
||||
if (hasHover && e.pointerType === 'mouse') {
|
||||
hovering = true;
|
||||
}
|
||||
});
|
||||
|
||||
container.addEventListener('pointerdown', (e) => {
|
||||
wrapper.addEventListener('pointerdown', (e) => {
|
||||
dragging = true;
|
||||
container.setPointerCapture(e.pointerId);
|
||||
wrapper.setPointerCapture(e.pointerId);
|
||||
setTarget(pctFromClientX(e.clientX));
|
||||
});
|
||||
|
||||
container.addEventListener('pointermove', (e) => {
|
||||
wrapper.addEventListener('pointermove', (e) => {
|
||||
if (dragging || hovering) {
|
||||
setTarget(pctFromClientX(e.clientX));
|
||||
}
|
||||
@@ -197,14 +203,14 @@ ${bodyHtml}
|
||||
const endDrag = (e) => {
|
||||
if (dragging) {
|
||||
dragging = false;
|
||||
try { container.releasePointerCapture(e.pointerId); } catch {}
|
||||
try { wrapper.releasePointerCapture(e.pointerId); } catch {}
|
||||
}
|
||||
};
|
||||
|
||||
container.addEventListener('pointerup', endDrag);
|
||||
container.addEventListener('pointercancel', endDrag);
|
||||
wrapper.addEventListener('pointerup', endDrag);
|
||||
wrapper.addEventListener('pointercancel', endDrag);
|
||||
|
||||
container.addEventListener('pointerleave', (e) => {
|
||||
wrapper.addEventListener('pointerleave', (e) => {
|
||||
endDrag(e);
|
||||
if (hovering) {
|
||||
hovering = false;
|
||||
|
||||
Reference in New Issue
Block a user