Improve split comparison: add before/after badges, extend slider range

Adds floating corner badges to clarify which side is before/after,
removes the "With Skills" divider label, and extends the slider range
to account for the skewed divider so it can fully reveal each side.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-03-04 09:39:05 -08:00
co-authored by Claude Opus 4.6
parent fd99c1f391
commit 98f5d839fd
7 changed files with 78 additions and 20 deletions
+3
View File
@@ -525,6 +525,9 @@ code {
width: 100%;
max-width: 600px;
margin: 0 auto;
padding: 20px;
margin-top: -20px;
margin-bottom: -20px;
}
.split-container {
+27
View File
@@ -79,6 +79,33 @@
transition: transform var(--duration-fast) var(--ease-spring);
}
/* Floating corner badges */
.split-badge {
position: absolute;
top: 10px;
font-size: 0.625rem;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
padding: 3px 8px;
border-radius: 3px;
z-index: 5;
pointer-events: none;
}
.split-badge--before {
left: 10px;
color: var(--color-ash);
background: var(--color-paper);
border: 1px solid var(--color-mist);
}
.split-badge--after {
right: 10px;
color: var(--color-paper);
background: var(--color-accent);
}
/* Mobile adjustments */
@media (hover: none) {
.split-container::after {
+26
View File
@@ -58,6 +58,29 @@
.split-label-dot {
transition: transform var(--duration-fast) var(--ease-spring);
}
.split-badge {
position: absolute;
top: 10px;
font-size: 0.625rem;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
padding: 3px 8px;
border-radius: 3px;
z-index: 5;
pointer-events: none;
}
.split-badge--before {
left: 10px;
color: var(--color-ash);
background: var(--color-paper);
border: 1px solid var(--color-mist);
}
.split-badge--after {
right: 10px;
color: var(--color-paper);
background: var(--color-accent);
}
@media (hover: none) {
.split-container::after {
content: '← Swipe →';
@@ -2374,6 +2397,9 @@ code {
width: 100%;
max-width: 600px;
margin: 0 auto;
padding: 20px;
margin-top: -20px;
margin-bottom: -20px;
}
.split-container {
position: relative;
+3 -3
View File
@@ -79,6 +79,7 @@
<div class="split-container">
<!-- Before: AI Slop -->
<div class="split-before">
<span class="split-badge split-badge--before">Before</span>
<div class="slop-card">
<div class="slop-header">
<div class="slop-avatar"></div>
@@ -100,6 +101,7 @@
</div>
<!-- After: Impeccable (shown through split) -->
<div class="split-after">
<span class="split-badge split-badge--after">After</span>
<div class="impeccable-card">
<p class="impeccable-eyebrow">Introducing</p>
<h3 class="impeccable-title">Thoughtful Design</h3>
@@ -108,9 +110,7 @@
</div>
</div>
<!-- The Divider -->
<div class="split-divider">
<span class="split-label">With Skills</span>
</div>
<div class="split-divider"></div>
</div>
<div class="split-labels">
<div class="split-label-item" data-point="before">
+4 -4
View File
@@ -219,8 +219,8 @@ function updateTerminal(cmd, container, allCommands) {
currentSplitInstance = initSplitCompare(splitComparison, {
defaultPosition: 50,
skewOffset: 8,
minPosition: 5,
maxPosition: 95
});
}
}
@@ -330,8 +330,8 @@ function setupMobileInteractions(commands) {
currentSplitInstance = initSplitCompare(splitComparison, {
defaultPosition: 50,
skewOffset: 6,
minPosition: 10,
maxPosition: 90
});
}
});
+1 -3
View File
@@ -6,9 +6,7 @@ export function initLensEffect() {
initSplitCompare(container, {
defaultPosition: 70,
skewOffset: 8,
minPosition: 5,
maxPosition: 95
skewOffset: 8
});
}
+14 -10
View File
@@ -11,8 +11,8 @@ export function initSplitCompare(container, options = {}) {
const {
defaultPosition = 70,
skewOffset = 8,
minPosition = 5,
maxPosition = 95,
minPosition = -skewOffset,
maxPosition = 100 + skewOffset,
lerpSpeed = 0.15,
animationThreshold = 40, // Re-trigger animations when crossing this threshold
onCrossThreshold = null // Callback when crossing threshold toward "after" side
@@ -89,7 +89,8 @@ export function initSplitCompare(container, options = {}) {
function handleMouseMove(e) {
if (isHovering) {
const rect = splitContainer.getBoundingClientRect();
targetX = ((e.clientX - rect.left) / rect.width) * 100;
const range = 100 + 2 * skewOffset;
targetX = ((e.clientX - rect.left) / rect.width) * range - skewOffset;
startAnimation();
}
}
@@ -142,10 +143,13 @@ export function initSplitCompare(container, options = {}) {
}
}
// Attach listeners
splitContainer.addEventListener('mouseenter', handleMouseEnter);
splitContainer.addEventListener('mouseleave', handleMouseLeave);
splitContainer.addEventListener('mousemove', handleMouseMove);
// Use the parent container for mouse events to create a larger hit area
const hitArea = splitContainer.parentElement || splitContainer;
// Attach listeners — mouse events on the wider hit area
hitArea.addEventListener('mouseenter', handleMouseEnter);
hitArea.addEventListener('mouseleave', handleMouseLeave);
hitArea.addEventListener('mousemove', handleMouseMove);
splitContainer.addEventListener('touchstart', handleTouchStart);
splitContainer.addEventListener('touchend', handleTouchEnd);
splitContainer.addEventListener('touchmove', handleTouchMove, { passive: false });
@@ -156,9 +160,9 @@ export function initSplitCompare(container, options = {}) {
// Return cleanup function
return {
destroy() {
splitContainer.removeEventListener('mouseenter', handleMouseEnter);
splitContainer.removeEventListener('mouseleave', handleMouseLeave);
splitContainer.removeEventListener('mousemove', handleMouseMove);
hitArea.removeEventListener('mouseenter', handleMouseEnter);
hitArea.removeEventListener('mouseleave', handleMouseLeave);
hitArea.removeEventListener('mousemove', handleMouseMove);
splitContainer.removeEventListener('touchstart', handleTouchStart);
splitContainer.removeEventListener('touchend', handleTouchEnd);
splitContainer.removeEventListener('touchmove', handleTouchMove);