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

140 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
## 💡 Recommended Implementation Strategy
### **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.