fix(reader): keep word translation popup as compact block on desktop without full-width stretch
This commit is contained in:
1 parent
f10965eff5
commit
e1cacde543
6 files changed
+86
-64
No files matched your search
@@ -40,6 +40,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideUpSheet {
|
||||
from {
|
||||
transform: translateY(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.auth-header,
|
||||
.login-header {
|
||||
text-align: center;
|
||||
|
||||
@@ -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) --- */
|
||||
@media (max-width: 768px) {
|
||||
/* 4. Dictionary & Search */
|
||||
|
||||
@@ -1549,9 +1549,11 @@
|
||||
background-color: var(--bg-surface);
|
||||
border: 1px solid var(--border-focus);
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: 0 12px 24px -4px rgba(0, 0, 0, 0.5);
|
||||
width: 320px;
|
||||
max-width: calc(100vw - 32px);
|
||||
box-shadow: 0 12px 28px -4px rgba(0, 0, 0, 0.55);
|
||||
width: 340px;
|
||||
max-width: 360px;
|
||||
max-height: calc(100vh - 40px);
|
||||
overflow-y: auto;
|
||||
padding: 16px;
|
||||
animation: fadeInScale 0.15s ease-out;
|
||||
}
|
||||
@@ -2061,6 +2063,56 @@
|
||||
font-size: 17px;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
|
||||
@@ -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">
|
||||
<title>Notes — Персональный тренажер и словарь английского языка</title>
|
||||
<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 -->
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
@@ -2049,7 +2049,7 @@
|
||||
<!-- Audio Element for native streaming -->
|
||||
<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>
|
||||
</html>
|
||||
|
||||
@@ -1309,31 +1309,40 @@ export function positionWordPopup(targetElement) {
|
||||
if (window.innerWidth <= 768) {
|
||||
readerWordPopup.style.top = '';
|
||||
readerWordPopup.style.left = '';
|
||||
readerWordPopup.style.right = '';
|
||||
readerWordPopup.style.bottom = '';
|
||||
readerWordPopup.style.width = '';
|
||||
return;
|
||||
}
|
||||
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 viewportWidth = window.innerWidth;
|
||||
const viewportHeight = window.innerHeight;
|
||||
|
||||
let left = rect.left + (rect.width / 2) - (popupWidth / 2);
|
||||
if (left + popupWidth > viewportWidth - 12) {
|
||||
left = viewportWidth - popupWidth - 12;
|
||||
if (left + popupWidth > viewportWidth - 16) {
|
||||
left = viewportWidth - popupWidth - 16;
|
||||
}
|
||||
if (left < 12) {
|
||||
left = 12;
|
||||
if (left < 16) {
|
||||
left = 16;
|
||||
}
|
||||
|
||||
const minTop = isZenMode ? 16 : 65;
|
||||
let top = rect.bottom + 8;
|
||||
if (top + popupHeight > viewportHeight - 12) {
|
||||
if (rect.top - popupHeight - 8 >= 65 || rect.top > viewportHeight / 2) {
|
||||
top = Math.max(65, rect.top - popupHeight - 8);
|
||||
if (top + popupHeight > viewportHeight - 16) {
|
||||
if (rect.top - popupHeight - 8 >= minTop || rect.top > viewportHeight / 2) {
|
||||
top = Math.max(minTop, rect.top - popupHeight - 8);
|
||||
}
|
||||
}
|
||||
|
||||
readerWordPopup.style.top = `${Math.round(top)}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 = '') {
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
// Service Worker for Notes English PWA (Stage 2)
|
||||
// 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 PRECACHE_URLS = [
|
||||
|
||||
Reference in new issue
Block a user