mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
docs: address spec review feedback for resize/rotate redesign
Adds: state architecture for rotate preview, dimension data source, fit mode defaults, mobile layout notes, extensibility guidance.
This commit is contained in:
@@ -15,10 +15,12 @@ The resize settings also use technical jargon (contain, cover, fill, inside, out
|
||||
Replace the current mode toggle (Pixels/Percentage) with three tabs:
|
||||
|
||||
#### Presets Tab (default)
|
||||
- Grid of cards grouped by platform (Instagram, Twitter/X, Facebook, YouTube, LinkedIn)
|
||||
- Single-column scrollable list of cards grouped by platform (Instagram, Twitter/X, Facebook, YouTube, LinkedIn) — the sidebar is 18rem wide, so single-column avoids cramped cards
|
||||
- Each card shows: platform icon, preset name (e.g., "Post", "Story", "Header"), dimensions (e.g., "1080 × 1080")
|
||||
- Clicking a card selects it (highlighted border), clicking again deselects
|
||||
- Selected preset populates the dimensions automatically
|
||||
- Presets use "Crop to fit" (cover) as the default fit mode — this is the expected behavior for social media sizing
|
||||
- "Don't enlarge" checkbox available below preset grid
|
||||
- Process button at bottom
|
||||
|
||||
#### Custom Size Tab
|
||||
@@ -35,6 +37,7 @@ Replace the current mode toggle (Pixels/Percentage) with three tabs:
|
||||
#### Scale Tab
|
||||
- Percentage number input
|
||||
- Quick-select buttons: 25% | 50% | 75%
|
||||
- `fit` and `withoutEnlargement` are intentionally omitted — percentage scaling doesn't need them. API defaults (`contain`, `false`) are sent.
|
||||
- Process button at bottom
|
||||
|
||||
### Resize: Side-by-Side Result Display
|
||||
@@ -46,16 +49,23 @@ Replace the before/after slider with side-by-side thumbnails:
|
||||
- **Right**: "Resized" label, the processed image, new dimensions below (e.g., "1080 × 720"), file size (e.g., "340 KB")
|
||||
- File size savings shown between/below (e.g., "86% smaller")
|
||||
- Checkerboard background for transparency (same pattern as current viewer)
|
||||
- **Dimensions**: Read client-side from blob URLs using `Image.onload` to get `naturalWidth`/`naturalHeight`. No backend changes needed.
|
||||
- **File sizes**: Use existing `originalSize`/`processedSize` from the API response (already available in the file store).
|
||||
- **Mobile**: On small screens, thumbnails stack vertically instead of side-by-side.
|
||||
- Review panel (undo, download, continue editing) remains unchanged
|
||||
|
||||
### Rotate/Flip: Live CSS Preview
|
||||
|
||||
Replace the "process then compare" flow with live preview:
|
||||
|
||||
**State architecture**: `rotate-settings.tsx` emits transform values (angle, flipH, flipV) via a callback prop from `tool-page.tsx`. `tool-page.tsx` holds the preview transform state and passes it down to `ImageViewer` as optional props (`cssRotate`, `cssFlipH`, `cssFlipV`). `ImageViewer` applies these as CSS `transform: rotate(Xdeg) scaleX(Y) scaleY(Z)`.
|
||||
|
||||
- When a file is loaded, it shows in the image viewer as normal
|
||||
- As the user adjusts controls (rotate buttons, angle slider, flip toggles), CSS transforms update the preview in real-time — no server call
|
||||
- Controls stay the same: quick rotate 90 left/right, angle slider 0-360, horizontal/vertical flip toggles
|
||||
- **Non-90-degree angles**: CSS preview will clip corners (the image rotates within its container). This is acceptable as a preview — the final server output will have proper canvas extension. This is a known discrepancy.
|
||||
- The "Process" button label changes to "Apply" to signal finality
|
||||
- "Apply" button remains disabled when no changes are made (angle=0, no flips) — same as current behavior
|
||||
- Clicking "Apply" sends to the server, produces the final file
|
||||
|
||||
### Rotate/Flip: Result Display
|
||||
@@ -65,13 +75,18 @@ After applying:
|
||||
- The transformation is self-evident
|
||||
- Review panel appears with undo/download options
|
||||
|
||||
### Other Tools
|
||||
|
||||
The `BeforeAfterSlider` remains for all other tools (compress, filters, etc.). Only resize and rotate/flip get special treatment. In `tool-page.tsx`, branch on `toolId` using a set (e.g., `TOOLS_WITHOUT_SLIDER`) for extensibility.
|
||||
|
||||
## Files to Modify
|
||||
|
||||
### Frontend
|
||||
- `apps/web/src/components/tools/resize-settings.tsx` — rewrite with tab-based UI
|
||||
- `apps/web/src/components/tools/rotate-settings.tsx` — add live CSS preview controls
|
||||
- `apps/web/src/pages/tool-page.tsx` — conditionally render side-by-side for resize, skip before/after slider for rotate/flip
|
||||
- New component: `apps/web/src/components/common/side-by-side-comparison.tsx` — reusable side-by-side thumbnail comparison
|
||||
- `apps/web/src/components/tools/rotate-settings.tsx` — emit transform values via callback, change button label to "Apply"
|
||||
- `apps/web/src/pages/tool-page.tsx` — hold preview transform state, conditionally render side-by-side for resize, ImageViewer for rotate/flip, BeforeAfterSlider for everything else
|
||||
- `apps/web/src/components/common/image-viewer.tsx` — accept optional CSS transform props for live rotate/flip preview
|
||||
- `apps/web/src/components/common/side-by-side-comparison.tsx` — new component for side-by-side thumbnail comparison with dimensions and file size
|
||||
|
||||
### No Backend Changes
|
||||
- Resize and rotate API routes remain unchanged
|
||||
|
||||
Reference in New Issue
Block a user