fix(reader): keep word translation popup as compact block on desktop without full-width stretch

This commit is contained in:
2026-10-08 11:46:44 +03:00
parent f10965eff5
commit e1cacde543
6 changed files with 86 additions and 64 deletions
+11
View File
@@ -40,6 +40,17 @@
} }
} }
@keyframes slideUpSheet {
from {
transform: translateY(100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.auth-header, .auth-header,
.login-header { .login-header {
text-align: center; text-align: center;
-50
View File
@@ -757,56 +757,6 @@
} }
/* 7. Bottom Sheet for Word Translation Popup on Mobile */
.reader-word-popup {
position: fixed !important;
top: auto !important;
bottom: calc(58px + env(safe-area-inset-bottom, 0px)) !important;
left: 8px !important;
right: 8px !important;
width: auto !important;
max-width: none !important;
border-radius: 18px !important;
box-shadow: 0 -8px 30px rgba(0, 0, 0, 0.5) !important;
border: 1px solid var(--border-focus) !important;
background-color: var(--bg-surface) !important;
z-index: 10005 !important;
padding: 14px 16px !important;
animation: slideUpSheet 0.22s cubic-bezier(0.16, 1, 0.3, 1) !important;
}
.reader-settings-panel {
position: fixed !important;
top: auto !important;
bottom: calc(58px + env(safe-area-inset-bottom, 0px)) !important;
left: 8px !important;
right: 8px !important;
width: auto !important;
max-height: calc(85dvh - 60px) !important;
overflow-y: auto !important;
-webkit-overflow-scrolling: touch !important;
border-radius: 20px !important;
box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.55) !important;
border: 1px solid var(--border-focus) !important;
background-color: var(--bg-surface) !important;
color: var(--text-main) !important;
padding: 16px 18px 24px !important;
z-index: 10006 !important;
animation: slideUpSheet 0.22s cubic-bezier(0.16, 1, 0.3, 1) !important;
}
@keyframes slideUpSheet {
from {
transform: translateY(100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
/* --- Responsive Mobile Overrides (max-width: 768px) --- */ /* --- Responsive Mobile Overrides (max-width: 768px) --- */
@media (max-width: 768px) { @media (max-width: 768px) {
/* 4. Dictionary & Search */ /* 4. Dictionary & Search */
+55 -3
View File
@@ -1549,9 +1549,11 @@
background-color: var(--bg-surface); background-color: var(--bg-surface);
border: 1px solid var(--border-focus); border: 1px solid var(--border-focus);
border-radius: var(--radius-lg); border-radius: var(--radius-lg);
box-shadow: 0 12px 24px -4px rgba(0, 0, 0, 0.5); box-shadow: 0 12px 28px -4px rgba(0, 0, 0, 0.55);
width: 320px; width: 340px;
max-width: calc(100vw - 32px); max-width: 360px;
max-height: calc(100vh - 40px);
overflow-y: auto;
padding: 16px; padding: 16px;
animation: fadeInScale 0.15s ease-out; animation: fadeInScale 0.15s ease-out;
} }
@@ -2061,6 +2063,56 @@
font-size: 17px; font-size: 17px;
line-height: 1.65; line-height: 1.65;
} }
/* Mobile Bottom Sheet for Word Translation Popup */
.reader-word-popup {
position: fixed !important;
top: auto !important;
bottom: calc(58px + env(safe-area-inset-bottom, 0px)) !important;
left: 8px !important;
right: 8px !important;
width: auto !important;
max-width: none !important;
max-height: calc(85dvh - 60px) !important;
overflow-y: auto !important;
border-radius: 18px !important;
box-shadow: 0 -8px 30px rgba(0, 0, 0, 0.5) !important;
border: 1px solid var(--border-focus) !important;
background-color: var(--bg-surface) !important;
z-index: 10005 !important;
padding: 14px 16px !important;
animation: slideUpSheet 0.22s cubic-bezier(0.16, 1, 0.3, 1) !important;
}
body.zen-mode-active .reader-word-popup {
bottom: calc(12px + env(safe-area-inset-bottom, 0px)) !important;
}
/* Mobile Bottom Sheet for Reader Settings */
.reader-settings-panel {
position: fixed !important;
top: auto !important;
bottom: calc(58px + env(safe-area-inset-bottom, 0px)) !important;
left: 8px !important;
right: 8px !important;
width: auto !important;
max-width: none !important;
max-height: calc(85dvh - 60px) !important;
overflow-y: auto !important;
-webkit-overflow-scrolling: touch !important;
border-radius: 20px !important;
box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.55) !important;
border: 1px solid var(--border-focus) !important;
background-color: var(--bg-surface) !important;
color: var(--text-main) !important;
padding: 16px 18px 24px !important;
z-index: 10006 !important;
animation: slideUpSheet 0.22s cubic-bezier(0.16, 1, 0.3, 1) !important;
}
body.zen-mode-active .reader-settings-panel {
bottom: calc(12px + env(safe-area-inset-bottom, 0px)) !important;
}
} }
/* ========================================================================== /* ==========================================================================
+2 -2
View File
@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<title>Notes — Персональный тренажер и словарь английского языка</title> <title>Notes — Персональный тренажер и словарь английского языка</title>
<meta name="description" content="Защищённый персональный тренажёр и словарь английского языка с интервальными повторениями SRS SM-2, контекстным поиском и озвучкой"> <meta name="description" content="Защищённый персональный тренажёр и словарь английского языка с интервальными повторениями SRS SM-2, контекстным поиском и озвучкой">
<link rel="stylesheet" href="/static/css/style.css?v=6.7"> <link rel="stylesheet" href="/static/css/style.css?v=6.8">
<!-- PWA meta and icons --> <!-- PWA meta and icons -->
<link rel="manifest" href="/manifest.json"> <link rel="manifest" href="/manifest.json">
@@ -2049,7 +2049,7 @@
<!-- Audio Element for native streaming --> <!-- Audio Element for native streaming -->
<audio id="global-audio-player" preload="none"></audio> <audio id="global-audio-player" preload="none"></audio>
<script type="module" src="/static/js/app.js?v=6.4"></script> <script type="module" src="/static/js/app.js?v=6.5"></script>
</body> </body>
</html> </html>
+17 -8
View File
@@ -1309,31 +1309,40 @@ export function positionWordPopup(targetElement) {
if (window.innerWidth <= 768) { if (window.innerWidth <= 768) {
readerWordPopup.style.top = ''; readerWordPopup.style.top = '';
readerWordPopup.style.left = ''; readerWordPopup.style.left = '';
readerWordPopup.style.right = '';
readerWordPopup.style.bottom = '';
readerWordPopup.style.width = '';
return; return;
} }
const rect = targetElement.getBoundingClientRect(); const rect = targetElement.getBoundingClientRect();
const popupWidth = 320; const popupWidth = (readerWordPopup.offsetWidth && readerWordPopup.offsetWidth >= 280 && readerWordPopup.offsetWidth <= 380)
? readerWordPopup.offsetWidth
: 340;
const popupHeight = readerWordPopup.offsetHeight || 220; const popupHeight = readerWordPopup.offsetHeight || 220;
const viewportWidth = window.innerWidth; const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight; const viewportHeight = window.innerHeight;
let left = rect.left + (rect.width / 2) - (popupWidth / 2); let left = rect.left + (rect.width / 2) - (popupWidth / 2);
if (left + popupWidth > viewportWidth - 12) { if (left + popupWidth > viewportWidth - 16) {
left = viewportWidth - popupWidth - 12; left = viewportWidth - popupWidth - 16;
} }
if (left < 12) { if (left < 16) {
left = 12; left = 16;
} }
const minTop = isZenMode ? 16 : 65;
let top = rect.bottom + 8; let top = rect.bottom + 8;
if (top + popupHeight > viewportHeight - 12) { if (top + popupHeight > viewportHeight - 16) {
if (rect.top - popupHeight - 8 >= 65 || rect.top > viewportHeight / 2) { if (rect.top - popupHeight - 8 >= minTop || rect.top > viewportHeight / 2) {
top = Math.max(65, rect.top - popupHeight - 8); top = Math.max(minTop, rect.top - popupHeight - 8);
} }
} }
readerWordPopup.style.top = `${Math.round(top)}px`; readerWordPopup.style.top = `${Math.round(top)}px`;
readerWordPopup.style.left = `${Math.round(left)}px`; readerWordPopup.style.left = `${Math.round(left)}px`;
readerWordPopup.style.right = 'auto';
readerWordPopup.style.bottom = 'auto';
readerWordPopup.style.width = `${popupWidth}px`;
} }
export async function openWordPopup(term, contextSentence, targetElement, paragraphContext = '') { export async function openWordPopup(term, contextSentence, targetElement, paragraphContext = '') {
+1 -1
View File
@@ -1,7 +1,7 @@
// Service Worker for Notes English PWA (Stage 2) // Service Worker for Notes English PWA (Stage 2)
// Strategy: Cache-first for static assets, Network-first for API calls. // Strategy: Cache-first for static assets, Network-first for API calls.
const CACHE_NAME = 'notes-v6.7'; const CACHE_NAME = 'notes-v6.8';
const OFFLINE_URL = '/'; const OFFLINE_URL = '/';
const PRECACHE_URLS = [ const PRECACHE_URLS = [