feat: Ableton Live-style effects and complete automation system
Enhanced visual design: - Improved device rack container with darker background and inner shadow - Device cards now have rounded corners, shadows, and colored indicators - Better visual separation between enabled/disabled effects - Active devices highlighted with accent border Complete automation infrastructure (Phase 9): - Created comprehensive type system for automation lanes and points - Implemented AutomationPoint component with drag-and-drop editing - Implemented AutomationHeader with mode controls (Read/Write/Touch/Latch) - Implemented AutomationLane with canvas-based curve rendering - Integrated automation lanes into Track component below effects - Created automation playback engine with real-time interpolation - Added automation data persistence to localStorage Automation features: - Add/remove automation points by clicking/double-clicking - Drag points to change time and value - Multiple automation modes (Read, Write, Touch, Latch) - Linear and step curve types (bezier planned) - Adjustable lane height (60-180px) - Show/hide automation per lane - Real-time value display at playhead - Color-coded lanes by parameter type - Keyboard delete support (Delete/Backspace) Track type updates: - Added automation field to Track interface - Updated track creation to initialize empty automation - Updated localStorage save/load to include automation data Files created: - components/automation/AutomationPoint.tsx - components/automation/AutomationHeader.tsx - components/automation/AutomationLane.tsx - lib/audio/automation/utils.ts (helper functions) - lib/audio/automation/playback.ts (playback engine) - types/automation.ts (complete type system) Files modified: - components/effects/EffectDevice.tsx (Ableton-style visual improvements) - components/tracks/Track.tsx (automation lanes integration) - types/track.ts (automation field added) - lib/audio/track-utils.ts (automation initialization) - lib/hooks/useMultiTrack.ts (automation persistence) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -25,40 +25,50 @@ export function EffectDevice({
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex-shrink-0 flex flex-col h-full border-l border-border transition-all duration-200',
|
||||
effect.enabled ? 'bg-accent/20' : 'bg-muted/20',
|
||||
'flex-shrink-0 flex flex-col h-full transition-all duration-200 rounded-md overflow-hidden',
|
||||
effect.enabled
|
||||
? 'bg-card border border-border/50 shadow-md'
|
||||
: 'bg-card/40 border border-border/30 shadow-sm opacity-60',
|
||||
isExpanded ? 'min-w-96' : 'w-10'
|
||||
)}
|
||||
>
|
||||
{!isExpanded ? (
|
||||
/* Collapsed State - No Header */
|
||||
<button
|
||||
onClick={() => setIsExpanded(true)}
|
||||
className="w-full h-full flex flex-col items-center justify-between py-1 hover:bg-primary/10 transition-colors group"
|
||||
title={`Expand ${effect.name}`}
|
||||
>
|
||||
<ChevronRight className="h-3 w-3 flex-shrink-0 text-muted-foreground group-hover:text-primary transition-colors" />
|
||||
<span
|
||||
className="flex-1 text-xs font-medium whitespace-nowrap text-muted-foreground group-hover:text-primary transition-colors"
|
||||
style={{
|
||||
writingMode: 'vertical-rl',
|
||||
textOrientation: 'mixed',
|
||||
}}
|
||||
/* Collapsed State */
|
||||
<>
|
||||
{/* Colored top indicator */}
|
||||
<div className={cn('h-0.5 w-full', effect.enabled ? 'bg-primary' : 'bg-muted-foreground/20')} />
|
||||
|
||||
<button
|
||||
onClick={() => setIsExpanded(true)}
|
||||
className="w-full h-full flex flex-col items-center justify-between py-1 hover:bg-primary/10 transition-colors group"
|
||||
title={`Expand ${effect.name}`}
|
||||
>
|
||||
{effect.name}
|
||||
</span>
|
||||
<div
|
||||
className={cn(
|
||||
'w-1 h-1 rounded-full flex-shrink-0 mb-1',
|
||||
effect.enabled ? 'bg-primary' : 'bg-muted-foreground/30'
|
||||
)}
|
||||
title={effect.enabled ? 'Enabled' : 'Disabled'}
|
||||
/>
|
||||
</button>
|
||||
<ChevronRight className="h-3 w-3 flex-shrink-0 text-muted-foreground group-hover:text-primary transition-colors" />
|
||||
<span
|
||||
className="flex-1 text-xs font-medium whitespace-nowrap text-muted-foreground group-hover:text-primary transition-colors"
|
||||
style={{
|
||||
writingMode: 'vertical-rl',
|
||||
textOrientation: 'mixed',
|
||||
}}
|
||||
>
|
||||
{effect.name}
|
||||
</span>
|
||||
<div
|
||||
className={cn(
|
||||
'w-1.5 h-1.5 rounded-full flex-shrink-0 mb-1',
|
||||
effect.enabled ? 'bg-primary shadow-sm shadow-primary/50' : 'bg-muted-foreground/30'
|
||||
)}
|
||||
title={effect.enabled ? 'Enabled' : 'Disabled'}
|
||||
/>
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{/* Colored top indicator */}
|
||||
<div className={cn('h-0.5 w-full', effect.enabled ? 'bg-primary' : 'bg-muted-foreground/20')} />
|
||||
|
||||
{/* Full-Width Header Row */}
|
||||
<div className="flex items-center gap-1 px-2 py-1 border-b border-border bg-card/30 flex-shrink-0">
|
||||
<div className="flex items-center gap-1 px-2 py-1.5 border-b border-border/50 bg-muted/30 flex-shrink-0">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
@@ -95,7 +105,7 @@ export function EffectDevice({
|
||||
</div>
|
||||
|
||||
{/* Device Body */}
|
||||
<div className="flex-1 min-h-0 overflow-y-auto custom-scrollbar p-2">
|
||||
<div className="flex-1 min-h-0 overflow-y-auto custom-scrollbar p-3 bg-card/50">
|
||||
<EffectParameters effect={effect} onUpdateParameters={onUpdateParameters} />
|
||||
</div>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user