- 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>
- Plus button now conditionally rendered based on track.effectsExpanded
- Matches automation controls behavior
- Cleaner UI when panel is collapsed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added EffectBrowser import and state management
- Plus button opens dialog to select from all available effects
- Effect is added to track when selected from browser
- Removed hardcoded low-pass filter addition
- Better UX for adding effects to tracks
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Removed absolute positioning from eye icon button
- Added Plus button to add effects (currently adds low-pass filter)
- All controls now properly inline in normal flex flow
- Eye button correctly positioned at end without overlap
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Removed absolute positioning from eye icon button
- Made all controls part of normal flex flow
- Eye button now correctly positioned at end without overlap
- Chevron controls no longer overlay the eye icon
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Streamlined track controls and master controls to same width (240px)
- Fixed track controls container to use full width of parent column
- Matched TrackControls card structure with MasterControls (gap-3, no w-full/h-full)
- Updated outer container padding from p-2 to p-4 with gap-4
- Adjusted track controls wrapper to center content instead of stretching
- Added max-width constraint to PlaybackControls to prevent width changes
- Centered transport control buttons in footer
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Import cn utility function from @/lib/utils/cn
- Fixes ReferenceError: cn is not defined
- Required for conditional classNames on effect labels
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Effect labels show in primary color when enabled
- Effect labels show in gray when bypassed/disabled
- Added opacity reduction (60%) for bypassed effects
- Visual feedback matches effect state at a glance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Display effect names as small chips/badges in effects header
- Shows all effect names at a glance without expanding
- Styled with primary color background and border
- Horizontal scrollable if many effects
- Visible whether effects rack is expanded or collapsed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove '(N)' count display from effects bar header
- Effect names are already shown in EffectDevice component:
- Collapsed: vertical text label
- Expanded: header with full name
- Cleaner header appearance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace ChevronDown/ChevronRight with Eye/EyeOff icons
- Position eye icon absolutely on the right side
- Match AutomationHeader styling with bg-muted/50 and border
- Eye icon shows when expanded, EyeOff when collapsed
- Consistent UX between automation and effects bars
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Track component now uses Math.max to ensure track.height is at least MIN_TRACK_HEIGHT
- TrackList component also uses Math.max for consistent enforcement
- Fixes issue where tracks with old height values (340px, 357px) were smaller
- All tracks now guaranteed to be exactly 360px regardless of stored height
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Import DEFAULT_TRACK_HEIGHT and COLLAPSED_TRACK_HEIGHT from types
- Use DEFAULT_TRACK_HEIGHT (340px) instead of hardcoded 240px fallback
- Ensures all tracks have the same height as the first track
- Matches the height used when creating tracks
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove fixed height from Track waveformOnly mode
- Use h-full class to fill flex container instead
- Allows parent scroll container to show horizontal scrollbar based on zoom
- Waveform now properly expands horizontally without clipping
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove h-32 wrapper div around AutomationLane
- AutomationLane now uses its own height (lane.height, defaults to 80px)
- Automation controls (canvas, points) now visible and interactive
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Track container now has fixed height (240px default or track.height)
- Waveform uses flex-1 to take remaining space
- Automation and effects bars use flex-shrink-0 for fixed height
- When bars expand, waveform shrinks instead of container growing
- Matches DAW behavior where track height stays constant
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace absolute positioning with flex column layout
- Waveform, automation bar, and effects bar now stacked vertically
- Removes gaps between bars naturally with stacked layout
- Both bars remain collapsible with no position dependencies
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Removed border-t from effects bar container
- Keeps border-b for bottom edge separation
- No gap between automation and effects bars in both folded and unfolded states
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Default selectedParameterId to 'volume' when undefined
- Fixes issue where clicking automation header did nothing
- Chevron now correctly shows fold/unfold state
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Sparkles icon import to TrackExtensions
- Remove invalid props from AutomationLane (trackId, isPlaying, onSeek)
- Fix createAutomationPoint call to use object parameter with curve property
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed issues:
1. Made automation bar collapsible with chevron indicator
2. Removed border-t from automation lane container (no gap to effects)
3. Restored lane.visible filter so AutomationLane properly renders with controls
The AutomationLane component has all the rich editing UI:
- Click canvas to add automation points
- Drag points to move them
- Double-click to delete points
- Keyboard delete (Del/Backspace) for selected points
- Visual feedback with selected state
All controls are intact and functional when automation bar is expanded.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed all three issues:
1. Removed automation (A) and effects (E) toggle buttons from TrackControls
2. Made automation bar always expanded and non-collapsible
3. Added bottom border to effects bar (border-b)
Changes:
- TrackControls.tsx: Removed entire Row 2 (A/E buttons section)
- TrackList.tsx: Removed click handler and chevron from automation header
- TrackList.tsx: Automation lane always visible (no conditional rendering)
- TrackList.tsx: Added border-b to effects bar container
- TrackList.tsx: Added border-b to automation bar for visual consistency
Bars are now permanent, always-visible UI elements at the bottom of tracks.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major improvements to automation and effects bars:
- Both bars now positioned at bottom of waveform (not top)
- Bars are always visible when track is expanded (no show/hide buttons)
- Effects bar at absolute bottom
- Automation bar above effects, dynamically positioned based on effects state
- Removed inner container from effects - direct rendering with EffectDevice
- Removed close buttons (X icons) - bars are permanent
- Effects render directly with gap-3 padding, no TrackExtensions wrapper
- Automation controls preserved (AutomationLane unchanged)
This creates a cleaner, always-accessible interface where users can quickly
expand/collapse automation or effects without toggling visibility.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes automation and effects from card-based overlays to integrated bars:
- Automation bar positioned at absolute top with no margins/padding
- Effects bar positioned below automation or at top if automation hidden
- Both bars use bg-card/90 backdrop-blur-sm for subtle transparency
- Collapsible with ChevronDown/ChevronRight indicators
- Close button (X icon) on each bar
- Effects bar dynamically positions based on automation state
- Added effectsExpanded property to Track type
- Removed card container styling for cleaner integration
The bars now sit directly on the waveform as requested, making them feel
more integrated into the track view rather than floating overlays.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes to automation and effects overlays:
- Reduced backdrop opacity from bg-black/60 to bg-black/30 (less dark)
- Added header to automation overlay with parameter name display
- Added close button to automation overlay (ChevronDown icon)
- Wrapped automation lane in rounded card with border and shadow
- Both overlays now have consistent visual styling
- Added ChevronDown import to TrackList
This makes the overlays less obtrusive and adds proper controls for closing
the automation view, matching the effects overlay pattern.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Automation lanes and effects now render as overlays on top of the waveform
instead of below the track, solving both visibility and layout proportion issues.
Changes:
- Wrapped Track waveforms in relative container for overlay positioning
- Automation lanes render with bg-black/60 backdrop-blur overlay
- Effects render with TrackExtensions in overlay mode (asOverlay prop)
- Added overlay-specific rendering with close button and better empty state
- Both overlays use absolute positioning with z-10 for proper stacking
- Eliminated height mismatch between controls and waveform areas
This approach provides better visual integration and eliminates the need
to match heights between the two-column layout.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed multiple issues with the track layout system:
1. Effect cards now expandable/collapsible
- Added onToggleExpanded callback to EffectDevice
- Effect expansion state is properly toggled and persisted
2. Removed left column spacers causing misalignment
- Removed automation lane spacer (h-32)
- Removed effects section spacer (h-64/h-8)
- Automation lanes and effects now only in waveform column
- This eliminates the height mismatch between columns
3. Layout now cleaner
- Left column stays fixed with only track controls
- Right column contains waveforms, automation, and effects
- No artificial spacers needed for alignment
The automation lanes and effects sections now appear properly in the
waveform area without creating alignment issues in the controls column.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed critical bug where ImportDialog was always rendered regardless of
the open prop value. The component interface didn't match the actual
implementation, causing it to appear on page load.
Changes:
- Added `open` prop to ImportDialogProps interface
- Added early return when `open` is false to prevent rendering
- Renamed `onCancel` to `onClose` to match Track component usage
- Made fileName, sampleRate, and channels optional props
- Dialog now only appears when explicitly opened by user action
This fixes the issue where the dialog appeared immediately on page load
when loading a saved project.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added padding around effects device rack and gap between effect cards
for better visual integration and spacing.
Changes:
- Added p-3 padding to effects rack container
- Added gap-3 between effect device cards
- Improves visual consistency and readability
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed issue where ImportDialog was being rendered for each track in
waveform mode, causing multiple unclosable dialogs to appear on page load.
Changes:
- Moved ImportDialog to renderControlsOnly mode only
- Each track now has exactly one ImportDialog (rendered in controls column)
- Removed duplicate ImportDialog from renderWaveformOnly mode
- Removed ImportDialog from fallback return statement
This ensures only one dialog appears per track, making it properly closable.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Restored the automation lane and effects sections that were removed during
the Track component refactoring. These sections now render as full-width
rows below each track, spanning across both the controls and waveforms columns.
Changes:
- Created TrackExtensions component for effects section rendering
- Added automation lane rendering in TrackList after each track waveform
- Added placeholder spacers in left controls column to maintain alignment
- Effects section shows collapsible device rack with mini preview when collapsed
- Automation lanes render when track.automation.showAutomation is true
- Import dialog moved to waveform-only rendering mode
The automation and effects sections are now properly unfoldable again.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added back the right border on the track controls column to visually
separate the controls from the waveform area.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added pb-3 (padding-bottom) to the track controls column to account
for the horizontal scrollbar height in the waveforms column, ensuring
track controls stay perfectly aligned with their waveforms.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Track controls now stay perfectly aligned with their waveforms during
vertical scrolling. The waveform column handles all scrolling (both
horizontal and vertical), and synchronizes its vertical scroll position
to the controls column.
Changes:
- Removed independent vertical scroll from controls column
- Added scroll event handler to waveforms column
- Controls column scrollTop is synced with waveforms column
- Track controls and waveforms now stay aligned at all times
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed React Hooks error by moving waveformScrollRef declaration
before the conditional early return. Hooks must always be called
in the same order on every render.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Refactored track layout to use a two-column design where:
- Left column: All track control panels (fixed, vertical scroll)
- Right column: All waveforms (shared horizontal scroll container)
This ensures all track waveforms scroll together horizontally when
zoomed in, providing a more cohesive DAW-like experience.
Changes:
- Added renderControlsOnly and renderWaveformOnly props to Track component
- Track component now supports conditional rendering of just controls or just waveform
- TrackList renders each track twice: once for controls, once for waveforms
- Waveforms share a common scrollable container for synchronized scrolling
- Track controls stay fixed while waveforms scroll horizontally together
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Modified the waveform minWidth calculation to only apply when
zoom > 1, so the waveform fills the available viewport space
at default zoom level instead of creating unnecessary horizontal
scrolling.
Changes:
- minWidth only applied when zoom > 1
- At zoom = 1.0, waveform takes 100% of available space
- Scrollbar only appears when actually zoomed in
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed horizontal scrollbar implementation to only scroll the waveform
content area while keeping track controls fixed in the viewport.
Changes:
- Wrapped waveform content in a scrollable container with overflow-x-auto
- Moved minWidth calculation to inner container
- Track controls now stay fixed at 192px width
- No scrollbar appears on initial track load
- Scrollbar only appears when zooming extends content beyond viewport
Resolves issue where entire track row (including controls) was
scrolling out of view when zoomed in.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added all remaining keyboard shortcuts for a complete keyboard-driven workflow:
Playback Shortcuts:
- Home: Jump to start
- End: Jump to end
- Left/Right Arrow: Seek ±1 second
- Ctrl+Left/Right: Seek ±5 seconds
Editing Shortcuts:
- Ctrl+A: Select All (entire track content)
View Shortcuts:
- Ctrl+Plus/Equals: Zoom in
- Ctrl+Minus: Zoom out
- Ctrl+0: Fit to view
All shortcuts work seamlessly with existing shortcuts:
- Spacebar: Play/Pause
- Ctrl+Z/Y: Undo/Redo
- Ctrl+X/C/V: Cut/Copy/Paste
- Ctrl+S: Save
- Ctrl+D: Duplicate
- Delete/Backspace: Delete
- Escape: Clear selection
The editor is now fully controllable via keyboard for a professional
audio editing workflow similar to Audacity/Reaper.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed from single JSON file to ZIP archive format to avoid string
length limits when serializing large audio buffers.
New ZIP structure:
- project.json (metadata, track info, effects, automation)
- track_0.wav, track_1.wav, etc. (audio files in WAV format)
Benefits:
- No more RangeError: Invalid string length
- Smaller file sizes (WAV compression vs base64 JSON)
- Human-readable audio files in standard format
- Can extract and inspect individual tracks
- Easier to edit/debug project metadata
Added jszip dependency for ZIP file handling.
Changed file picker to accept .zip files.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added full export/import functionality for projects:
Export Features:
- Export button for each project in Projects dialog
- Downloads project as JSON file with all data
- Includes tracks, audio buffers, effects, automation, settings
- Filename format: {project_name}_{timestamp}.json
Import Features:
- Import button in Projects dialog header
- File picker for .json files
- Automatically generates new project ID to avoid conflicts
- Appends "(Imported)" to project name
- Preserves all project data
This enables:
- Backup of projects outside the browser
- Sharing projects with collaborators
- Migration between computers/browsers
- Version snapshots at different stages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- Modified handleSaveProject to accept showToast parameter (default: false)
- Auto-saves now run silently without toast notifications
- Added Ctrl+S / Cmd+S keyboard shortcut for manual save with toast
- Added "Save Project" and "Open Projects" to command palette
- Error toasts still shown for all save failures
This provides the best of both worlds:
- Automatic background saves don't interrupt the user
- Manual saves (Ctrl+S or command palette) provide confirmation
- Users can work without being constantly notified
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The handleSaveProject callback had currentTime in its dependencies, which
caused the callback to be recreated on every playback frame update. This
made the auto-save effect reset its timer constantly, preventing auto-save
from ever triggering.
Solution: Use a ref to capture the latest currentTime value without
including it in the callback dependencies. This keeps the callback stable
while still saving the correct currentTime.
Added debug logging to track auto-save scheduling and triggering.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**useMultiTrack.ts:**
- Removed localStorage persistence (tracks, effects, automation)
- Now relies entirely on IndexedDB via project management system
- Simpler state management without dual persistence
**AudioEditor.tsx:**
- Store last project ID in localStorage when saving
- Auto-load last project on page mount
- Only runs once per session with hasAutoLoaded flag
- Falls back to empty state if project can't be loaded
**Benefits:**
- No more conflicts between localStorage and IndexedDB
- Effects and automation properly persisted
- Seamless experience - reload page and your project is ready
- Single source of truth (IndexedDB)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>