diff --git a/.cursor/rules/common b/.cursor/rules/common index 0048a591..402558c9 160000 --- a/.cursor/rules/common +++ b/.cursor/rules/common @@ -1 +1 @@ -Subproject commit 0048a59175d3774a9ed517c1fe8ade681d8cea42 +Subproject commit 402558c9424d32857338fd40a8c52f63050e424b diff --git a/website/modules/asset/ui/src/index.js b/website/modules/asset/ui/src/index.js index 511d5494..c1b76b97 100644 --- a/website/modules/asset/ui/src/index.js +++ b/website/modules/asset/ui/src/index.js @@ -12,7 +12,19 @@ import { setupTagSearchForInput } from './searchInputHandler'; import { FilterModal } from './filterModal'; import { initClientSideFiltering } from './clientSideFiltering'; -/* eslint-enable sort-imports */ +function revealLoaded() { + document + .querySelectorAll( + '.breadcrumb.loading, .sf-container.loading, .page-main_content.loading', + ) + .forEach((el) => { + el.classList.remove('loading'); + el.classList.add('loaded'); + if (el.hasAttribute('aria-busy')) { + el.setAttribute('aria-busy', 'false'); + } + }); +} function initConfiguration() { window.DEFAULT_VISIBLE_TAGS_COUNT = 5; @@ -57,13 +69,11 @@ function initFontChanger() { setInterval(() => { currentFontIndex = (currentFontIndex + 1) % fonts.length; - // Use Array.prototype.at() for safer array access const currentFont = fonts.at(currentFontIndex); heroContent.style.fontFamily = currentFont; }, 500); } -// Tag search filter for case studies page function initCaseStudiesTagFilter({ inputSelector = '.tag-search', containerSelector = '.filter-section', @@ -92,22 +102,17 @@ function initializeAllComponents() { initClientSideFiltering(); } -// Barba pages function initBarbaPageTransitions() { if (!document.querySelector('[data-barba="container"]')) return; apos.util.onReady(() => { - // Initialize case studies filter handler initCaseStudiesFilterHandler(); - // Original Barba enter callback const originalEnterCallback = function (data, hasFilterAnchor) { - // Scroll to the top after page transition (unless we have a filter anchor) if (!hasFilterAnchor) { window.scrollTo(0, 0); } - // Close menu if it's open const menuButton = document.getElementById('nav-icon'); const menu = document.querySelector('[data-menu]'); if (menuButton && menu) { @@ -115,7 +120,6 @@ function initBarbaPageTransitions() { menuButton.classList.remove('open'); } - // Trigger video play after transition const video = data.next.container.querySelector('video'); if (video) { video.play(); @@ -160,7 +164,6 @@ function initBarbaPageTransitions() { cacheIgnore: false, preventRunning: true, timeout: 10000, - transitions: [ { sync: false, @@ -175,16 +178,11 @@ function initBarbaPageTransitions() { ], }); - // Add after hook for updating menu state barba.hooks.after(() => { // Update menu active state const currentPath = window.location.pathname; const menuLinks = document.querySelectorAll('.sf-nav__list a'); - - // First, remove active class from all menu items menuLinks.forEach((link) => link.classList.remove('active')); - - // Then, add active class to the current menu item menuLinks.forEach((link) => { const href = link.getAttribute('href'); const hrefPath = new URL(href, window.location.origin).pathname; @@ -192,11 +190,15 @@ function initBarbaPageTransitions() { link.classList.add('active'); } }); + + revealLoaded(); + if (!window.caseStudiesFilterModal) { + initFilterModal(); + } }); }); } -// Anchor Navigation function initAnchorNavigation() { const anchors = document.querySelectorAll('a[href^="#"]'); if (!anchors.length) return; @@ -216,7 +218,6 @@ function initAnchorNavigation() { function initMenuToggle() { apos.util.onReady(() => { - // Menu Open const menuButton = document.getElementById('nav-icon'); const menu = document.querySelector('[data-menu]'); @@ -227,7 +228,6 @@ function initMenuToggle() { menuButton.classList.toggle('open'); }); - // Close menu when clicking on menu items for non-logged users const menuLinks = menu.querySelectorAll('a'); menuLinks.forEach((link) => { link.addEventListener('click', () => { @@ -240,7 +240,6 @@ function initMenuToggle() { }); } -// Filter Case Studies modal for Case Studies mobile page function initFilterModal() { if (!document.querySelector('.cs_list')) { return; @@ -257,12 +256,10 @@ function initFilterModal() { }); } -document.addEventListener('DOMContentLoaded', initFilterModal); - -if (typeof barba !== 'undefined') { - barba.hooks.after(() => { - initFilterModal(); - }); +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initFilterModal); +} else { + initFilterModal(); } export default () => { @@ -270,6 +267,12 @@ export default () => { initializeAllComponents(); + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', revealLoaded); + } else { + revealLoaded(); + } + apos.util.onReady(() => { initCaseStudiesFilterHandler(); }); @@ -278,17 +281,15 @@ export default () => { initAnchorNavigation(); initMenuToggle(); - // Case studies anchor fix setTimeout(() => { const { pathname, search, hash } = window.location; - const isCasesPage = pathname.includes('/cases'); - const hasFilterParams = - search.includes('industry') || - search.includes('stack') || - search.includes('caseStudyType') || - hash.includes('filter'); - - if (isCasesPage && hasFilterParams) { + if ( + pathname.includes('/cases') && + (search.includes('industry') || + search.includes('stack') || + search.includes('caseStudyType') || + hash.includes('filter')) + ) { const filterAnchor = document.getElementById('filter'); if (filterAnchor) filterAnchor.scrollIntoView({ behavior: 'smooth' }); } diff --git a/website/modules/asset/ui/src/scss/_animation.scss b/website/modules/asset/ui/src/scss/_animation.scss index 1d4cef9d..a2f81eca 100644 --- a/website/modules/asset/ui/src/scss/_animation.scss +++ b/website/modules/asset/ui/src/scss/_animation.scss @@ -55,3 +55,40 @@ filter: blur(0); } } + +// Loading/Loaded states for reveal animations +.loading { + opacity: 0; + overflow: hidden; + visibility: hidden; + transform: translateY(20px); + transition: + opacity 0.6s ease-out, + transform 0.6s ease-out; +} + +.loaded { + opacity: 1; + overflow: visible; + visibility: visible; + transform: translateY(0); +} + +// Specific loading states for breadcrumbs and containers +.breadcrumb.loading, +.sf-container.loading { + opacity: 0 !important; + visibility: hidden !important; + transform: translateY(15px); + transition: + opacity 0.5s ease-out, + visibility 0.5s ease-out, + transform 0.5s ease-out; +} + +.breadcrumb.loaded, +.sf-container.loaded { + opacity: 1 !important; + visibility: visible !important; + transform: translateY(0); +} diff --git a/website/modules/asset/ui/src/scss/_cases.scss b/website/modules/asset/ui/src/scss/_cases.scss index 3172ece0..87bba548 100644 --- a/website/modules/asset/ui/src/scss/_cases.scss +++ b/website/modules/asset/ui/src/scss/_cases.scss @@ -7,7 +7,6 @@ &_content { display: flex; flex-direction: column; - gap: 2rem; margin-bottom: 3rem; } diff --git a/website/modules/case-studies-page/views/index.html b/website/modules/case-studies-page/views/index.html index 0202ffe7..80e6780b 100644 --- a/website/modules/case-studies-page/views/index.html +++ b/website/modules/case-studies-page/views/index.html @@ -6,7 +6,13 @@ data-default-visible-tags="{{ data.defaultVisibleTagsCount }}" >