feat(prezentacja): kliknięcie powiększa kosmogram na pełne okno (PRE-25)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 11m52s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m57s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 46s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 19s
build / build (push) Successful in 1m10s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m59s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m50s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 42s
Testy / Kontrola składni wszystkich warstw (push) Successful in 19s
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 11m52s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m57s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 46s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 19s
build / build (push) Successful in 1m10s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m59s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m50s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 42s
Testy / Kontrola składni wszystkich warstw (push) Successful in 19s
Ósma wskazówka partnerów, jako małe QoL przed PRE-22. Koło rysujemy w kolumnie tekstu, więc na mniejszym ekranie glify i stopnie robią się nieczytelne. Kliknięcie rozciąga wykres na całe okno, ponowne wraca do strony. SVG skaluje się bez utraty jakości, więc nie potrzeba drugiej wersji rysunku ani biblioteki. Wyjście z powiększenia na trzy sposoby: klik w wykres, klik w tło, Esc. Dostępne też z klawiatury (Enter/Spacja, focus-visible), bo inaczej obejrzenie szczegółów wymagałoby myszy. Dwie decyzje warte odnotowania: 1. WARSTWA. z-index 1100 CELOWO pomiędzy: ponad kontrolkami Leafleta (1000), ale PONIŻEJ okna postępu (1200). Gdy trwa pisanie horoskopu, log operacji ma zostać na wierzchu. Test pilnuje tej nierówności, bo to jedyna liczba tutaj, którą łatwo zmienić bez zastanowienia i zepsuć coś niewidocznego na oko. 2. ROZMIAR. Koło jest kwadratowe, więc ograniczamy je KRÓTSZYM bokiem okna (min(96vw, 92vh)) — inaczej na szerokim ekranie wystawałoby w pionie. Skrypt podpięty globalnie w base.html i osłonięty sprawdzeniem, czy koło w ogóle jest na stronie — zadziała też na przyszłej zakładce „Skompiluj" bez zmian. Przy powiększeniu blokujemy przewijanie strony pod spodem. Weryfikacja na żywej aplikacji, pomiarami w DOM: po kliknięciu .wheel-fig ma position:fixed, display:flex, z-index:1100; SVG rośnie z 460×460 do 662×653 przy oknie 1280×720, visibility visible; body dostaje overflow:hidden. Ponowne kliknięcie wraca do 460×460 i zdejmuje klasę. Zrzutu ekranu stanu powiększonego NIE mam — panel przeglądarki zaciął się w trakcie (puste klatki, viewport raportowany jako 0×0), więc opieram się na pomiarach i testach. Testy: 10 nowych. Całość: prezentacja 87 passed, logika 265 / 1 skip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit was merged in pull request #29.
This commit is contained in:
Binary file not shown.
@@ -50,6 +50,24 @@ td.glyph { color: var(--accent); white-space: nowrap; }
|
||||
.wheel-fig figcaption { margin-top: .4rem; }
|
||||
/* glify wewnątrz SVG dziedziczą monochromatyczny stack fontów (DAN-18) */
|
||||
svg.wheel text.glyph { font-size: inherit; }
|
||||
|
||||
/* Powiększenie na pełne okno (PRE-25). Kliknięcie rozciąga wykres na cały ekran,
|
||||
ponowne wraca. z-index 1100 CELOWO pomiędzy: ponad kontrolki Leafleta (1000),
|
||||
ale PONIŻEJ okna postępu (1200) — gdy trwa pisanie horoskopu, log operacji ma
|
||||
zostać na wierzchu. */
|
||||
.wheel-fig svg.wheel { cursor: zoom-in; }
|
||||
.wheel-fig svg.wheel:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
|
||||
.wheel-fig.zoomed {
|
||||
position: fixed; inset: 0; z-index: 1100; margin: 0;
|
||||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||||
gap: .5rem; padding: 1rem; background: var(--bg);
|
||||
}
|
||||
/* min() po obu wymiarach: koło jest kwadratowe, więc ograniczamy je krótszym
|
||||
bokiem okna — inaczej na szerokim ekranie wystawałoby w pionie. */
|
||||
.wheel-fig.zoomed svg.wheel {
|
||||
max-width: min(96vw, 92vh); width: min(96vw, 92vh); height: auto; cursor: zoom-out;
|
||||
}
|
||||
body.wheel-zoom-open { overflow: hidden; } /* nie przewijaj treści pod spodem */
|
||||
form { background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 1.25rem; }
|
||||
.row { display: flex; gap: .5rem; }
|
||||
.row input[type=text] { flex: 1; }
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
// Powiększanie kosmogramu na pełne okno (PRE-25).
|
||||
//
|
||||
// Koło rysujemy w kolumnie tekstu, więc na małym ekranie glify i stopnie robią
|
||||
// się nieczytelne. Kliknięcie rozciąga wykres na całe okno, ponowne wraca do
|
||||
// strony. SVG skaluje się bez utraty jakości, więc nie potrzeba drugiej wersji
|
||||
// rysunku ani żadnej biblioteki.
|
||||
//
|
||||
// Podpięte globalnie i osłonięte sprawdzeniem, czy koło w ogóle jest na stronie
|
||||
// — dzięki temu zadziała też na przyszłej zakładce „Skompiluj", bez zmian tutaj.
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var ZOOMED = 'zoomed';
|
||||
|
||||
function ready(fn) {
|
||||
if (document.readyState !== 'loading') fn();
|
||||
else document.addEventListener('DOMContentLoaded', fn);
|
||||
}
|
||||
|
||||
ready(function () {
|
||||
var figures = document.querySelectorAll('.wheel-fig');
|
||||
if (!figures.length) return;
|
||||
|
||||
Array.prototype.forEach.call(figures, function (fig) {
|
||||
var svg = fig.querySelector('svg.wheel');
|
||||
if (!svg) return;
|
||||
|
||||
// Klawiatura ma działać tak samo jak mysz — to nie jest ozdobnik, tylko
|
||||
// jedyny sposób na obejrzenie szczegółów wykresu.
|
||||
svg.setAttribute('tabindex', '0');
|
||||
svg.setAttribute('role', 'button');
|
||||
svg.setAttribute('aria-label', 'Kosmogram — kliknij, aby powiększyć na całe okno');
|
||||
|
||||
function toggle() {
|
||||
var on = fig.classList.toggle(ZOOMED);
|
||||
// Blokujemy przewijanie strony pod spodem: inaczej scroll „przecieka"
|
||||
// na treść, której i tak nie widać.
|
||||
document.body.classList.toggle('wheel-zoom-open', on);
|
||||
svg.setAttribute('aria-label', on
|
||||
? 'Kosmogram powiększony — kliknij lub naciśnij Esc, aby wrócić'
|
||||
: 'Kosmogram — kliknij, aby powiększyć na całe okno');
|
||||
if (on) svg.focus();
|
||||
}
|
||||
|
||||
svg.addEventListener('click', toggle);
|
||||
svg.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggle(); }
|
||||
});
|
||||
|
||||
// Klik w tło (poza samym rysunkiem) też zamyka — naturalne dla nakładki.
|
||||
fig.addEventListener('click', function (e) {
|
||||
if (e.target === fig && fig.classList.contains(ZOOMED)) toggle();
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (e.key === 'Escape' && fig.classList.contains(ZOOMED)) toggle();
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
@@ -10,6 +10,9 @@
|
||||
odtworzyć współrzędne, ZANIM geo.js zbuduje mapę — mapa startuje od razu
|
||||
we właściwym miejscu, bez przestawiania. #}
|
||||
<script defer src="/static/formsync.js"></script>
|
||||
{# Powiększanie kosmogramu (PRE-25) — globalnie, bo koło pojawi się też na
|
||||
zakładce „Skompiluj"; skrypt sam sprawdza, czy jest co powiększać. #}
|
||||
<script defer src="/static/wheelzoom.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
"""Powiększanie kosmogramu na pełne okno (PRE-25).
|
||||
|
||||
Test strukturalny, jak przy pozostałych rzeczach żyjących w JS/CSS. Osobno
|
||||
pilnujemy warstwy nakładki: to jedyna liczba w tym pliku, którą łatwo zmienić
|
||||
bez zastanowienia i zepsuć coś, czego się nie widzi na pierwszy rzut oka.
|
||||
"""
|
||||
import pathlib
|
||||
import re
|
||||
|
||||
APP = pathlib.Path(__file__).resolve().parents[1] / "app"
|
||||
JS = (APP / "static" / "wheelzoom.js").read_text(encoding="utf-8")
|
||||
CSS = (APP / "static" / "styles.css").read_text(encoding="utf-8")
|
||||
BASE = (APP / "templates" / "base.html").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_script_is_loaded_globally():
|
||||
"""Ładowane w base.html, bo koło pojawi się też na zakładce Skompiluj."""
|
||||
assert "wheelzoom.js" in BASE
|
||||
|
||||
|
||||
def test_toggles_on_click():
|
||||
assert "addEventListener('click'" in JS
|
||||
assert "classList.toggle" in JS
|
||||
|
||||
|
||||
def test_closes_with_escape():
|
||||
assert "'Escape'" in JS
|
||||
|
||||
|
||||
def test_reachable_from_keyboard():
|
||||
"""Bez tego jedyny sposób na obejrzenie szczegółów wykresu wymagałby myszy."""
|
||||
assert "tabindex" in JS
|
||||
assert "'Enter'" in JS
|
||||
|
||||
|
||||
def test_page_scroll_is_locked_while_zoomed():
|
||||
"""Inaczej przewijanie „przecieka" na treść pod spodem, której i tak nie widać."""
|
||||
assert "wheel-zoom-open" in JS
|
||||
assert re.search(r"body\.wheel-zoom-open\s*\{[^}]*overflow:\s*hidden", CSS)
|
||||
|
||||
|
||||
def test_zoomed_layer_sits_above_map_but_below_progress():
|
||||
"""Warstwy: kontrolki Leafleta 1000 < kosmogram < okno postępu 1200.
|
||||
Gdy trwa pisanie horoskopu, log operacji ma zostać na wierzchu."""
|
||||
zoom = re.search(r"\.wheel-fig\.zoomed\s*\{[^}]*z-index:\s*(\d+)", CSS)
|
||||
progress = re.search(r"\.progress-overlay\s*\{[^}]*z-index:\s*(\d+)", CSS)
|
||||
assert zoom and progress, "nie znaleziono warstw w CSS"
|
||||
assert 1000 < int(zoom.group(1)) < int(progress.group(1))
|
||||
|
||||
|
||||
def test_zoomed_wheel_is_bounded_by_shorter_window_side():
|
||||
"""Koło jest kwadratowe — ograniczamy je krótszym bokiem okna, inaczej na
|
||||
szerokim ekranie wystawałoby w pionie."""
|
||||
block = re.search(r"\.wheel-fig\.zoomed svg\.wheel\s*\{[^}]*\}", CSS)
|
||||
assert block and "vh" in block.group(0) and "vw" in block.group(0)
|
||||
|
||||
|
||||
def test_cursor_signals_the_affordance():
|
||||
assert "zoom-in" in CSS and "zoom-out" in CSS
|
||||
|
||||
|
||||
def test_does_nothing_without_a_wheel():
|
||||
"""Na zakładkach bez kosmogramu skrypt ma po prostu wyjść."""
|
||||
assert "if (!figures.length) return;" in JS
|
||||
Reference in New Issue
Block a user