docs: v0.2.1 design spec — polish, icons, cut clip, shortcuts
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
# v0.2.1 — Polish, Icons, Cut Clip & Shortcuts Reference
|
||||
|
||||
## Overview
|
||||
|
||||
Incremental polish release building on v0.2.0 Player mode. Six changes: controls position tweak, Lucide icon migration, blur animation fix, mode toggle shortcuts, cut-clip feature, and keyboard shortcuts reference in the About dialog.
|
||||
|
||||
---
|
||||
|
||||
## 1. Floating Controls Position & Blur Fix
|
||||
|
||||
### Position
|
||||
|
||||
Raise `.player-controls-overlay` from `bottom: 48px` to `bottom: 64px` (+16px).
|
||||
|
||||
### Blur Pop-in Fix
|
||||
|
||||
**Problem:** `backdrop-filter: blur(8px)` is on `.player-controls-panel` while the parent `.player-controls-overlay` transitions `opacity: 0 → 1`. WebKit doesn't smoothly composite `backdrop-filter` through an ancestor `opacity` transition — the blur snaps on once opacity crosses a rendering threshold.
|
||||
|
||||
**Fix:** Move the blur background into a `::before` pseudo-element on `.player-controls-panel`. The pseudo-element handles `background` + `backdrop-filter` and has its own `opacity` transition driven by the `.visible` class on the overlay ancestor. The panel itself becomes `position: relative` with no background/backdrop-filter of its own.
|
||||
|
||||
```css
|
||||
.player-controls-panel {
|
||||
position: relative;
|
||||
/* background and backdrop-filter removed */
|
||||
}
|
||||
|
||||
.player-controls-panel::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.75);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border-radius: 12px;
|
||||
z-index: -1;
|
||||
opacity: 0;
|
||||
transition: opacity 0.25s ease;
|
||||
}
|
||||
|
||||
.player-controls-overlay.visible .player-controls-panel::before {
|
||||
opacity: 1;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Lucide Icon Migration
|
||||
|
||||
Install `lucide-svelte` as a dependency. Replace all emoji and text-glyph icons with Lucide SVG components across `PlayerControls.svelte`, `TransportControls.svelte`, and the `App.svelte` toolbar.
|
||||
|
||||
### Icon Mapping
|
||||
|
||||
| Current | Lucide Component | Location |
|
||||
|---|---|---|
|
||||
| 🔇 / 🔉 / 🔊 | `VolumeX` / `Volume1` / `Volume2` | PlayerControls, TransportControls |
|
||||
| ⏪ | `SkipBack` | PlayerControls |
|
||||
| ❚❚ / ▶ | `Pause` / `Play` | PlayerControls, TransportControls |
|
||||
| ⏩ | `SkipForward` | PlayerControls |
|
||||
| CC (text) | `Captions` | PlayerControls |
|
||||
| ⧉ | `PictureInPicture2` | PlayerControls |
|
||||
| ⛶ / ⤓ | `Maximize` / `Minimize` | PlayerControls |
|
||||
| ⚙ | `Settings` | App toolbar |
|
||||
| ℹ | `Info` | App toolbar |
|
||||
| ⬒ / ⬓ | `PanelLeft` / `PanelBottom` | App toolbar |
|
||||
| ✂️ (new) | `Scissors` | PlayerControls (cut clip button) |
|
||||
| ◄K / K► | `ChevronFirst` / `ChevronLast` | TransportControls |
|
||||
| ◄\| / \|► | `StepBack` / `StepForward` | TransportControls |
|
||||
|
||||
Icons render inline as SVGs. Size: 16–18px to match existing button dimensions.
|
||||
|
||||
---
|
||||
|
||||
## 3. Mode Toggle Shortcuts
|
||||
|
||||
Both `C` and `P` keys become bidirectional toggles. Pressing either key switches from the current mode to the other mode.
|
||||
|
||||
Implementation: both the `'c'/'C'` and `'p'/'P'` cases in `handleGlobalKeydown` call `toggleMode()` instead of hard-coding a target mode via `setAppMode()`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Cut Clip Feature
|
||||
|
||||
### Button
|
||||
|
||||
A scissors icon (`Scissors` from Lucide) in the `PlayerControls` right control group, positioned between the speed selector and the CC button.
|
||||
|
||||
### Behavior
|
||||
|
||||
- **Left-click / `X` key:** Create a 10-second clip starting at the current playhead position (`currentTime` → `currentTime + 10`). Clamp end to `session.duration`. Switch to Clipper mode. Playhead stays at its current position.
|
||||
- **Right-click / `Z` key:** Create a 10-second clip ending at the current playhead position (`currentTime - 10` → `currentTime`). Clamp start to `0`. Switch to Clipper mode. Playhead stays at its current position.
|
||||
|
||||
### Implementation
|
||||
|
||||
- Add a `cutClip(position: 'at' | 'before')` helper. It calls `addClip(start, end)` from the clips store, then `setAppMode('clipper')`.
|
||||
- Pass an `onCutClip` callback prop to `PlayerControls`. The button's `onclick` calls `onCutClip('at')`, `oncontextmenu` prevents default and calls `onCutClip('before')`.
|
||||
- In `handleGlobalKeydown`: `X`/`x` → `cutClip('at')`, `Z`/`z` → `cutClip('before')`. Only active in Player mode.
|
||||
- **Tooltip:** "Cut clip at playhead (X) · Right-click: 10s before (Z)"
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- No video loaded (`session.duration === 0`): no-op.
|
||||
- Playhead < 10s from start: `Z`/right-click clamps start to 0.
|
||||
- Playhead < 10s from end: `X`/left-click clamps end to duration.
|
||||
|
||||
---
|
||||
|
||||
## 5. Tabbed About Dialog with Keyboard Shortcuts
|
||||
|
||||
### Tab Structure
|
||||
|
||||
Two tabs: **About** (default) and **Shortcuts**.
|
||||
|
||||
### About Tab
|
||||
|
||||
Identical to current content (icon, app name, version, author, license, repo link, close button). Dialog stays at ~360px wide.
|
||||
|
||||
### Shortcuts Tab
|
||||
|
||||
Two-column layout (key on left, description on right) grouped by section headers. Dialog expands to ~520px wide with `max-height: 70vh` and vertical scroll. Width change transitions smoothly (`transition: max-width 0.2s ease`).
|
||||
|
||||
Tab switcher: text tabs at the top of the dialog, active tab gets accent-color underline.
|
||||
|
||||
### Complete Shortcut Reference
|
||||
|
||||
**Global (both modes):**
|
||||
|
||||
| Key | Action |
|
||||
|---|---|
|
||||
| `Space` | Play / Pause |
|
||||
| `K` | Play / Pause |
|
||||
| `J` | Shuttle slower (−0.25×) |
|
||||
| `L` | Shuttle faster (+0.25×) |
|
||||
| `←` | Seek back 5s |
|
||||
| `→` | Seek forward 5s |
|
||||
| `Shift+←` | Seek back 1s |
|
||||
| `Shift+→` | Seek forward 1s |
|
||||
| `,` | Previous frame |
|
||||
| `.` | Next frame |
|
||||
| `<` (Shift+,) | Previous keyframe |
|
||||
| `>` (Shift+.) | Next keyframe |
|
||||
| `C` / `P` | Toggle mode |
|
||||
| `Cmd+/` | About |
|
||||
|
||||
**Player mode:**
|
||||
|
||||
| Key | Action |
|
||||
|---|---|
|
||||
| `F` | Toggle fullscreen |
|
||||
| `X` | Cut clip at playhead → Clipper |
|
||||
| `Z` | Cut clip 10s before playhead → Clipper |
|
||||
|
||||
**Clipper mode:**
|
||||
|
||||
| Key | Action |
|
||||
|---|---|
|
||||
| `I` | Set in-point |
|
||||
| `O` | Set out-point |
|
||||
| `Delete` / `Backspace` | Remove selected clip |
|
||||
| `Cmd+E` | Export |
|
||||
Reference in New Issue
Block a user