feat(top_bar): animowane chowanie paska przy oknie wyszukiwania - #800
Open
mpasternak wants to merge 1 commit into
Open
feat(top_bar): animowane chowanie paska przy oknie wyszukiwania#800mpasternak wants to merge 1 commit into
mpasternak wants to merge 1 commit into
Conversation
Pasek `nav.sticky-header` znikał i pojawiał się skokowo przy otwieraniu i zamykaniu okna wyszukiwania globalnego. Nie był to brak animacji, tylko efekt uboczny blokady przewijania: `openGlobalSearch()` ustawia na <body> `position: fixed` z ujemnym `top`, co łamie `position: sticky` paska — <body> przestaje być kontenerem scrollującym, więc pasek wraca na swoją pozycję w dokumencie i na przewiniętej stronie wypada poza kadr. Przywrócenie stanu siedziało dodatkowo w `setTimeout(..., 350)`, więc pasek wracał dopiero PO zwinięciu okna, zamiast równolegle z nim. Na czas trwania modala przypinamy pasek ręcznie (`global-search-pinned` → `position: fixed`, z kompensacją `padding-top` na <body>, żeby treść widoczna przez rozmyte tło nie podskoczyła) i dopiero wtedy wysuwamy go klasą `global-search-hidden` (`translateY(-100%)` + `opacity: 0`). Asymetria czasów jest w czystym CSS, bez dodatkowych timerów: przejście używa `transition-delay` stanu DOCELOWEGO, więc `0.1s` na regule bazowej dotyczy powrotu paska, a `0s` w `.global-search-hidden` — chowania. Pasek wraca teraz równolegle ze zwijaniem okna. Uwzględnia `prefers-reduced-motion: reduce`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A3baC9RxFJRjzXA6yiUrF3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Po naciśnięciu
/paseknav.sticky-headerznikał skokowo, a poESCwracał dopiero po zwinięciu okna wyszukiwania. Wyglądało to na brak animacji, ale przyczyna jest inna.openGlobalSearch()blokuje przewijanie klasycznym scroll-lockiem:To łamie
position: stickypaska (top_bar.scss):<body>przestaje być kontenerem scrollującym, więc pasek wraca na swoją pozycję w dokumencie — czyli poza górną krawędź, jeśli strona była przewinięta. Przy scrollu 0 błąd był niewidoczny, stąd łatwo go było przeoczyć.Przywrócenie stanu siedziało dodatkowo w
setTimeout(..., 350), czyli wykonywało się po zakończeniucollapseToButton— stąd sekwencyjność przy zamykaniu.Rozwiązanie
Na czas trwania modala pasek przechodzi pod ręczną kontrolę:
.global-search-pinned→position: fixed; top: 0(zastępuje niedziałającesticky), z kompensacjąpadding-topna<body>, żeby treść widoczna przez rozmyte tło nie podskoczyła o wysokość paska;.global-search-hidden→translateY(-100%)+opacity: 0, przejście 250 msease-out.Przy zamykaniu klasa chowająca znika na początku
closeGlobalSearch(), więc pasek wjeżdża równolegle ze zwijaniem okna. Odpięcie idzie w tej samej klatce cowindow.scrollTo— pasek przypięty (fixed,top: 0) istickyprzytop: 0są w tym samym miejscu, więc przełączenie jest niewidoczne.Asymetria czasów bez timerów
Chowanie ma ruszać natychmiast, powrót — z lekkim opóźnieniem. Załatwione czystym CSS, bo przejście używa
transition-*stanu docelowego:Dlaczego
void nav.offsetHeightBez tego obie klasy trafiłyby do jednego przeliczenia stylu, element nigdy nie miałby stanu początkowego i pasek znikałby skokowo — dokładnie tak jak przed zmianą. Linijka wygląda na martwy zapis, więc ma w kodzie komentarz wyjaśniający.
Uwzględnione
prefers-reduced-motion: reduce.Uwaga o
position: fixed<nav>jest bezpośrednim dzieckiem<body>(base.html:229), abodymaposition: relativeprzez@extend .gradient-background. To bezpieczne — containing block dlafixedtworzą tylkotransform,filter,perspective,containiwill-change, nieposition. Przypięty pasek pozostaje względem viewportu także wtedy, gdy scroll-lock ustawibody { position: fixed }.Testy
src/integration_tests/test_global_search.py— 3 passed (strona renderuje się bez błędów,/otwiera okno, wyniki się ładują,ENTERnawiguje).Sam ruch animacji nie jest pokryty testem — świadoma decyzja, weryfikacja wizualna jest ręczna.
Jak sprawdzić ręcznie
uv run run-site run --from-dump ~/db-backup-20260428-093811.pg_dumpPrzewiń stronę w dół przed naciśnięciem
/— przy scrollu 0 różnicy nie widać.Warto zerknąć na dwie rzeczy: czy treść pod rozmytym tłem nie drga przy otwieraniu (kompensacja
padding-top) i czy nie ma przeskoku w chwili oddania paska z powrotem podstickyprzy zamykaniu.Strojenie to dwie liczby w
top_bar.scss:0.25s(czas) i0.1s(opóźnienie powrotu).🤖 Generated with Claude Code
https://claude.ai/code/session_01A3baC9RxFJRjzXA6yiUrF3