Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Pasek nawigacji chowa się i wraca płynną animacją przy otwieraniu oraz
zamykaniu okna wyszukiwania globalnego, zamiast znikać i pojawiać się skokowo.
43 changes: 43 additions & 0 deletions src/bpp/static/scss/top_bar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,49 @@ nav.sticky-header {
z-index: 2000; // Must be highest to ensure dropdown appears above all sticky elements
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);

// Chowanie paska na czas otwartego okna wyszukiwania globalnego.
//
// Modal blokuje przewijanie ustawiajac na <body> `position: fixed`
// z ujemnym `top` (global_search_modal.html). To lamie `position:
// sticky` powyzej: <body> przestaje byc kontenerem scrollujacym, wiec
// pasek wraca na swoja pozycje w dokumencie i - gdy strona byla
// przewinieta - znika skokowo za gorna krawedzia. Dlatego na czas
// trwania modala przypinamy go recznie klasa `global-search-pinned`
// i dopiero wtedy mozemy go plynnie wysunac klasa
// `global-search-hidden`. Obie klasy zdejmuje `closeGlobalSearch()`.
//
// `position: fixed` jest tu wzgledem viewportu, bo zaden przodek
// (<html>, <body>) nie ma transform/filter/perspective/contain -
// samo `position: relative`/`fixed` na <body> containing blocku dla
// fixed nie tworzy.
transition: transform 0.25s ease-out, opacity 0.25s ease-out;

// Opoznienie dotyczy stanu DOCELOWEGO przejscia, czyli powrotu paska:
// wjezdza chwile po starcie zwijania okna, zamiast scigac sie z nim.
transition-delay: 0.1s;

&.global-search-pinned {
position: fixed;
top: 0;
left: 0;
right: 0;
}

&.global-search-hidden {
transform: translateY(-100%);
opacity: 0;
pointer-events: none;

// Chowanie ma ruszac natychmiast, rownolegle z rozwijaniem okna.
transition-delay: 0s;
}
}

@media (prefers-reduced-motion: reduce) {
nav.sticky-header {
transition: none;
}
}

.top-bar {
Expand Down
37 changes: 37 additions & 0 deletions src/django_bpp/templates/global_search_modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,12 @@ <h3>Jak wyszukiwać?</h3>
// Save scroll position and block background scrolling
scrollPosition = window.pageYOffset || document.documentElement.scrollTop;

// Zmierz pasek nawigacji ZANIM cokolwiek ruszymy - za chwile
// wypadnie z flow i jego wysokosc bedzie potrzebna do
// kompensacji na <body>.
var nav = document.querySelector('nav.sticky-header');
var navHeight = nav ? nav.offsetHeight : 0;

// Lock the body completely
document.body.style.position = 'fixed';
document.body.style.top = '-' + scrollPosition + 'px';
Expand All @@ -490,6 +496,19 @@ <h3>Jak wyszukiwać?</h3>
// Also lock html element for extra security
document.documentElement.style.overflow = 'hidden';

// Przypnij pasek nawigacji do viewportu i wysun go poza kadr.
// Blokada scrolla powyzej (body -> position: fixed) lamie jego
// `position: sticky`, wiec bez tego pasek znikalby skokowo;
// klasy sa zdejmowane w closeGlobalSearch(). Reflow miedzy
// klasami jest konieczny: bez niego przegladarka scala oba
// zapisy stylu w jeden i przejscia nie ma.
if (nav) {
nav.classList.add('global-search-pinned');
document.body.style.paddingTop = navHeight + 'px';
void nav.offsetHeight;
nav.classList.add('global-search-hidden');
}

// Remove previous animation classes
container.classList.remove('animating-out');

Expand Down Expand Up @@ -622,11 +641,19 @@ <h3>Jak wyszukiwać?</h3>
window.closeGlobalSearch = function() {
var modal = document.getElementById('globalSearchModal');
var container = document.querySelector('.global-search-container');
var nav = document.querySelector('nav.sticky-header');

// Add closing animation
container.classList.add('animating-out');
modal.classList.add('closing');

// Pasek wjezdza ROWNOLEGLE ze zwijaniem okna, nie po nim.
// Wlasne opoznienie 0.1s ma w CSS (top_bar.scss), zeby ruch nie
// startowal dokladnie w tej samej klatce co collapseToButton.
if (nav) {
nav.classList.remove('global-search-hidden');
}

// After animation completes, hide modal and restore scrolling
setTimeout(function() {
modal.classList.remove('show', 'closing');
Expand All @@ -647,6 +674,16 @@ <h3>Jak wyszukiwać?</h3>
// Restore scroll position
window.scrollTo(0, scrollPosition);

// Oddaj pasek z powrotem `position: sticky`. Musi to isc w
// tej samej klatce co przywrocenie scrolla powyzej: pasek
// przypiety (fixed, top 0) i sticky przy top 0 sa w tym
// samym miejscu, wiec przelaczenie jest niewidoczne, a
// kompensacja paddingu znika razem z powrotem nav do flow.
if (nav) {
nav.classList.remove('global-search-pinned');
document.body.style.paddingTop = '';
}

// Reset container styles for next opening
container.style.transform = '';
container.style.opacity = '';
Expand Down