From 9cca7559fb10b30771b8f5a2fefe313b5852469d Mon Sep 17 00:00:00 2001 From: Vitalii Pikozh Date: Thu, 7 Aug 2025 20:41:06 +0300 Subject: [PATCH 01/14] set loading and loaded classes to main content --- website/modules/asset/ui/src/scss/_base.scss | 9 +++++++++ .../modules/case-studies-page/views/index.html | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/website/modules/asset/ui/src/scss/_base.scss b/website/modules/asset/ui/src/scss/_base.scss index fc1d7330..162bd847 100644 --- a/website/modules/asset/ui/src/scss/_base.scss +++ b/website/modules/asset/ui/src/scss/_base.scss @@ -177,3 +177,12 @@ .breadcrumb-link:hover { text-decoration: underline; } + +#page-main_content.loading { + opacity: 0; + transition: opacity 0.3s ease-in-out; +} + +#page-main_content.loaded { + opacity: 1; +} diff --git a/website/modules/case-studies-page/views/index.html b/website/modules/case-studies-page/views/index.html index 0202ffe7..4b00f729 100644 --- a/website/modules/case-studies-page/views/index.html +++ b/website/modules/case-studies-page/views/index.html @@ -6,7 +6,9 @@ data-default-visible-tags="{{ data.defaultVisibleTagsCount }}" >
-
{% area data.page, 'main' %}
+
+ {% area data.page, 'main' %} +
@@ -295,6 +297,17 @@

{{ article.portfolioTitle }}

+ {% endblock main %} From 33a5ae44e81ce6330cfbf16bb9dc0f0a75e6b0e7 Mon Sep 17 00:00:00 2001 From: Vitalii Pikozh Date: Thu, 14 Aug 2025 12:37:14 +0300 Subject: [PATCH 02/14] feat: implement breadcrumbs visibility control and prevent content flash - Add breadcrumbs functionality with hidden/visible classes - Implement DOM content loading script for breadcrumbs - Update layout.html to handle breadcrumbs visibility - Modify case-studies-page to control breadcrumbs display - Update CSS for better content visibility control --- website/modules/asset/ui/src/scss/_base.scss | 11 ++-- website/modules/asset/ui/src/scss/_cases.scss | 1 - .../case-studies-page/views/index.html | 12 ++-- website/views/fragments/fragments.html | 55 ++++++++++--------- website/views/layout.html | 18 +++++- 5 files changed, 59 insertions(+), 38 deletions(-) diff --git a/website/modules/asset/ui/src/scss/_base.scss b/website/modules/asset/ui/src/scss/_base.scss index 162bd847..6fe07930 100644 --- a/website/modules/asset/ui/src/scss/_base.scss +++ b/website/modules/asset/ui/src/scss/_base.scss @@ -178,11 +178,14 @@ text-decoration: underline; } -#page-main_content.loading { +.hidden { opacity: 0; - transition: opacity 0.3s ease-in-out; + overflow: hidden; + visibility: hidden; } - -#page-main_content.loaded { +.visible { opacity: 1; + + overflow: visible; + visibility: visible; } 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 4b00f729..73da11c5 100644 --- a/website/modules/case-studies-page/views/index.html +++ b/website/modules/case-studies-page/views/index.html @@ -6,7 +6,7 @@ data-default-visible-tags="{{ data.defaultVisibleTagsCount }}" >
-
+ @@ -302,11 +302,13 @@

{{ article.portfolioTitle }}

if (container) { window.addEventListener('load', () => { - console.log('Page loaded, updating class…'); - container.classList.remove('loading'); - container.classList.add('loaded'); - }); + container.classList.remove('hidden'); + container.classList.add('visible'); + }); + + } + diff --git a/website/views/fragments/fragments.html b/website/views/fragments/fragments.html index d1271277..1e291621 100644 --- a/website/views/fragments/fragments.html +++ b/website/views/fragments/fragments.html @@ -32,30 +32,31 @@

© {{ data.currentYear or '2025' }} S&F

{% endfragment %} {% fragment breadcrumbs() %} {% if data.page._url != -data.home._url %} - -{% endif %} {% endfragment %} + data.home._url %} + + {% endif %} {% endfragment %} + \ No newline at end of file diff --git a/website/views/layout.html b/website/views/layout.html index 7bc6d4a1..56c0d8e3 100644 --- a/website/views/layout.html +++ b/website/views/layout.html @@ -33,7 +33,7 @@ {% endif %} > {% render fragments.breadcrumbs() %} -
+ {# Close .bp-wrapper #} {% endblock %} From 38fc58354d8712a2da9f1f680e4a108df2790757 Mon Sep 17 00:00:00 2001 From: Vitalii Pikozh Date: Thu, 14 Aug 2025 12:47:16 +0300 Subject: [PATCH 03/14] use DOMContentLoaded instead load --- website/modules/case-studies-page/views/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/modules/case-studies-page/views/index.html b/website/modules/case-studies-page/views/index.html index 73da11c5..89f12621 100644 --- a/website/modules/case-studies-page/views/index.html +++ b/website/modules/case-studies-page/views/index.html @@ -301,7 +301,7 @@

{{ article.portfolioTitle }}

const container = document.getElementById('page-main_content'); if (container) { - window.addEventListener('load', () => { + window.addEventListener('DOMContentLoaded', () => { container.classList.remove('hidden'); container.classList.add('visible'); }); From 64f74235ad1052f2d1fd89539ea8090e6aa6026e Mon Sep 17 00:00:00 2001 From: Vitalii Pikozh Date: Thu, 14 Aug 2025 14:10:19 +0300 Subject: [PATCH 04/14] remove debuging console.log --- website/views/layout.html | 1 - 1 file changed, 1 deletion(-) diff --git a/website/views/layout.html b/website/views/layout.html index 56c0d8e3..5e5eae27 100644 --- a/website/views/layout.html +++ b/website/views/layout.html @@ -51,7 +51,6 @@ const breadcrumbs = document.querySelector('.breadcrumb'); const container = document.querySelector('.sf-container'); if (breadcrumbs) { - console.log('Script in breadcrumbs'); breadcrumbs.classList.remove('hidden'); breadcrumbs.classList.add('visible'); } From b9ad348b7199d395721322d43ce12b9f987b3217 Mon Sep 17 00:00:00 2001 From: Vitalii Pikozh Date: Thu, 14 Aug 2025 22:22:04 +0300 Subject: [PATCH 05/14] rename css classes --- .cursor/rules/common | 2 +- website/modules/asset/ui/src/scss/_base.scss | 4 +- .../case-studies-page/views/index.html | 16 ++-- website/views/fragments/fragments.html | 92 +++++++++++-------- website/views/layout.html | 81 ++++++++-------- 5 files changed, 106 insertions(+), 89 deletions(-) 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/scss/_base.scss b/website/modules/asset/ui/src/scss/_base.scss index 6fe07930..0fd030e1 100644 --- a/website/modules/asset/ui/src/scss/_base.scss +++ b/website/modules/asset/ui/src/scss/_base.scss @@ -178,12 +178,12 @@ text-decoration: underline; } -.hidden { +.loading { opacity: 0; overflow: hidden; visibility: hidden; } -.visible { +.loaded { opacity: 1; overflow: visible; diff --git a/website/modules/case-studies-page/views/index.html b/website/modules/case-studies-page/views/index.html index 89f12621..b61bfb27 100644 --- a/website/modules/case-studies-page/views/index.html +++ b/website/modules/case-studies-page/views/index.html @@ -6,7 +6,11 @@ data-default-visible-tags="{{ data.defaultVisibleTagsCount }}" >
- {# Close .bp-wrapper #} {% endblock %} From a39528d71b33eb27dfad61a6697f0bac26dd35f2 Mon Sep 17 00:00:00 2001 From: Vitalii Pikozh Date: Thu, 14 Aug 2025 22:56:17 +0300 Subject: [PATCH 07/14] Update layout.html to prevent content flash --- website/views/layout.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/website/views/layout.html b/website/views/layout.html index 60a41d96..63c7ca19 100644 --- a/website/views/layout.html +++ b/website/views/layout.html @@ -48,10 +48,10 @@ -
- {# Close .bp-wrapper #} {% endblock %} - + {% render fragments.breadcrumbs() %} +
+ {% endblock %} + + {% block main %} + {# Usually, your page templates in the @apostrophecms/pages module will override this block. It is safe to assume this is where your + page-specific content should go. #} + {% endblock %} + + {% block afterMain %} +
+ + {% render fragments.footer() %} + + +
+{# Close .bp-wrapper #} {% endblock %} From e8bc4508a1187c57773536e6d7ef6ce4a9bf7ede Mon Sep 17 00:00:00 2001 From: Vitalii Pikozh Date: Fri, 15 Aug 2025 00:52:05 +0300 Subject: [PATCH 09/14] fix stucture of layout --- website/views/layout.html | 116 +++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/website/views/layout.html b/website/views/layout.html index f978f728..9ce25e7d 100644 --- a/website/views/layout.html +++ b/website/views/layout.html @@ -5,70 +5,70 @@ {% set title = data.piece.title or data.page.title %} {% block title %} - {{ title }} + {{ title }} {% if not title %} - {{ apos.log('Looks like you forgot to override the title block in a template that does not have access to an Apostrophe page or -piece.') }} + {{ apos.log('Looks like you forgot to override the title block in a template that does not have access to an Apostrophe page or piece.') }} {% endif %} {% endblock %} -{# ✅ Add favicon in the head section #} +{# ✅ Add favicon in the section #} {% block extraHead %} - + {% component '@apostrophecms/seo:tagManagerHead' with data %} - {% endblock %} -{% block beforeMain %} +{% endblock %} + +{% block beforeMain %} {% component '@apostrophecms/seo:tagManagerBody' with data %} -Skip to content -
- {% render fragments.header() %} -
Skip to content +
- {% render fragments.breadcrumbs() %} -
- {% endblock %} + {% render fragments.header() %} +
+ {% render fragments.breadcrumbs() %} +
+{% endblock %} - {% block main %} - {# Usually, your page templates in the @apostrophecms/pages module will override this block. It is safe to assume this is where your - page-specific content should go. #} - {% endblock %} - - {% block afterMain %} -
-
- {% render fragments.footer() %} - - -
-{# Close .bp-wrapper #} {% endblock %} +{% block main %} + {# Usually, your page templates in the @apostrophecms/pages module will override this block. It is safe to assume this is where your page-specific content should go. #} +{% endblock %} + +{% block afterMain %} +
+
+ {% render fragments.footer() %} + + +
+{# Close .bp-wrapper #} +{% endblock %} From 4e6667673c33e7d2847da3b9816aee08a7060125 Mon Sep 17 00:00:00 2001 From: Vitalii Pikozh Date: Sat, 16 Aug 2025 12:43:30 +0300 Subject: [PATCH 10/14] fix --- website/views/layout.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/website/views/layout.html b/website/views/layout.html index 9ce25e7d..482787f4 100644 --- a/website/views/layout.html +++ b/website/views/layout.html @@ -21,17 +21,17 @@ {% component '@apostrophecms/seo:tagManagerBody' with data %} Skip to content
+ class="bp-wrapper relative" + data-barba="wrapper" +> {% render fragments.header() %}
{% render fragments.breadcrumbs() %} From 7bb6d8a3edd6b3db80da86190006232a6ffd18b3 Mon Sep 17 00:00:00 2001 From: Vitalii Pikozh Date: Sat, 16 Aug 2025 14:34:09 +0300 Subject: [PATCH 11/14] create revealLoaded --- website/modules/asset/ui/src/index.js | 50 ++++++++++--------- .../modules/asset/ui/src/scss/_animation.scss | 37 ++++++++++++++ website/modules/asset/ui/src/scss/_base.scss | 11 ---- .../case-studies-page/views/index.html | 10 ---- website/views/layout.html | 21 ++------ 5 files changed, 67 insertions(+), 62 deletions(-) diff --git a/website/modules/asset/ui/src/index.js b/website/modules/asset/ui/src/index.js index 511d5494..bcd691c0 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,12 +102,10 @@ 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 @@ -175,16 +183,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,6 +195,10 @@ function initBarbaPageTransitions() { link.classList.add('active'); } }); + + revealLoaded(); + + initFilterModal(); }); }); } @@ -259,17 +266,13 @@ function initFilterModal() { document.addEventListener('DOMContentLoaded', initFilterModal); -if (typeof barba !== 'undefined') { - barba.hooks.after(() => { - initFilterModal(); - }); -} - export default () => { initConfiguration(); initializeAllComponents(); + document.addEventListener('DOMContentLoaded', revealLoaded); + apos.util.onReady(() => { initCaseStudiesFilterHandler(); }); @@ -281,14 +284,13 @@ export default () => { // 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/_base.scss b/website/modules/asset/ui/src/scss/_base.scss index 43721dff..fc1d7330 100644 --- a/website/modules/asset/ui/src/scss/_base.scss +++ b/website/modules/asset/ui/src/scss/_base.scss @@ -177,14 +177,3 @@ .breadcrumb-link:hover { text-decoration: underline; } - -.loading { - opacity: 0; - overflow: hidden; - visibility: hidden; -} -.loaded { - opacity: 1; - overflow: visible; - visibility: visible; -} diff --git a/website/modules/case-studies-page/views/index.html b/website/modules/case-studies-page/views/index.html index 495a4ed8..80e6780b 100644 --- a/website/modules/case-studies-page/views/index.html +++ b/website/modules/case-studies-page/views/index.html @@ -301,17 +301,7 @@

{{ article.portfolioTitle }}

-
-{# Close .bp-wrapper #} + {# Close .bp-wrapper #} {% endblock %} From e8cc54ce2d3402d3ea41a856101aae804ff4a3fd Mon Sep 17 00:00:00 2001 From: Vitalii Pikozh Date: Sat, 16 Aug 2025 14:47:44 +0300 Subject: [PATCH 12/14] =?UTF-8?q?feat:=20replace=20inline=20hidden?= =?UTF-8?q?=E2=86=92visible=20with=20centralized=20loading=E2=86=92loaded?= =?UTF-8?q?=20handler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- website/modules/asset/ui/src/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/website/modules/asset/ui/src/index.js b/website/modules/asset/ui/src/index.js index bcd691c0..d593483e 100644 --- a/website/modules/asset/ui/src/index.js +++ b/website/modules/asset/ui/src/index.js @@ -271,7 +271,11 @@ export default () => { initializeAllComponents(); - document.addEventListener('DOMContentLoaded', revealLoaded); + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', revealLoaded); + } else { + revealLoaded(); + } apos.util.onReady(() => { initCaseStudiesFilterHandler(); From 34b4648ee9bb2e5a85bb5161c7d6554a203a8b64 Mon Sep 17 00:00:00 2001 From: Vitalii Pikozh Date: Sat, 16 Aug 2025 15:02:03 +0300 Subject: [PATCH 13/14] delete unnecessary comments from case-studies-page --- website/modules/asset/ui/src/index.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/website/modules/asset/ui/src/index.js b/website/modules/asset/ui/src/index.js index d593483e..d815a7a5 100644 --- a/website/modules/asset/ui/src/index.js +++ b/website/modules/asset/ui/src/index.js @@ -108,14 +108,11 @@ function initBarbaPageTransitions() { apos.util.onReady(() => { 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) { @@ -123,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(); @@ -285,7 +281,6 @@ export default () => { initAnchorNavigation(); initMenuToggle(); - // Case studies anchor fix setTimeout(() => { const { pathname, search, hash } = window.location; if ( From 1a59ad3dc1ad67eceea2d35af92a5e6cc1da7a0a Mon Sep 17 00:00:00 2001 From: Vitalii Pikozh Date: Sat, 16 Aug 2025 16:11:50 +0300 Subject: [PATCH 14/14] clean up index.js --- website/modules/asset/ui/src/index.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/website/modules/asset/ui/src/index.js b/website/modules/asset/ui/src/index.js index d815a7a5..c1b76b97 100644 --- a/website/modules/asset/ui/src/index.js +++ b/website/modules/asset/ui/src/index.js @@ -164,7 +164,6 @@ function initBarbaPageTransitions() { cacheIgnore: false, preventRunning: true, timeout: 10000, - transitions: [ { sync: false, @@ -193,13 +192,13 @@ function initBarbaPageTransitions() { }); revealLoaded(); - - initFilterModal(); + if (!window.caseStudiesFilterModal) { + initFilterModal(); + } }); }); } -// Anchor Navigation function initAnchorNavigation() { const anchors = document.querySelectorAll('a[href^="#"]'); if (!anchors.length) return; @@ -219,7 +218,6 @@ function initAnchorNavigation() { function initMenuToggle() { apos.util.onReady(() => { - // Menu Open const menuButton = document.getElementById('nav-icon'); const menu = document.querySelector('[data-menu]'); @@ -230,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', () => { @@ -243,7 +240,6 @@ function initMenuToggle() { }); } -// Filter Case Studies modal for Case Studies mobile page function initFilterModal() { if (!document.querySelector('.cs_list')) { return; @@ -260,7 +256,11 @@ function initFilterModal() { }); } -document.addEventListener('DOMContentLoaded', initFilterModal); +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initFilterModal); +} else { + initFilterModal(); +} export default () => { initConfiguration();