333 lines
13 KiB
Markdown
333 lines
13 KiB
Markdown
|
|
# DAW UI LAYOUT & PANEL SYSTEM ARCHITECTURE
|
|
|
|
This document details the interface layout solution (UI Layout Architecture), HTML/CSS structure, and interaction algorithms (Resizing, Scrolling) for a Hybrid DAW system, supporting responsive flexible scaling across Panels and the bottom dock strip.
|
|
|
|
---
|
|
|
|
## 1. Overall Layout Diagram (Grid Structure)
|
|
|
|
The application interface is structured around 3 main axes following an App Shell model (`Viewport Locked 100vh`):
|
|
|
|
```text
|
|
┌──────────────────────────────────────────────────────────────────────────────────┐
|
|
│ Top Navigation & Transport Toolbar (Fixed Top Bar) │
|
|
├───────────────────────────────────────────────────────────┬──────────────────────┤
|
|
│ │ RIGHT COLUMN │
|
|
│ MAIN WORKSPACE │ (RIGHT SIDEBAR) │
|
|
│ ┌───────────────────────┬───────────────────────────────┐ │ ┌──────────────────┐ │
|
|
│ │ Track Control Panels │ Timeline / Audio Viewport │ │ │ Media Explorer │ │
|
|
│ │ (Track List) │ (Beat Grid & Waveforms) │ │ │ (Dynamic Height) │ │
|
|
│ │ │ │ │ ├──────────────────┤ │
|
|
│ │ │ │ │ │ AI Panel │ │
|
|
│ │ │ │ │ │ (Dynamic Height) │ │
|
|
│ └───────────────────────┴───────────────────────────────┘ │ └──────────────────┘ │
|
|
├───────────────────────────────────────────────────────────┴──────────────────────┤
|
|
│ BOTTOM DOCK PANEL STRIP - Horizontal Scroll (Overflow-X Auto) │
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
│ │ Export Panel │ │ DSP Tools │ │ Panel 03 │ │ Panel 04... │ ──────► │
|
|
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
├──────────────────────────────────────────────────────────────────────────────────┤
|
|
│ Status Bar (Fixed Bottom Status) │
|
|
└──────────────────────────────────────────────────────────────────────────────────┘
|
|
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Layout Region Details
|
|
|
|
### A. Main Workspace (Center Region)
|
|
|
|
* **Function:** Contains the track list (Track Controls), timeline ruler (Timeline Ruler), and audio/MIDI display areas (Audio Waveform & Piano Roll Clip Grid).
|
|
* **Behavior:** Auto-expands (`flex-grow: 1`) to fill the remaining screen space after subtracting the width of the Right Sidebar and the height of the Bottom Panel.
|
|
|
|
### B. Bottom Panel Dock Strip (Bottom Row)
|
|
|
|
* **Technical Specifications:**
|
|
* **Flexible Horizontal Scroll:** The container has a fixed height (e.g., `220px`), using `overflow-x: auto` and `display: flex`.
|
|
* **Sub-Panels:** Houses a list of independent Card/Tile tools (Export Panel, Python DSP Tools Panel, Selection Panel, FX Panel, etc.).
|
|
* **No Shrinking (`flex-shrink: 0`):** Each Sub-Panel is configured with `flex-shrink: 0` and a minimum width (`min-width: 280px - 350px`). When the combined width of all panels exceeds the screen width, a horizontal scrollbar appears automatically.
|
|
|
|
|
|
|
|
### C. Right Resizable Sidebar (Multi-Panel Right Column)
|
|
|
|
* **Technical Specifications:**
|
|
* **Width Resizing:** The entire right column can be resized by dragging its left border (Border Left Drag Handle) to expand or collapse the visible space of the Main Workspace.
|
|
* **Vertical Stacking:** Houses stacked child panels (e.g., Media Explorer, AI Panel, Inspector, etc.).
|
|
* **Independent Height Resizing:** Horizontal splitters (Horizontal Splitter / Resizer Handle) sit between stacked child panels, allowing users to drag up/down to adjust height ratios between panels.
|
|
|
|
|
|
|
|
---
|
|
|
|
## 3. HTML & CSS Framework Implementation
|
|
|
|
### HTML Core Structure
|
|
|
|
```html
|
|
<div class="daw-app-shell">
|
|
<!-- Top Toolbar -->
|
|
<header class="daw-top-bar">...</header>
|
|
|
|
<!-- Body Middle Container -->
|
|
<div class="daw-body-container">
|
|
|
|
<!-- Main Center Viewport -->
|
|
<main class="daw-main-workspace">
|
|
<div class="track-headers-column">...</div>
|
|
<div class="timeline-canvas-viewport">...</div>
|
|
</main>
|
|
|
|
<!-- Vertical Resizer Handle (Adjusts Right Sidebar Width) -->
|
|
<div class="resizer-col-handle" id="col-resizer"></div>
|
|
|
|
<!-- Right Sidebar Container -->
|
|
<aside class="daw-right-sidebar" id="right-sidebar">
|
|
|
|
<!-- Panel 1: Media Explorer -->
|
|
<div class="sidebar-panel" id="panel-media-explorer">
|
|
<div class="panel-header">Media Explorer</div>
|
|
<div class="panel-content">...</div>
|
|
</div>
|
|
|
|
<!-- Horizontal Resizer Handle (Adjusts Panel Heights inside the Column) -->
|
|
<div class="resizer-row-handle" id="row-resizer-1"></div>
|
|
|
|
<!-- Panel 2: AI Panel -->
|
|
<div class="sidebar-panel" id="panel-ai">
|
|
<div class="panel-header">AI Panel</div>
|
|
<div class="panel-content">...</div>
|
|
</div>
|
|
|
|
</aside>
|
|
</div>
|
|
|
|
<!-- Bottom Panel Strip (Horizontal Scroll Container) -->
|
|
<footer class="daw-bottom-strip">
|
|
<div class="bottom-panel">Export Panel</div>
|
|
<div class="bottom-panel">Python DSP Tools Panel</div>
|
|
<div class="bottom-panel">Selection Panel</div>
|
|
<div class="bottom-panel">Plugin FX Rack Panel</div>
|
|
<div class="bottom-panel">MIDI Event List Panel</div>
|
|
</footer>
|
|
|
|
<!-- Status Bar -->
|
|
<div class="daw-status-bar">...</div>
|
|
</div>
|
|
|
|
```
|
|
|
|
### CSS System Architecture
|
|
|
|
```css
|
|
:root {
|
|
--right-sidebar-width: 320px;
|
|
--bottom-strip-height: 220px;
|
|
--top-bar-height: 80px;
|
|
--status-bar-height: 25px;
|
|
--panel-border-color: #2a2a2a;
|
|
}
|
|
|
|
/* Fullscreen Fixed App Shell */
|
|
.daw-app-shell {
|
|
display: flex;
|
|
flex-direction: column;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
overflow: hidden;
|
|
background-color: #121212;
|
|
color: #e0e0e0;
|
|
}
|
|
|
|
/* Middle Section holding Main Workspace and Right Sidebar */
|
|
.daw-body-container {
|
|
display: flex;
|
|
flex: 1;
|
|
height: calc(100vh - var(--top-bar-height) - var(--bottom-strip-height) - var(--status-bar-height));
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* Auto-expanding Main Workspace */
|
|
.daw-main-workspace {
|
|
flex: 1;
|
|
display: flex;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* Right Sidebar with Width controlled via CSS Variable */
|
|
.daw-right-sidebar {
|
|
width: var(--right-sidebar-width);
|
|
min-width: 200px;
|
|
max-width: 600px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background-color: #1a1a1a;
|
|
border-left: 1px solid var(--panel-border-color);
|
|
}
|
|
|
|
/* Vertically stacked child Panels in Right Sidebar */
|
|
.sidebar-panel {
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
background: #1e1e1e;
|
|
border-bottom: 1px solid var(--panel-border-color);
|
|
}
|
|
|
|
#panel-media-explorer {
|
|
height: 50%; /* Default 50/50 split */
|
|
min-height: 100px;
|
|
}
|
|
|
|
#panel-ai {
|
|
flex: 1; /* Fills remaining height */
|
|
min-height: 100px;
|
|
}
|
|
|
|
/* BOTTOM ROW: Enables Horizontal Scrolling */
|
|
.daw-bottom-strip {
|
|
height: var(--bottom-strip-height);
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 8px;
|
|
overflow-x: auto; /* Enables horizontal scroll when panels overflow */
|
|
overflow-y: hidden;
|
|
background-color: #161616;
|
|
border-top: 1px solid var(--panel-border-color);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* Optimized custom horizontal scrollbar for DAW styling */
|
|
.daw-bottom-strip::-webkit-scrollbar {
|
|
height: 8px;
|
|
}
|
|
.daw-bottom-strip::-webkit-scrollbar-thumb {
|
|
background: #3a3a3a;
|
|
border-radius: 4px;
|
|
}
|
|
.daw-bottom-strip::-webkit-scrollbar-thumb:hover {
|
|
background: #00ffcc;
|
|
}
|
|
|
|
/* Sub-panels inside the bottom strip */
|
|
.bottom-panel {
|
|
flex: 0 0 auto; /* Prevents shrinking, locks content dimensions */
|
|
width: 320px;
|
|
height: 100%;
|
|
background-color: #222;
|
|
border: 1px solid #333;
|
|
border-radius: 6px;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
/* RESIZER HANDLES */
|
|
.resizer-col-handle {
|
|
width: 5px;
|
|
cursor: ew-resize; /* Horizontal resize cursor */
|
|
background: transparent;
|
|
transition: background 0.2s;
|
|
z-index: 10;
|
|
}
|
|
.resizer-col-handle:hover,
|
|
.resizer-col-handle:active {
|
|
background: #00ffcc;
|
|
}
|
|
|
|
.resizer-row-handle {
|
|
height: 5px;
|
|
cursor: ns-resize; /* Vertical resize cursor */
|
|
background: transparent;
|
|
transition: background 0.2s;
|
|
z-index: 10;
|
|
}
|
|
.resizer-row-handle:hover,
|
|
.resizer-row-handle:active {
|
|
background: #00ffcc;
|
|
}
|
|
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Interaction Algorithms (JS Resizing Logic)
|
|
|
|
To handle smooth resizing without stuttering or dropped events when dragging over `iframe` or `canvas` elements, the algorithms rely on `pointerdown`, `pointermove`, and `pointerup` events.
|
|
|
|
### A. Right Sidebar Width Resizing Algorithm (Horizontal Resizer)
|
|
|
|
```javascript
|
|
const colResizer = document.getElementById('col-resizer');
|
|
const rightSidebar = document.getElementById('right-sidebar');
|
|
|
|
colResizer.addEventListener('pointerdown', (e) => {
|
|
e.preventDefault();
|
|
colResizer.setPointerCapture(e.pointerId);
|
|
|
|
const startX = e.clientX;
|
|
const startWidth = rightSidebar.getBoundingClientRect().width;
|
|
|
|
const onPointerMove = (moveEvent) => {
|
|
// Delta calculation: dragging left increases width, dragging right decreases width
|
|
const deltaX = startX - moveEvent.clientX;
|
|
const newWidth = Math.max(200, Math.min(600, startWidth + deltaX));
|
|
|
|
document.documentElement.style.setProperty('--right-sidebar-width', `${newWidth}px`);
|
|
};
|
|
|
|
const onPointerUp = (upEvent) => {
|
|
colResizer.releasePointerCapture(upEvent.pointerId);
|
|
colResizer.removeEventListener('pointermove', onPointerMove);
|
|
colResizer.removeEventListener('pointerup', onPointerUp);
|
|
};
|
|
|
|
colResizer.addEventListener('pointermove', onPointerMove);
|
|
colResizer.addEventListener('pointerup', onPointerUp);
|
|
});
|
|
|
|
```
|
|
|
|
### B. Right Sidebar Panel Height Resizing Algorithm (Vertical Resizer)
|
|
|
|
```javascript
|
|
const rowResizer = document.getElementById('row-resizer-1');
|
|
const topPanel = document.getElementById('panel-media-explorer');
|
|
|
|
rowResizer.addEventListener('pointerdown', (e) => {
|
|
e.preventDefault();
|
|
rowResizer.setPointerCapture(e.pointerId);
|
|
|
|
const startY = e.clientY;
|
|
const startHeight = topPanel.getBoundingClientRect().height;
|
|
|
|
const onPointerMove = (moveEvent) => {
|
|
const deltaY = moveEvent.clientY - startY;
|
|
const newHeight = Math.max(100, startHeight + deltaY);
|
|
|
|
topPanel.style.height = `${newHeight}px`;
|
|
topPanel.style.flex = 'none'; // Switch from flex ratio to fixed px during drag
|
|
};
|
|
|
|
const onPointerUp = (upEvent) => {
|
|
rowResizer.releasePointerCapture(upEvent.pointerId);
|
|
rowResizer.removeEventListener('pointermove', onPointerMove);
|
|
rowResizer.removeEventListener('pointerup', onPointerUp);
|
|
};
|
|
|
|
colResizer.addEventListener('pointermove', onPointerMove);
|
|
colResizer.addEventListener('pointerup', onPointerUp);
|
|
});
|
|
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Summary of Solution Advantages
|
|
|
|
* **Native Horizontal Scrolling:** The bottom Dock area flexibly accommodates an unlimited number of Panels. Users can scroll horizontally (`Shift + Mouse Wheel`) or use a trackpad to browse panels easily.
|
|
* **Smooth & Accurate Resizing:** Utilizing Pointer Capture ensures drag interactions do not drop or break even when the cursor moves rapidly beyond the Resizer handle's bounds.
|
|
* **Standardized CSS Variables:** Enables easy persistence of layout states (`Width`/`Height`) to the browser's `localStorage`, restoring the user's custom layout configuration on app reload. |