diff --git a/assets/css/frontend/homepage-fixed/ajax-tab-error-state.css b/assets/css/frontend/homepage-fixed/ajax-tab-error-state.css index 86ebd3e8..8065e566 100644 --- a/assets/css/frontend/homepage-fixed/ajax-tab-error-state.css +++ b/assets/css/frontend/homepage-fixed/ajax-tab-error-state.css @@ -61,10 +61,6 @@ display: none; } - /* Card mode: 2 columns */ - .aksrt-homepage__posts[data-view="card"] > .posts-item { - width: calc(50% - 16px); - } } /* ================================================================ @@ -102,7 +98,11 @@ display: none; } - /* Card mode: 2 columns (match Zibll) */ + /* Zibll keeps article cards in two columns throughout the mobile range. */ + .aksrt-homepage__posts[data-view="card"] { + margin: -5px; + } + .aksrt-homepage__posts[data-view="card"] > .posts-item { width: calc(50% - 10px); margin: 5px; @@ -196,16 +196,6 @@ font-size: 12px; } - /* Card mode: single column */ - .aksrt-homepage__posts[data-view="card"] { - margin: 0; - } - - .aksrt-homepage__posts[data-view="card"] > .posts-item { - width: 100%; - margin: 0 0 10px; - } - /* Tab skeleton: adapt */ .aksrt-homepage__tab-skeleton-thumb { width: 96px; diff --git a/assets/js/homepage-fixed.js b/assets/js/homepage-fixed.js index 57eaeb32..e7fc03cb 100644 --- a/assets/js/homepage-fixed.js +++ b/assets/js/homepage-fixed.js @@ -816,7 +816,27 @@ return (activeBtn && activeBtn.getAttribute('data-view-mode')) || getViewMode(); } - applyViewMode(buttons, getPostsContainers(), getViewMode()); + var initialMode = getViewMode(); + var activePanel = getActivePanel(stream); + var renderedMode = activePanel ? activePanel.getAttribute('data-view') : ''; + applyViewMode(buttons, getPostsContainers(), initialMode); + + // The persisted preference may differ from the server-rendered mode. + // Class toggling alone leaves list-only markup and its `.flex` utility in + // place, which forces a supposed card to occupy a full row. Fetch the + // matching renderer immediately so DOM and visual mode stay atomic. + if (activePanel && renderedMode !== initialMode) { + requestHomepagePanel(activePanel, { + termId: getPanelTermId(activePanel), + page: 1, + perPage: getHomepagePerPage(activePanel), + sort: getCurrentSort(stream), + viewMode: initialMode, + panel: activePanel.getAttribute('data-home-tab-panel') || 'latest', + source: 'home', + tabOrderby: getPanelTabOrderby(activePanel) + }); + } buttons.forEach(function (btn) { btn.addEventListener('click', function () { diff --git a/tests/widget-system/post-visual-contract.test.cjs b/tests/widget-system/post-visual-contract.test.cjs index a485895f..185c2450 100644 --- a/tests/widget-system/post-visual-contract.test.cjs +++ b/tests/widget-system/post-visual-contract.test.cjs @@ -24,6 +24,8 @@ test('post list DOM follows the Zibll flex and multi-image contract', () => { test('homepage card mode keeps the Zibll inline-block three-column flow', () => { const css = read('assets/css/frontend/homepage-fixed/base-2.css'); + const responsive = read('assets/css/frontend/homepage-fixed/ajax-tab-error-state.css'); + const homepageScript = read('assets/js/homepage-fixed.js'); const scripts = read('src/Core/ScriptsPart1b.php'); const cardModeStart = css.indexOf('.aksrt-homepage__posts[data-view="card"] {'); const cardItemStart = css.indexOf('.aksrt-homepage__posts[data-view="card"] > .posts-item {'); @@ -41,6 +43,22 @@ test('homepage card mode keeps the Zibll inline-block three-column flow', () => assert.match(scripts, /\$homepage_style_parts\s*=\s*\[/); assert.match(scripts, /filemtime\(\$part_path\)/); assert.doesNotMatch(scripts, /wp_enqueue_style\(\s*'aksrt-homepage-fixed',\s*\$base_uri\s*\.\s*'\/assets\/css\/frontend\/homepage-fixed\.css'/); + + const tabletStart = responsive.indexOf('@media (max-width: 991.98px)'); + const mobileStart = responsive.indexOf('@media (max-width: 767px)'); + const smallMobileStart = responsive.indexOf('@media (max-width: 640px)'); + const tablet = responsive.slice(tabletStart, mobileStart); + const mobile = responsive.slice(mobileStart, smallMobileStart); + const smallMobile = responsive.slice(smallMobileStart); + + assert.doesNotMatch(tablet, /data-view="card"/); + assert.match(mobile, /data-view="card"[\s\S]*?width:\s*calc\(50% - 10px\)/); + assert.match(mobile, /data-view="card"[\s\S]*?margin:\s*-5px/); + assert.doesNotMatch(smallMobile, /data-view="card"[\s\S]*?width:\s*100%/); + + assert.match(homepageScript, /var initialMode = getViewMode\(\)/); + assert.match(homepageScript, /var renderedMode = activePanel \? activePanel\.getAttribute\('data-view'\)/); + assert.match(homepageScript, /renderedMode !== initialMode[\s\S]*?requestHomepagePanel\(activePanel/); }); test('site shell has one float owner and fluid zones sit outside main', () => {