fix: constrain fader handles to track lane boundaries
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -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({
|
||||
<div
|
||||
className="absolute left-1/2 -translate-x-1/2 w-10 h-4 bg-primary/80 border-2 border-primary rounded-md shadow-lg cursor-grab active:cursor-grabbing pointer-events-none transition-all"
|
||||
style={{
|
||||
// Inverted: value 1 = top, value 0 = bottom
|
||||
top: `calc(${(1 - value) * 100}% - 0.5rem)`,
|
||||
// Inverted: value 1 = top of track (20%), value 0 = bottom of track (80%)
|
||||
// Track has top-8 bottom-8 padding (20% and 80% of h-40 container)
|
||||
// Handle moves within 60% range (from 20% to 80%)
|
||||
top: `calc(${20 + (1 - value) * 60}% - 0.5rem)`,
|
||||
}}
|
||||
>
|
||||
{/* Handle grip lines */}
|
||||
|
||||
@@ -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({
|
||||
<div
|
||||
className="absolute left-1/2 -translate-x-1/2 w-10 h-4 bg-primary/80 border-2 border-primary rounded-md shadow-lg cursor-grab active:cursor-grabbing pointer-events-none transition-all"
|
||||
style={{
|
||||
// Inverted: value 1 = top, value 0 = bottom
|
||||
top: `calc(${(1 - value) * 100}% - 0.5rem)`,
|
||||
// Inverted: value 1 = top of track (20%), value 0 = bottom of track (80%)
|
||||
// Track has top-8 bottom-8 padding (20% and 80% of h-40 container)
|
||||
// Handle moves within 60% range (from 20% to 80%)
|
||||
top: `calc(${20 + (1 - value) * 60}% - 0.5rem)`,
|
||||
}}
|
||||
>
|
||||
{/* Handle grip lines */}
|
||||
|
||||
Reference in New Issue
Block a user