docs: v0.2.1 design spec — polish, icons, cut clip, shortcuts

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-23 01:42:50 -04:00
parent 2e36d16bfe
commit 21a5445143

View File

@@ -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 |