From e1d596751af6c7333af81c801fa7a02463ceb871 Mon Sep 17 00:00:00 2001 From: popovskik Date: Sat, 1 Aug 2026 20:30:47 +0200 Subject: [PATCH] Pagination fixes, blog page chooser, Events & Projects redesign MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pagination - Fix the broken mobile layout on News & Projects: page numbers on top, Previous / Next side-by-side below (shared .pagination component) - Add a page chooser to the Blog: rewrite blog-filter.js to combine the topic filter with client-side pagination (page size 6), add the pager markup (all 3 languages) and .blog-pagination styles; it auto-hides when a topic has one page Events & Projects — match the Blog/News design - Hero: uppercase letter-spaced eyebrow, sentence-case bold title, lead subtitle, soft gradient; drop the redundant hero subscribe form and the placeholder copy (signup still available in the bottom newsletter CTA); align MK/SI titles to "Events & projects" - Filters: News-style pills (dark active), left-aligned, with the thin separator line below; .filter-inner wrapper aligns pills/separator with the grid - Spacing: reduce the gap under the header, add space below the filter so the separator / Events sub-filter no longer collide with "All our projects" (these hero/spacing tweaks also tidy the shared About/Get-to-know/ Timeline heroes) Co-Authored-By: Claude Opus 4.8 (1M context) --- blog-filter.js | 85 ++++++++++++++++++++++++++--- css/pages/_blog.css | 10 ++++ css/pages/_projects.css | 118 ++++++++++++++++++++-------------------- en/blog/index.html | 5 ++ en/projects/index.html | 37 ++++++------- mk/blog/index.html | 5 ++ mk/projects/index.html | 37 ++++++------- si/blog/index.html | 5 ++ si/projects/index.html | 37 ++++++------- 9 files changed, 213 insertions(+), 126 deletions(-) diff --git a/blog-filter.js b/blog-filter.js index 7aafb2aa..c79d0906 100644 --- a/blog-filter.js +++ b/blog-filter.js @@ -1,22 +1,91 @@ -/* Blog topic filter: chips toggle which cards are shown. No dependencies. */ +/* Blog: topic filter + client-side pagination (they work together). + Chips toggle the visible topic; the pager pages through the matches. */ (function () { var list = document.querySelector('.blog-list'); if (!list) return; - var chips = list.querySelectorAll('.blog-chip'); - var cards = list.querySelectorAll('.blog-card'); + var chips = [].slice.call(list.querySelectorAll('.blog-chip')); + var cards = [].slice.call(list.querySelectorAll('.blog-card')); + var pager = list.querySelector('.blog-pagination'); + var numbers = pager ? pager.querySelector('.pagination-numbers') : null; + var prevBtn = pager ? pager.querySelector('[data-nav="prev"]') : null; + var nextBtn = pager ? pager.querySelector('[data-nav="next"]') : null; + var pageSize = pager ? (parseInt(pager.getAttribute('data-page-size'), 10) || 6) : 6; - function apply(topic) { - cards.forEach(function (card) { - var show = topic === 'all' || card.getAttribute('data-topic') === topic; - card.hidden = !show; + var state = { topic: 'all', page: 1 }; + + function matching() { + return cards.filter(function (c) { + return state.topic === 'all' || c.getAttribute('data-topic') === state.topic; }); } + // Compact list of page tokens: numbers and 'dots'. + function tokens(total, cur) { + if (total <= 7) { + var all = []; + for (var i = 1; i <= total; i++) all.push(i); + return all; + } + var set = { 1: 1, 2: 1 }; + set[total] = 1; set[total - 1] = 1; + set[cur] = 1; set[cur - 1] = 1; set[cur + 1] = 1; + var pages = Object.keys(set).map(Number).filter(function (n) { return n >= 1 && n <= total; }).sort(function (a, b) { return a - b; }); + var out = []; + for (var j = 0; j < pages.length; j++) { + if (j > 0 && pages[j] - pages[j - 1] > 1) out.push('dots'); + out.push(pages[j]); + } + return out; + } + + function buildPager(total) { + if (!pager) return; + if (total <= 1) { pager.hidden = true; return; } + pager.hidden = false; + numbers.innerHTML = ''; + tokens(total, state.page).forEach(function (t) { + if (t === 'dots') { + var s = document.createElement('span'); + s.className = 'page-dots'; + s.textContent = '...'; + numbers.appendChild(s); + return; + } + var b = document.createElement('button'); + b.type = 'button'; + b.className = 'page-number' + (t === state.page ? ' active' : ''); + b.textContent = t; + b.addEventListener('click', function () { state.page = t; render(true); }); + numbers.appendChild(b); + }); + prevBtn.classList.toggle('disabled', state.page <= 1); + nextBtn.classList.toggle('disabled', state.page >= total); + } + + function render(scroll) { + var m = matching(); + var total = Math.max(1, Math.ceil(m.length / pageSize)); + if (state.page > total) state.page = total; + if (state.page < 1) state.page = 1; + var start = (state.page - 1) * pageSize; + var end = start + pageSize; + cards.forEach(function (c) { c.hidden = true; }); + m.slice(start, end).forEach(function (c) { c.hidden = false; }); + buildPager(total); + if (scroll) list.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + chips.forEach(function (chip) { chip.addEventListener('click', function () { chips.forEach(function (c) { c.classList.remove('is-active'); }); chip.classList.add('is-active'); - apply(chip.getAttribute('data-topic')); + state.topic = chip.getAttribute('data-topic'); + state.page = 1; + render(false); }); }); + if (prevBtn) prevBtn.addEventListener('click', function () { if (state.page > 1) { state.page--; render(true); } }); + if (nextBtn) nextBtn.addEventListener('click', function () { state.page++; render(true); }); + + render(false); })(); diff --git a/css/pages/_blog.css b/css/pages/_blog.css index 68670c29..c2a00bac 100644 --- a/css/pages/_blog.css +++ b/css/pages/_blog.css @@ -176,3 +176,13 @@ .blog-hero h1 { font-size: 30px; } .blog-grid { columns: 1; } } + +/* Pagination — reuses the shared .pagination look; reset button chrome. + Topic filter + client-side paging are handled by blog-filter.js. */ +.blog-pagination { margin-top: 40px; } +.blog-pagination .pagination-arrow, +.blog-pagination .page-number { + background: transparent; + border: none; + font-family: inherit; +} diff --git a/css/pages/_projects.css b/css/pages/_projects.css index aa43b0ab..25feec8a 100644 --- a/css/pages/_projects.css +++ b/css/pages/_projects.css @@ -19,8 +19,10 @@ } .page-header-section { - padding: 96px 0; - background: #FFFFFF; + background: linear-gradient(180deg, #FFF7F2 0%, #FFFFFF 100%); + /* .page-content already offsets the fixed 80px header, so this top value + is the actual visible gap under the menu — keep it small. */ + padding: 40px 24px 44px; text-align: center; } @@ -28,30 +30,34 @@ display: flex; flex-direction: column; align-items: center; - gap: 24px; - max-width: 960px; + gap: 14px; + max-width: 760px; } +/* Eyebrow — uppercase, letter-spaced, like the News/Blog hero */ .page-subtitle { - font-weight: 600; - font-size: 16px; - color: #FA7850; + display: inline-block; + font-weight: 700; + font-size: 14px; + letter-spacing: 0.06em; + text-transform: uppercase; + color: #E8833A; } .page-header-section h1 { - font-weight: 600; - font-size: 48px; - line-height: 60px; - letter-spacing: -0.02em; + font-weight: 700; + font-size: 42px; + line-height: 1.12; color: #101828; margin: 0; + max-width: 760px; } .page-description { - font-size: 20px; - line-height: 30px; - color: #667085; - max-width: 768px; + font-size: 18px; + line-height: 28px; + color: #475467; + max-width: 640px; margin: 0; } @@ -107,67 +113,60 @@ /* 1b. Filter kategorij (pill navigacija + podfiltri) */ +/* Filter bar — left-aligned pills with a thin separator, like the News hub. + .filter-inner mirrors the posts container so the pills/separator line up + with the grid below. */ .filter-section { - padding: 0 24px 44px; - margin-top: -40px; + padding: 8px 80px 40px; /* bottom gap so the separator/sub-filter clears "All our projects" */ +} +.filter-inner { + max-width: 1280px; + margin: 0 auto; + padding: 0 32px; display: flex; flex-direction: column; - align-items: center; - gap: 20px; + gap: 16px; } -/* Zunanja "pill" navigacija (glavne kategorije) */ .filter-nav { display: flex; + flex-wrap: wrap; align-items: center; - gap: 4px; - max-width: 100%; - padding: 6px; - background: #F9FAFB; - border-radius: 999px; - box-shadow: 0px 8px 30px rgba(16, 24, 40, 0.06); - overflow-x: auto; - scrollbar-width: none; - -ms-overflow-style: none; + gap: 10px; + padding-bottom: 24px; + border-bottom: 1px solid #EAECF0; /* thin, near-transparent separator */ } -.filter-nav::-webkit-scrollbar { display: none; } .filter-pill { - flex: 0 0 auto; - display: inline-flex; - align-items: center; - justify-content: center; - height: 40px; - padding: 0 20px; - border: none; - background: transparent; - border-radius: 999px; font-family: inherit; font-size: 14px; font-weight: 600; line-height: 1; - color: #344054; + color: #475467; + background: #F2F4F7; + border: 1px solid transparent; + border-radius: 999px; + padding: 9px 16px; white-space: nowrap; cursor: pointer; - transition: color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease; + transition: background 0.15s ease, color 0.15s ease; } .filter-pill:hover { - color: #2D738C; + background: #E4E7EC; } .filter-pill.active { - color: #2D738C; - background: #FFFFFF; - box-shadow: 0px 1px 3px rgba(16, 24, 40, 0.1), 0px 1px 2px rgba(16, 24, 40, 0.06); + background: #101828; + color: #FFFFFF; } -/* Notranja vrstica s podfiltri (npr. vrste dogodkov) */ +/* Sub-filter row (e.g. event types) — sits under the pills, left aligned */ .filter-subnav { display: flex; flex-wrap: wrap; align-items: center; - justify-content: center; + justify-content: flex-start; gap: 12px; } .filter-subnav[hidden] { display: none; } @@ -321,12 +320,12 @@ } .page-header-section { - padding: 64px 24px; + padding: 32px 20px 28px; } .page-header-section h1 { - font-size: 32px; - line-height: 40px; + font-size: 30px; + line-height: 1.15; } .page-description { @@ -344,16 +343,16 @@ } .filter-section { - padding: 0 16px 28px; - margin-top: -24px; - align-items: stretch; - gap: 16px; + padding: 8px 20px 32px; + } + .filter-inner { + padding: 0; + gap: 14px; } - /* Na mobilnem se glavna navigacija vodoravno pomika */ .filter-nav { justify-content: flex-start; - border-radius: 12px; + padding-bottom: 20px; } .filter-subnav { @@ -381,11 +380,14 @@ } .pagination { - flex-direction: column; - gap: 24px; + flex-wrap: wrap; + gap: 20px; } + /* Numbers on their own row on top; Previous / Next share the row below */ .pagination-numbers { order: -1; + flex-basis: 100%; + justify-content: center; } } \ No newline at end of file diff --git a/en/blog/index.html b/en/blog/index.html index af5d7948..d9d9f76b 100644 --- a/en/blog/index.html +++ b/en/blog/index.html @@ -263,6 +263,11 @@ + diff --git a/en/projects/index.html b/en/projects/index.html index 71fa9c16..0027d513 100644 --- a/en/projects/index.html +++ b/en/projects/index.html @@ -148,31 +148,28 @@
Our projects -

Events & Projects

-

Subscribe to learn about new product features, the latest in technology, solutions, and updates.

- -

We care about your data in our privacy policy

+

Events & projects

+

The events, projects and moments that bring the Macedonian student community in Slovenia together.

- -
diff --git a/mk/blog/index.html b/mk/blog/index.html index 7fc0dca5..a958ea30 100644 --- a/mk/blog/index.html +++ b/mk/blog/index.html @@ -263,6 +263,11 @@ + diff --git a/mk/projects/index.html b/mk/projects/index.html index 0b518d56..d5a0d949 100644 --- a/mk/projects/index.html +++ b/mk/projects/index.html @@ -148,31 +148,28 @@
Наши проекти -

Проекти

-

Претплатете се за да дознаете за новите функции на производите, најновите технологии, решенија и ажурирања.

- -

Ние се грижиме за вашите податоци во нашата политика за приватност

+

Настани и проекти

+

Настаните, проектите и моментите што ја зближуваат македонската студентска заедница во Словенија.

- -
diff --git a/si/blog/index.html b/si/blog/index.html index 28b1273f..a83bc99f 100644 --- a/si/blog/index.html +++ b/si/blog/index.html @@ -263,6 +263,11 @@ + diff --git a/si/projects/index.html b/si/projects/index.html index c17f8018..44dd5522 100644 --- a/si/projects/index.html +++ b/si/projects/index.html @@ -148,31 +148,28 @@
Naši projekti -

Projekti

-

Naročite se in bodite na tekočem z novimi funkcijami, najnovejšimi tehnologijami, rešitvami in posodobitvami.

- -

Skrbimo za vaše podatke v naši politiki zasebnosti.

+

Dogodki in projekti

+

Dogodki, projekti in trenutki, ki povezujejo makedonsko študentsko skupnost v Sloveniji.

- -