feat: smooth analog zoom with solid blue hover

UX improvements for more responsive, fluid zoom experience:

1. Smooth analog response:
   - Removed 50ms debounce - applies zoom immediately
   - Changed step from 5 to 1 for ultra-smooth increments
   - Updated transition: 0.08s linear (was 0.3s cubic-bezier)
   - Real-time transform updates for analog feel vs digital jumps

2. Solid blue hover (no gradient):
   - Changed from multi-color gradient to solid #3b82f6 blue
   - Maintains gray when not hovering
   - Clean, simple visual feedback matching reference design

3. Visual enhancement:
   - Keyboard shortcuts now use step 10 for faster adjustments
   - Instant response eliminates "digital" feeling
   - Smooth, continuous zoom matching analog controls

Technical changes:
- HTML: step="1" instead of step="5"
- CSS: solid color hover, 0.08s linear transition
- JS: removed debounce timeout, immediate applyZoom()
This commit is contained in:
juanatsap
2025-11-12 11:46:19 +00:00
parent b6aeb697fe
commit c1506a4d1e
3 changed files with 11 additions and 27 deletions
+5 -15
View File
@@ -552,7 +552,7 @@ iconify-icon {
/* Zoom transform properties */ /* Zoom transform properties */
transform-origin: top center; /* Scale from top-center to maintain header alignment */ transform-origin: top center; /* Scale from top-center to maintain header alignment */
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); /* Smooth material-design easing */ transition: transform 0.08s linear; /* Immediate, smooth analog response */
will-change: transform; /* Hint browser to optimize for transforms */ will-change: transform; /* Hint browser to optimize for transforms */
} }
@@ -3521,15 +3521,10 @@ html {
transition: all 0.3s ease; transition: all 0.3s ease;
} }
/* Colorful gradient on hover */ /* Solid blue color on hover - no gradient */
.zoom-control:hover .zoom-slider, .zoom-control:hover .zoom-slider,
.zoom-slider:hover { .zoom-slider:hover {
background: linear-gradient(to right, background: #3b82f6; /* solid blue */
#ef4444 0%, /* red */
#f97316 25%, /* orange */
#3b82f6 50%, /* blue */
#22c55e 100% /* green */
);
} }
.zoom-slider:focus { .zoom-slider:focus {
@@ -3591,15 +3586,10 @@ html {
transition: all 0.3s ease; transition: all 0.3s ease;
} }
/* Firefox Range Track - Colorful on hover */ /* Firefox Range Track - Solid blue on hover */
.zoom-control:hover .zoom-slider::-moz-range-track, .zoom-control:hover .zoom-slider::-moz-range-track,
.zoom-slider:hover::-moz-range-track { .zoom-slider:hover::-moz-range-track {
background: linear-gradient(to right, background: #3b82f6; /* solid blue */
#ef4444 0%, /* red */
#f97316 25%, /* orange */
#3b82f6 50%, /* blue */
#22c55e 100% /* green */
);
} }
/* Reset Button - Circular with dynamic value inside */ /* Reset Button - Circular with dynamic value inside */
+5 -11
View File
@@ -277,19 +277,13 @@
applyZoom(zoomValue, false); // false = don't save (already loaded from storage) applyZoom(zoomValue, false); // false = don't save (already loaded from storage)
} }
// Real-time slider updates with debouncing for performance // Real-time slider updates - immediate, smooth analog experience
let zoomTimeout;
slider.addEventListener('input', function(e) { slider.addEventListener('input', function(e) {
const zoomValue = parseInt(e.target.value, 10); const zoomValue = parseInt(e.target.value, 10);
// Update ARIA and display immediately (no debounce) // Apply zoom and update display immediately for smooth analog feel
updateZoomDisplay(zoomValue); updateZoomDisplay(zoomValue);
applyZoom(zoomValue, true);
// Debounce the actual transform application (smoother on slower devices)
clearTimeout(zoomTimeout);
zoomTimeout = setTimeout(() => {
applyZoom(zoomValue, true);
}, 50); // 50ms debounce
}); });
// Reset button // Reset button
@@ -306,10 +300,10 @@
if ((e.ctrlKey || e.metaKey) && !e.shiftKey) { if ((e.ctrlKey || e.metaKey) && !e.shiftKey) {
if (e.key === '=' || e.key === '+') { if (e.key === '=' || e.key === '+') {
e.preventDefault(); e.preventDefault();
incrementZoom(5); incrementZoom(10);
} else if (e.key === '-') { } else if (e.key === '-') {
e.preventDefault(); e.preventDefault();
incrementZoom(-5); incrementZoom(-10);
} else if (e.key === '0') { } else if (e.key === '0') {
e.preventDefault(); e.preventDefault();
slider.value = 100; slider.value = 100;
+1 -1
View File
@@ -464,7 +464,7 @@
class="zoom-slider" class="zoom-slider"
min="50" min="50"
max="200" max="200"
step="5" step="1"
value="100" value="100"
aria-label="{{if eq .Lang "es"}}Ajustar nivel de zoom del CV{{else}}Adjust CV zoom level{{end}}" aria-label="{{if eq .Lang "es"}}Ajustar nivel de zoom del CV{{else}}Adjust CV zoom level{{end}}"
aria-valuemin="50" aria-valuemin="50"