# v0.2.1 — Polish, Icons, Cut Clip & Shortcuts Reference ## Task Description Design, plan, and implement v0.2.1 of the GUI Video Clipper app. Six items: raise floating controls position, replace emoji icons with Lucide SVGs, fix blur pop-in animation, make C/P shortcuts bidirectional toggles, add "cut clip" feature from Player mode, and add keyboard shortcuts reference in a tabbed About dialog. ## Changes Made ### Commits (d8a6e0e → d7a2071) 1. **`646f2e5`** — `fix: raise controls to 64px, smooth blur via ::before pseudo-element` - `src/lib/components/PlayerControls.svelte`: Changed `bottom: 48px` → `64px`, moved `background` + `backdrop-filter` from `.player-controls-panel` to a `::before` pseudo-element with its own opacity transition 2. **`be27b1b`** — `feat: replace emoji icons with Lucide SVG components` - Installed `@lucide/svelte` dependency - `src/lib/components/PlayerControls.svelte`: Replaced 🔇/🔉/🔊, ⏪, ❚❚/▶, ⏩, CC, ⧉, ⛶/⤓ with Lucide components (VolumeX/Volume1/Volume2, Rewind, Pause/Play, FastForward, Captions, PictureInPicture2, Maximize/Minimize) - `src/lib/components/TransportControls.svelte`: Replaced ◄K/K►, ◄|/|►, ❚❚/▶, 🔇/🔉/🔊 with ChevronFirst/ChevronLast, SkipBack/SkipForward, Pause/Play, VolumeX/Volume1/Volume2 - `src/App.svelte`: Replaced ⬒/⬓, ℹ, ⚙ with PanelLeft/PanelBottom, Info, Settings 3. **`d964c97`** — `feat: C and P both toggle between Clipper/Player modes` - `src/App.svelte`: Combined `'p'/'P'/'c'/'C'` cases to all call `toggleMode()` 4. **`ac7cb70`** — `feat: cut clip from Player mode (X/Z keys, scissors button)` - Created `src/lib/utils/clipRange.ts` with `computeQuickClipRange()` utility - Created `tests/lib/utils/clipRange.test.ts` (8 tests) - `src/lib/components/PlayerControls.svelte`: Added scissors button with `onCutClip` prop - `src/App.svelte`: Added `cutClip()` function, `X`/`Z` keyboard shortcuts (Player mode only) 5. **`507e3b7`** — `feat: tabbed About dialog with keyboard shortcuts reference` - Rewrote `src/lib/components/AboutDialog.svelte` with "About" / "Shortcuts" tabs - Created `tests/lib/components/AboutDialog.test.ts` (5 tests) - Dialog dynamically sizes: ~360px for About, ~520px for Shortcuts 6. **`d7a2071`** — `fix: guard against zero-length clip at EOF` - `src/lib/utils/clipRange.ts`: Added `start >= end` guard returning `null` - Added test for `computeQuickClipRange(120, 120, 'at')` → `null` ## Test Results - **69/69 tests passing** across 10 test files - **svelte-check**: 0 errors, 0 warnings ## Follow-Up Items - Remaining non-Lucide glyphs in ClipList, VideoPlayer, TimelineContextMenu (visual consistency for v0.2.2) - Icon-only buttons could benefit from `aria-label` for screen reader accessibility - Shortcuts reference in AboutDialog is static — could extract to shared source of truth with keyboard handler - No `role="tabpanel"` / `aria-controls` wiring on About dialog tabs (full WAI-ARIA tabs pattern) ## Lessons Learned - **WebKit `backdrop-filter` + `opacity` compositing**: WebKit doesn't smoothly composite `backdrop-filter` through an ancestor `opacity` transition. The fix is to isolate the blur into a `::before` pseudo-element with its own opacity transition. - **`@lucide/svelte` is the official package name** (not `lucide-svelte`). Uses tree-shakable named imports: `import { Play } from '@lucide/svelte'`. - **Svelte component testing text collisions**: When testing components with duplicate visible text (e.g., "Play / Pause" appears twice in a shortcuts table), use `getAllByText` or `getByRole` with name filters instead of `getByText`. - **Edge case: zero-length clips**: When clamping clip ranges to video bounds, always guard against `start >= end` after clamping to prevent zero-duration clips.