vOOice/MiniRecorder_Morphing_Requirements.md
2025-08-06 23:15:06 +05:45

4.7 KiB
Raw Blame History

MiniRecorder Morphing Window Requirements

🎯 Core Requirements

Visual Behavior

  1. Visualizer Always Centered: The audio visualizer must remain in the exact same position throughout all animations
  2. Fixed Window Position: The MiniRecorderView window position should never change during morphing
  3. Horizontal-Only Expansion: Only width should change, height remains constant at 34px
  4. Hover-Triggered: Expansion should occur on hover, collapse on hover exit

Layout States

Compact State (Default)

  • Width: ~70px (just enough for visualizer + minimal padding)
  • Content: Audio visualizer/status display only
  • Buttons: Hidden/not rendered
  • Centering: Visualizer perfectly centered in compact window

Expanded State (On Hover)

  • Width: ~160px (current full width)
  • Content: RecorderPromptButton + Visualizer + RecorderPowerModeButton
  • Buttons: Fully visible and functional
  • Centering: Visualizer remains in same absolute screen position

🔧 Technical Constraints

Window Positioning

  • Window's center point must remain constant
  • When expanding from 70px → 160px, window should grow equally left and right (45px each side)
  • NSRect calculations must account for center-anchored growth

Animation Requirements

  • Smooth spring animation (~0.3-0.4s duration)
  • Buttons should appear/disappear gracefully (fade in/out or slide from edges)
  • No jarring movements or position jumps
  • Reversible animation (expand ↔ collapse)

SwiftUI Layout Considerations

  • HStack with conditional button rendering
  • Visualizer maintains frame(maxWidth: .infinity) behavior in both states
  • Proper spacing and padding calculations for both states

Approach: Center-Anchored Window Growth with Sliding Buttons

Window Management (MiniRecorderPanel)

Compact Window Rect:
- Width: 70px
- Height: 34px  
- X: screenCenter - 35px
- Y: current Y position

Expanded Window Rect:
- Width: 160px
- Height: 34px
- X: screenCenter - 80px  // Grows left by 45px
- Y: same Y position      // Grows right by 45px

SwiftUI Layout (MiniRecorderView)

HStack(spacing: 0) {
    // Left button - slides in from left edge
    if isExpanded {
        RecorderPromptButton()
            .transition(.move(edge: .leading).combined(with: .opacity))
    }
    
    // Visualizer - always centered, never moves
    statusView
        .frame(width: visualizerWidth) // Fixed width
    
    // Right button - slides in from right edge  
    if isExpanded {
        RecorderPowerModeButton()
            .transition(.move(edge: .trailing).combined(with: .opacity))
    }
}

State Management

  • @State private var isExpanded = false
  • @State private var isHovering = false
  • Hover detection with debouncing for smooth UX
  • Window resize triggered by state changes

🎨 Animation Sequence

Expansion (Compact → Expanded)

  1. Trigger: Mouse enters window bounds
  2. Window: Animate width 70px → 160px (center-anchored)
  3. Buttons: Slide in from edges with fade-in
  4. Duration: ~0.3s with spring easing
  5. Result: Visualizer appears unmoved, buttons visible

Collapse (Expanded → Compact)

  1. Trigger: Mouse leaves window bounds (with delay)
  2. Buttons: Slide out to edges with fade-out
  3. Window: Animate width 160px → 70px (center-anchored)
  4. Duration: ~0.3s with spring easing
  5. Result: Back to visualizer-only, same position

🚫 Critical Don'ts

  • Never move the visualizer's absolute screen position
  • Never change the window's center point
  • Never animate height or vertical position
  • Never show jarring button pop-ins (use smooth transitions)
  • Never let buttons overlap the visualizer during animation

📐 Calculations

Visualizer Dimensions

  • AudioVisualizer: 12 bars × 3px + 11 × 2px spacing = 58px width
  • With padding: ~70px total compact width

Button Dimensions

  • Each button: ~24px width + padding
  • Total button space: ~90px (45px per side)
  • Total expanded width: 70px + 90px = 160px

Center-Anchored Growth

Compact X position: screenCenterX - 35px
Expanded X position: screenCenterX - 80px
Growth: 45px left + 45px right = 90px total

🎯 Success Criteria

Visualizer never visually moves during any animation
Window position anchor point remains constant
Smooth hover-based expansion/collapse
Buttons appear/disappear gracefully
No layout jumps or glitches
Maintains current functionality in expanded state

This approach ensures the visualizer appears completely stationary while the window "grows around it" to reveal the buttons, creating a seamless morphing effect.