feat: enhance AppLayout and SequencerPage for improved layout and responsiveness
This commit is contained in:
@@ -24,9 +24,10 @@ interface AppLayoutProps {
|
|||||||
href?: string
|
href?: string
|
||||||
}>
|
}>
|
||||||
}
|
}
|
||||||
|
noPadding?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AppLayout({ children, breadcrumb }: AppLayoutProps) {
|
export function AppLayout({ children, breadcrumb, noPadding = false }: AppLayoutProps) {
|
||||||
const [playerDisplayMode, setPlayerDisplayMode] = useState<PlayerDisplayMode>(
|
const [playerDisplayMode, setPlayerDisplayMode] = useState<PlayerDisplayMode>(
|
||||||
() => {
|
() => {
|
||||||
// Initialize from localStorage or default to 'normal'
|
// Initialize from localStorage or default to 'normal'
|
||||||
@@ -77,7 +78,7 @@ export function AppLayout({ children, breadcrumb }: AppLayoutProps) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div className="flex flex-1 flex-col gap-4 p-4 pt-0">{children}</div>
|
<div className={`flex flex-1 flex-col ${noPadding ? '' : 'gap-4 p-4 pt-0'}`}>{children}</div>
|
||||||
</SidebarInset>
|
</SidebarInset>
|
||||||
<Player onPlayerModeChange={setPlayerDisplayMode} />
|
<Player onPlayerModeChange={setPlayerDisplayMode} />
|
||||||
</SidebarProvider>
|
</SidebarProvider>
|
||||||
|
|||||||
@@ -211,6 +211,7 @@ export const SequencerCanvas = forwardRef<HTMLDivElement, SequencerCanvasProps>(
|
|||||||
}, ref) => {
|
}, ref) => {
|
||||||
const totalWidth = duration * zoom
|
const totalWidth = duration * zoom
|
||||||
const timelineRef = useRef<HTMLDivElement>(null)
|
const timelineRef = useRef<HTMLDivElement>(null)
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
// Add a fallback droppable for the entire canvas area
|
// Add a fallback droppable for the entire canvas area
|
||||||
const { setNodeRef: setCanvasDropRef } = useDroppable({
|
const { setNodeRef: setCanvasDropRef } = useDroppable({
|
||||||
@@ -234,18 +235,18 @@ export const SequencerCanvas = forwardRef<HTMLDivElement, SequencerCanvasProps>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={setCanvasDropRef} className="h-full flex flex-col">
|
<div ref={setCanvasDropRef} className="h-full w-full flex flex-col overflow-hidden">
|
||||||
{/* Time ruler */}
|
{/* Time ruler */}
|
||||||
<div className="h-8 bg-muted/50 border-b border-border/50 flex-shrink-0 overflow-hidden">
|
<div className="h-8 bg-muted/50 border-b border-border/50 flex-shrink-0 overflow-hidden">
|
||||||
<div
|
<div
|
||||||
ref={timelineRef}
|
ref={timelineRef}
|
||||||
className="h-full overflow-x-auto [&::-webkit-scrollbar]:hidden"
|
className="h-full w-full overflow-x-auto [&::-webkit-scrollbar]:hidden"
|
||||||
style={{
|
style={{
|
||||||
scrollbarWidth: 'none',
|
scrollbarWidth: 'none',
|
||||||
msOverflowStyle: 'none'
|
msOverflowStyle: 'none'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="relative h-full" style={{ width: `${totalWidth}px` }}>
|
<div className="relative h-full w-full" style={{ minWidth: `${totalWidth}px` }}>
|
||||||
{Array.from({ length: Math.ceil(duration) + 1 }).map((_, i) => (
|
{Array.from({ length: Math.ceil(duration) + 1 }).map((_, i) => (
|
||||||
<div key={i} className="absolute top-0 bottom-0" style={{ left: `${i * zoom}px` }}>
|
<div key={i} className="absolute top-0 bottom-0" style={{ left: `${i * zoom}px` }}>
|
||||||
{/* Time markers */}
|
{/* Time markers */}
|
||||||
@@ -277,10 +278,10 @@ export const SequencerCanvas = forwardRef<HTMLDivElement, SequencerCanvasProps>(
|
|||||||
{/* Tracks */}
|
{/* Tracks */}
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className="flex-1 min-h-0 min-w-0 overflow-auto"
|
className="flex-1 w-full overflow-auto"
|
||||||
onScroll={handleTracksScroll}
|
onScroll={handleTracksScroll}
|
||||||
>
|
>
|
||||||
<div style={{ width: `${totalWidth}px`, minWidth: `${totalWidth}px`, paddingBottom: '52px' }}>
|
<div style={{ minWidth: `${totalWidth}px`, paddingBottom: '52px' }}>
|
||||||
{tracks.map((track) => (
|
{tracks.map((track) => (
|
||||||
<TrackRow
|
<TrackRow
|
||||||
key={track.id}
|
key={track.id}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { TrackControls } from '@/components/sequencer/TrackControls'
|
|||||||
import { TimelineControls } from '@/components/sequencer/TimelineControls'
|
import { TimelineControls } from '@/components/sequencer/TimelineControls'
|
||||||
import { SoundLibrary } from '@/components/sequencer/SoundLibrary'
|
import { SoundLibrary } from '@/components/sequencer/SoundLibrary'
|
||||||
import { SequencerCanvas } from '@/components/sequencer/SequencerCanvas'
|
import { SequencerCanvas } from '@/components/sequencer/SequencerCanvas'
|
||||||
import { AppLayout } from '@/components/AppLayout'
|
|
||||||
import { DndContext, type DragEndEvent, type DragStartEvent, PointerSensor, useSensors, useSensor } from '@dnd-kit/core'
|
import { DndContext, type DragEndEvent, type DragStartEvent, PointerSensor, useSensors, useSensor } from '@dnd-kit/core'
|
||||||
import { useState, useRef, useCallback, useEffect } from 'react'
|
import { useState, useRef, useCallback, useEffect } from 'react'
|
||||||
|
|
||||||
@@ -285,15 +284,14 @@ export function SequencerPage() {
|
|||||||
}, [state.isPlaying, state.duration])
|
}, [state.isPlaying, state.duration])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<div className="h-screen w-screen flex flex-col overflow-hidden">
|
||||||
breadcrumb={{
|
{/* Simple Header */}
|
||||||
items: [
|
<div className="h-12 bg-background border-b flex items-center px-4 flex-shrink-0">
|
||||||
{ label: 'Home', href: '/' },
|
<a href="/" className="text-sm text-muted-foreground hover:text-foreground">Home</a>
|
||||||
{ label: 'Sequencer' }
|
<span className="mx-2 text-muted-foreground">/</span>
|
||||||
]
|
<span className="text-sm font-medium">Sequencer</span>
|
||||||
}}
|
</div>
|
||||||
>
|
|
||||||
<div className="h-full flex flex-col">
|
|
||||||
{/* Main Content */}
|
{/* Main Content */}
|
||||||
<div className="flex-1 flex overflow-hidden">
|
<div className="flex-1 flex overflow-hidden">
|
||||||
<DndContext
|
<DndContext
|
||||||
@@ -302,7 +300,7 @@ export function SequencerPage() {
|
|||||||
onDragEnd={handleDragEnd}
|
onDragEnd={handleDragEnd}
|
||||||
>
|
>
|
||||||
{/* Left Sidebar - Sound Library */}
|
{/* Left Sidebar - Sound Library */}
|
||||||
<div className="w-80 border-r bg-muted/30 flex flex-col">
|
<div className="w-64 border-r bg-muted/30 flex flex-col flex-shrink-0">
|
||||||
<div className="p-4 h-full">
|
<div className="p-4 h-full">
|
||||||
<SoundLibrary />
|
<SoundLibrary />
|
||||||
</div>
|
</div>
|
||||||
@@ -325,7 +323,7 @@ export function SequencerPage() {
|
|||||||
{/* Track Area */}
|
{/* Track Area */}
|
||||||
<div className="flex-1 flex overflow-hidden">
|
<div className="flex-1 flex overflow-hidden">
|
||||||
{/* Track Controls */}
|
{/* Track Controls */}
|
||||||
<div className="w-40 border-r">
|
<div className="w-32 border-r flex-shrink-0">
|
||||||
<TrackControls
|
<TrackControls
|
||||||
ref={trackControlsRef}
|
ref={trackControlsRef}
|
||||||
tracks={state.tracks}
|
tracks={state.tracks}
|
||||||
@@ -337,7 +335,7 @@ export function SequencerPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Sequencer Canvas */}
|
{/* Sequencer Canvas */}
|
||||||
<div className="flex-1 min-w-0 overflow-hidden">
|
<div className="flex-1 overflow-hidden">
|
||||||
<SequencerCanvas
|
<SequencerCanvas
|
||||||
ref={sequencerCanvasRef}
|
ref={sequencerCanvasRef}
|
||||||
tracks={state.tracks}
|
tracks={state.tracks}
|
||||||
@@ -355,6 +353,5 @@ export function SequencerPage() {
|
|||||||
</DndContext>
|
</DndContext>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</AppLayout>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user