From b1c0ff6f721a48bb95972a55ee8907a72e0c0834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kr=C3=BCger?= Date: Wed, 19 Nov 2025 18:15:27 +0100 Subject: [PATCH] fix: constrain fader handles to track lane boundaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fader handles now respect top-8 bottom-8 track padding - Handle moves only within the visible track lane (60% range) - Updated both TrackFader and MasterFader components - Value calculation clamped to track bounds (32px padding top/bottom) - Handle position mapped to 20%-80% range instead of 0%-100% - Prevents handle from going beyond visible track area 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- components/controls/MasterFader.tsx | 19 +++++++++++++++---- components/tracks/TrackFader.tsx | 19 +++++++++++++++---- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/components/controls/MasterFader.tsx b/components/controls/MasterFader.tsx index 91d95b2..0d1bb25 100644 --- a/components/controls/MasterFader.tsx +++ b/components/controls/MasterFader.tsx @@ -91,9 +91,18 @@ export function MasterFader({ const rect = containerRef.current.getBoundingClientRect(); const y = clientY - rect.top; + + // Track has 32px (2rem) padding on top and bottom (top-8 bottom-8) + const trackPadding = 32; + const trackHeight = rect.height - (trackPadding * 2); + + // Clamp y to track bounds + const clampedY = Math.max(trackPadding, Math.min(rect.height - trackPadding, y)); + // Inverted: top = max (1), bottom = min (0) - const percentage = Math.max(0, Math.min(1, 1 - (y / rect.height))); - onChange(percentage); + // Map clampedY from [trackPadding, height-trackPadding] to [1, 0] + const percentage = 1 - ((clampedY - trackPadding) / trackHeight); + onChange(Math.max(0, Math.min(1, percentage))); }; React.useEffect(() => { @@ -165,8 +174,10 @@ export function MasterFader({
{/* Handle grip lines */} diff --git a/components/tracks/TrackFader.tsx b/components/tracks/TrackFader.tsx index a5d5d07..3d8be93 100644 --- a/components/tracks/TrackFader.tsx +++ b/components/tracks/TrackFader.tsx @@ -87,9 +87,18 @@ export function TrackFader({ const rect = containerRef.current.getBoundingClientRect(); const y = clientY - rect.top; + + // Track has 32px (2rem) padding on top and bottom (top-8 bottom-8) + const trackPadding = 32; + const trackHeight = rect.height - (trackPadding * 2); + + // Clamp y to track bounds + const clampedY = Math.max(trackPadding, Math.min(rect.height - trackPadding, y)); + // Inverted: top = max (1), bottom = min (0) - const percentage = Math.max(0, Math.min(1, 1 - (y / rect.height))); - onChange(percentage); + // Map clampedY from [trackPadding, height-trackPadding] to [1, 0] + const percentage = 1 - ((clampedY - trackPadding) / trackHeight); + onChange(Math.max(0, Math.min(1, percentage))); }; React.useEffect(() => { @@ -161,8 +170,10 @@ export function TrackFader({
{/* Handle grip lines */}