From f160c0510b1506474269cb873a07cffb1f22e5c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Battistella=20Nadas?= Date: Tue, 9 Jun 2026 19:49:05 +0200 Subject: [PATCH] feat(ux): translate becomes a primary FAB stacked under camera MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Promotes Translate from an inline button under the input pane to the primary 56x56 FAB at the bottom-right corner. Camera FAB becomes the secondary in the stack, just above. Both share a single .fab base class; positioning via .fab-primary / .fab-secondary. - Translate icon: Material Symbols `translate` (28 px). - Pulsing-ring `busy` animation while a translation runs, since the icon-only button can't show "Translating…" text anymore. - body padding-bottom bumped to ~9 rem so the output pane scrolls clear of the stacked FABs. - ⌘/Ctrl-Enter still triggers translate via the existing CodeMirror keymap; tooltip text updated. --- CHANGELOG.md | 1 + static/index.html | 41 +++++++++++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7729ae1..7346388 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Changed - "Scan image" button replaced with a floating action button at the bottom-right of the viewport, using a Material Symbols Outlined camera glyph (`photo_camera`) for consistent rendering across platforms (was a small text button in the input pane header). +- "Translate" inline button replaced with a primary FAB using the `translate` Material Symbols icon, stacked directly under the camera FAB at the bottom-right corner (closest to the thumb on phones). The camera FAB is now the *secondary* in the stack, just above. Both 56 × 56 px, same accent fill. The translate FAB gains a pulsing-ring `busy` animation during a running translation; `goBtn.textContent` swap is gone (was meaningless for an icon-only button). `body` got `~9 rem` of bottom padding so content scrolls clear of the stack. - Crop modal: - No default crop box. User drags on the image to draw the region; falls back to full image if they confirm without drawing. - Buttons are now Material Symbols icons: `rotate_left`, `rotate_right`, `invert_colors` (new — see below), `check`. Cancel kept as text. The `check` (Use this) button is larger and more prominent. The Reset button was removed (rarely useful with no default box). diff --git a/static/index.html b/static/index.html index 2acff4d..b7a85d5 100644 --- a/static/index.html +++ b/static/index.html @@ -34,7 +34,8 @@ background: var(--bg); color: var(--fg); margin: 0; - padding: 2rem 1rem; + /* extra bottom padding so content scrolls clear of the stacked FABs */ + padding: 2rem 1rem calc(9rem + env(safe-area-inset-bottom, 0px)) 1rem; } .wrap { max-width: 960px; margin: 0 auto; } h1 { @@ -165,10 +166,10 @@ user-select: none; } - /* Floating action button for OCR scan — bottom-right, mobile-thumb friendly */ - .scan-fab { + /* Floating action buttons — stacked at bottom-right. + Translate is the primary action (closest to the thumb), Scan sits above. */ + .fab { position: fixed; - bottom: calc(1.5rem + env(safe-area-inset-bottom, 0px)); right: calc(1.5rem + env(safe-area-inset-right, 0px)); width: 56px; height: 56px; @@ -184,11 +185,25 @@ display: flex; align-items: center; justify-content: center; - transition: transform 0.15s; + transition: transform 0.15s, box-shadow 0.15s; + } + .fab .material-symbols-outlined { font-size: 28px; } + .fab:hover:not(:disabled) { transform: scale(1.06); } + .fab:disabled { opacity: 0.55; cursor: progress; } + .fab-primary { + bottom: calc(1.5rem + env(safe-area-inset-bottom, 0px)); + } + .fab-secondary { + /* sits above the primary: 56 (primary height) + 0.75rem gap + base offset */ + bottom: calc(1.5rem + 56px + 0.75rem + env(safe-area-inset-bottom, 0px)); + } + .fab.busy { + animation: fab-pulse 1.4s ease-in-out infinite; + } + @keyframes fab-pulse { + 0%, 100% { box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35); } + 50% { box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35), 0 0 0 8px rgba(224, 122, 62, 0.35); } } - .scan-fab .material-symbols-outlined { font-size: 28px; } - .scan-fab:hover:not(:disabled) { transform: scale(1.06); } - .scan-fab:disabled { opacity: 0.6; cursor: progress; } .scan-status { font-size: 0.75rem; color: var(--muted); @@ -408,13 +423,15 @@ -
- +