Skip to content

fix(global_search): szkło nad nieruchomą stroną i okno bez zapadania - #800

Open
mpasternak wants to merge 3 commits into
devfrom
worktree-topbar-animacja
Open

fix(global_search): szkło nad nieruchomą stroną i okno bez zapadania#800
mpasternak wants to merge 3 commits into
devfrom
worktree-topbar-animacja

Conversation

@mpasternak

@mpasternak mpasternak commented Sep 6, 2026

Copy link
Copy Markdown
Member

Problem

  1. Po / szare, rozmyte szkło wskakiwało w jednej klatce, a na przewiniętej stronie pasek nawigacji znikał skokowo.
  2. Po ESC (w pierwszej wersji tego PR) pasek wjeżdżał w zarezerwowane miejsce, pod nim była biała szczelina i breadcrumbs, a szczelina znikała skokowo na końcu animacji.
  3. Podczas wpisywania okno wyszukiwania zapadało się do pustego rozmiaru i odrastało przy każdym dopisanym lub skasowanym znaku.

Przyczyny

  • Blokada przewijania body { position: fixed; top: -Npx } łamała position: sticky paska i breadcrumbs (_breadcrumbs.scss). Oba wracały na swoje pozycje w dokumencie. Pierwsza wersja PR ratowała tylko pasek (fixed + padding-top na body), stąd szczelina.
  • .global-search-modal było przełączane z display: none, a od display: none przejście CSS nie startuje, więc transition: opacity było martwe.
  • Style modala były zdublowane: inline w global_search_modal.html i w top_bar.scss. Wersja inline wygrywała w kaskadzie, więc strojenie SCSS nic nie dawało.
  • performSearch() zastępował listę wyników napisem „Wyszukiwanie...”, więc okno spadało do min-height: 300px.

Rozwiązanie

Szkło i pasek (697a08d98)

  • Blokada przewijania to klasa global-search-open na <html> z overflow: hidden, a przy klasycznym (niezerowym) pasku przewijania dodatkowo scrollbar-gutter: stable. <body> jest nietknięte, sticky działa, nie trzeba scrollTo ani kompensacji.
  • Szkło korzysta z opacity + visibility (przy chowaniu visibility jest opóźnione o czas wygaszania). Czas 0,35 s jest wspólny z animacją okna, bez setTimeout w JS.
  • Usunięte: przypinanie paska (global-search-pinned / global-search-hidden), kompensacja paddingu i zdublowany CSS animacji. Keyframes okna przeniosłem z wersji inline, więc wygląd okna się nie zmienia.
  • Przy prefers-reduced-motion zostaje samo przejście szkła, bez skalowania okna.

Okno bez zapadania (2cef2d429)

  • Poprzednie wyniki zostają do nadejścia nowych: są przygaszane z opóźnieniem 150 ms, więc szybka odpowiedź nie przygasza wcale. Postęp pokazuje pasek wewnątrz pola, który nie zmienia wysokości. aria-busy działa jak wcześniej.
  • Podświetlenie trafia do HTML-a od razu przy renderowaniu, zamiast przebudowy każdej pozycji z mignięciem po 100 ms.
  • Zapytanie krótsze niż 3 znaki przerywa żądanie w toku, żeby spóźniona odpowiedź nie nadpisała pomocy.

Testy

src/integration_tests/test_global_search.py: 3 nowe testy Playwright, zielone lokalnie na chromium, firefox i webkit (9/9), cały plik na chromium 6/6.

  • test_global_search_does_not_move_page_layout: pozycja paska, breadcrumbs i scrollY są identyczne w każdej klatce otwarcia, stanu otwartego i zamknięcia (w tym kółko nad tłem i PageDown przy otwartym oknie).
  • test_global_search_backdrop_fades_gradually: szkło ma pośrednie krycie przy otwieraniu i przy zamykaniu.
  • test_global_search_dialog_does_not_collapse_while_next_search_loads: wstrzymane odpowiedzi autocomplete, wysokość okna mierzona w każdej klatce.

Na kodzie sprzed zmian testy padały z oczekiwanych powodów: breadcrumbs 58 → 117 px, okno 547 → 300 px, krycie szkła od razu 1. Sprawdzone mutacje: powrót do display: none, blokada na <body>, brak overflow: hidden, placeholder „Wyszukiwanie...”. Każda wywraca właściwy test.

uv run pytest src/integration_tests/test_global_search.py --browser chromium --browser firefox --browser webkit

Nie sprawdzone

  • iOS/iPadOS na prawdziwym urządzeniu (WebKit w Playwright to nie iOS Safari).
  • Długie opisy bibliograficzne z prawdziwej bazy (test używa krótkich etykiet).

Jak sprawdzić ręcznie

uv run run-site run --from-dump <dump bazy>
  • Przewiń stronę przed naciśnięciem /: przy scrollu 0 różnicy nie widać.
  • Potem ESC i obserwacja paska oraz breadcrumbs.
  • Na koniec wpisz frazę (np. test), Backspace i dopisz znak: okno nie powinno się zapadać.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Tu4mhWdY4zbQ82N74krLqZ

mpasternak and others added 3 commits September 6, 2026 06:57
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
…ać pasek

- blokada przewijania przez `overflow: hidden` na <html> zamiast
  `position: fixed` na <body>, które łamało `position: sticky` paska
  i breadcrumbs (biała szczelina i skok po ESC),
- szkło pojawia się i gaśnie przez `opacity` + `visibility`; od
  `display: none` przejście CSS nigdy nie startowało,
- okno i szkło mają wspólny czas 0.35s, bez setTimeout w JS,
- usunięty zdublowany CSS animacji z szablonu (wygrywał z SCSS),
- testy Playwright: układ strony w każdej klatce animacji oraz płynne
  krycie szkła; zweryfikowane na chromium, firefox i webkit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tu4mhWdY4zbQ82N74krLqZ
Każde nowe zapytanie zamieniało listę wyników na napis "Wyszukiwanie...",
więc okno spadało do min-height (300px) i odrastało po odpowiedzi — przy
każdym dopisanym lub skasowanym znaku.

- poprzednie wyniki zostają do nadejścia nowych: przygaszone (z 150ms
  opóźnieniem, szybka odpowiedź nie przygasza wcale), postęp to pasek
  wewnątrz pola, więc nic nie zmienia wysokości; aria-busy bez zmian,
- podświetlanie trafia do HTML-a od razu przy renderowaniu, zamiast
  przebudowywać każdą pozycję z mignięciem krycia po 100ms,
- nowa grupa wyników wchodzi od poziomu przygaszenia (0.5), bez slajdu,
- zapytanie krótsze niż 3 znaki przerywa żądanie w toku, żeby spóźniona
  odpowiedź nie nadpisała pomocy,
- test Playwright wstrzymuje odpowiedzi autocomplete i mierzy wysokość
  okna w każdej klatce; chromium, firefox, webkit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tu4mhWdY4zbQ82N74krLqZ
@mpasternak mpasternak changed the title feat(top_bar): animowane chowanie paska przy oknie wyszukiwania fix(global_search): szkło nad nieruchomą stroną i okno bez zapadania Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant