diff --git a/src/components/ContentGrid.astro b/src/components/ContentGrid.astro index b453d25..1d3f9ab 100644 --- a/src/components/ContentGrid.astro +++ b/src/components/ContentGrid.astro @@ -11,7 +11,8 @@ export interface Props { hasNextPage: boolean; endCursor: string | null; }; - perLoad?: number; + perLoad?: number; // Больше не используется, но оставляем для обратной совместимости + gridColumns?: 3 | 4; } const { @@ -20,13 +21,15 @@ const { type = 'latest', slug = '', pageInfo = { hasNextPage: false, endCursor: null }, - perLoad = 11 + perLoad = 11, // Игнорируется + gridColumns = 4 } = Astro.props; +// Конфиг без perLoad, так как будем вычислять на клиенте const loadMoreConfig = { type, slug, - perLoad + gridColumns }; function getCoauthorsNames(coauthors: any[]): string { @@ -35,17 +38,22 @@ function getCoauthorsNames(coauthors: any[]): string { return coauthors .map((coauthor: any) => { const name = coauthor?.node?.name || coauthor?.name; - const nickname = coauthor?.node?.nickname || coauthor?.nickname; - - return name; // Возвращаем только имя, ссылки будут в шаблоне + return name; }) .filter(Boolean) .join(', '); } -function shouldBeLarge(index: number): boolean { - if (index < 8) return false; - return (index - 8) % 11 === 0; +function shouldBeLarge(index: number, columns: number): boolean { + if (columns === 4) { + // Паттерн для 4 колонок: большие на позициях 8, 19, 30, 41... + if (index < 8) return false; + return (index - 8) % 11 === 0; + } else { + // Паттерн для 3 колонок: большие на позициях 6, 14, 22, 30... + if (index < 6) return false; + return (index - 6) % 8 === 0; + } } --- @@ -56,16 +64,21 @@ function shouldBeLarge(index: number): boolean { )} -
+
{items.map((item, index) => { const postUrl = item.uri || `/blog/${item.databaseId}`; const postDate = new Date(item.date); - const isLarge = shouldBeLarge(index); + const isLarge = shouldBeLarge(index, gridColumns); return (
)} - - {item.categories?.nodes?.[0] && ( - - )} + {item.categories?.nodes?.[0] && ( + + )}
- - - {pageInfo.hasNextPage && (
)} \ No newline at end of file diff --git a/src/components/Header/HeaderLine.astro b/src/components/Header/HeaderLine.astro new file mode 100644 index 0000000..f06ec50 --- /dev/null +++ b/src/components/Header/HeaderLine.astro @@ -0,0 +1,11 @@ +--- +import CurrentDate from '@components/Header/CurrentDate.astro'; +--- + +
+
+ +
+
+
+
\ No newline at end of file diff --git a/src/components/NewsSingle.astro b/src/components/NewsSingle.astro index 7e6e460..e4d89c6 100644 --- a/src/components/NewsSingle.astro +++ b/src/components/NewsSingle.astro @@ -90,7 +90,7 @@ const { post, pageInfo } = Astro.props; + + + diff --git a/src/layouts/MainLayout.astro b/src/layouts/MainLayout.astro index 5f759dc..3303f16 100644 --- a/src/layouts/MainLayout.astro +++ b/src/layouts/MainLayout.astro @@ -3,8 +3,8 @@ const { title, description, category, contentType } = Astro.props; import Header from '../components/Header/Header.astro'; -import Header_lite from '../components/Header/Header_lite.astro'; -import CurrentDate from '../components/Header/CurrentDate.astro'; +import HeaderLine from '../components/Header/HeaderLine.astro'; + import Footer from '../components/Footer.astro'; import '../styles/global.css'; @@ -20,13 +20,7 @@ import '../styles/global.css'; -
-
- -
-
-
-
+
diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro index 840a1df..a13fc19 100644 --- a/src/pages/[...slug].astro +++ b/src/pages/[...slug].astro @@ -1,5 +1,5 @@ --- -import MainLayout from '@layouts/MainLayout.astro'; +import ContentLayout from '@layouts/ContentLayout.astro'; import NewsSingle from '@components/NewsSingle.astro'; import ContentGrid from '@components/ContentGrid.astro'; @@ -58,7 +58,7 @@ if (pageInfo.type === 'single') { //одиночная статья //); --- - )} - + diff --git a/src/pages/articles/index.astro b/src/pages/articles/index.astro index 53eb678..06af93a 100644 --- a/src/pages/articles/index.astro +++ b/src/pages/articles/index.astro @@ -1,6 +1,6 @@ --- -import MainLayout from '@layouts/MainLayout.astro'; +import ContentLayout from '@layouts/ContentLayout.astro'; import ContentGrid from '@components/ContentGrid.astro'; import { getLatestPosts } from '@api/posts.js'; @@ -13,7 +13,7 @@ export const prerender = false; --- - @@ -24,9 +24,10 @@ export const prerender = false; items={posts} pageInfo={pageInfo} type="latest" + gridColumns={3} perLoad={11} showCount={false} /> - \ No newline at end of file + \ No newline at end of file diff --git a/src/pages/news/[...slug].astro b/src/pages/news/[...slug].astro index b902aa1..e14d39d 100644 --- a/src/pages/news/[...slug].astro +++ b/src/pages/news/[...slug].astro @@ -1,5 +1,5 @@ --- -import MainLayout from '@layouts/MainLayout.astro'; +import ContentLayout from '@layouts/ContentLayout.astro'; import NewsSingle from '@components/NewsSingle.astro'; import { detectPageType } from '@lib/detect-page-type'; @@ -48,7 +48,7 @@ if (import.meta.env.DEV) { } --- - )} - + diff --git a/src/pages/news/index.astro b/src/pages/news/index.astro index e021b7a..ff2ee34 100644 --- a/src/pages/news/index.astro +++ b/src/pages/news/index.astro @@ -1,10 +1,10 @@ --- -import MainLayout from '@layouts/MainLayout.astro'; +import ContentLayout from '@layouts/ContentLayout.astro'; --- - diff --git a/src/styles/components/ContentGrid.css b/src/styles/components/ContentGrid.css index 83bced4..e119aa6 100644 --- a/src/styles/components/ContentGrid.css +++ b/src/styles/components/ContentGrid.css @@ -24,15 +24,33 @@ padding-top: 20px; } -/* Сетка постов */ -.posts-grid { +/* ===== СЕТКИ С РАЗНЫМ КОЛИЧЕСТВОМ КОЛОНОК ===== */ + +/* Сетка на 4 колонки (по умолчанию) */ +.posts-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--grid-gap); width: 100%; } -/* Карточка поста - базовые стили */ +/* Сетка на 3 колонки */ +.posts-grid-3 { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--grid-gap); + width: 100%; +} + +/* Базовый класс для обратной совместимости */ +.posts-grid { + display: grid; + gap: var(--grid-gap); + width: 100%; +} + +/* ===== КАРТОЧКИ ПОСТОВ ===== */ + .post-card { background: white; border-radius: var(--border-radius); @@ -44,16 +62,7 @@ display: flex; flex-direction: column; height: 0; - padding-bottom: 100%; /* Aspect ratio hack для надежности */ -} - -/* Большие карточки (десктоп) */ -@media (min-width: 1200px) { - .post-card-large { - grid-column: span 2; - aspect-ratio: 2 / 1; - padding-bottom: 50%; - } + padding-bottom: 100%; } /* Hover эффекты */ @@ -66,15 +75,6 @@ transform: scale(1.05); } -/* Ссылка карточки */ -.post-card-link { - position: absolute; - inset: 0; - display: block; - text-decoration: none; - color: inherit; -} - /* Контейнер изображения */ .post-image-container { position: absolute; @@ -97,8 +97,6 @@ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } - - /* Оверлей с контентом */ .post-content-overlay { position: absolute; @@ -118,10 +116,6 @@ gap: 8px; } - - - - .post-meta-overlay { margin-bottom: 3px; } @@ -145,11 +139,6 @@ text-overflow: ellipsis; } -.category-badge-white{ - background-color: white; - color: black; -} - .author-name { font-size: 12px; color: rgba(255, 255, 255, 0.85); @@ -157,41 +146,36 @@ font-weight: 400; } -/* Убедитесь что индикаторы не занимают лишнее место */ -#infinity-scroll-sentinel { - height: 1px; - width: 100%; - visibility: hidden; - pointer-events: none; +.author-link { + color: white; + text-decoration: none; + border-bottom: 1px solid rgba(255, 255, 255, 0.3); + transition: border-color var(--transition-speed) ease; } -.loading-indicator { - text-align: center; - padding: 40px 0; - color: #666; - min-height: auto; /* ← Важно! */ +.author-link:hover { + border-bottom-color: white; } -.no-more-posts { - text-align: center; - padding: 30px 0; - color: #666; - font-size: 16px; - border-top: 1px solid #eee; - margin-top: 20px; - min-height: auto; /* ← Важно! */ -} +/* ===== АДАПТИВНОСТЬ ДЛЯ РАЗНЫХ ЭКРАНОВ ===== */ - - - -/* Улучшения для больших карточек */ +/* Десктоп (1200px и больше) */ @media (min-width: 1200px) { - .post-card-large .post-category-badge { - font-size: 12px; - padding: 6px 12px; + /* Для сетки 4 колонки - большие карточки на 2 колонки */ + .posts-grid-4 .post-card-large { + grid-column: span 2; + aspect-ratio: 2 / 1; + padding-bottom: 50%; } + /* Для сетки 3 колонки - большие карточки на 2 колонки */ + .posts-grid-3 .post-card-large { + grid-column: span 2; + aspect-ratio: 2 / 1; + padding-bottom: 50%; + } + + /* Улучшения для больших карточек */ .post-card-large .post-content-overlay { padding: var(--overlay-padding-large); gap: 10px; @@ -212,27 +196,35 @@ } } -/* Ноутбуки: 3 колонки */ +/* Ноутбуки (992px - 1199px) */ @media (min-width: 992px) and (max-width: 1199px) { - .posts-grid { + /* Все сетки переходят на 3 колонки */ + .posts-grid-4, + .posts-grid-3 { grid-template-columns: repeat(3, 1fr); } - .post-card-large { + /* Большие карточки становятся обычными */ + .posts-grid-4 .post-card-large, + .posts-grid-3 .post-card-large { grid-column: span 1; aspect-ratio: 1 / 1; padding-bottom: 100%; } } -/* Планшеты: 2 колонки */ +/* Планшеты (768px - 991px) */ @media (min-width: 768px) and (max-width: 991px) { - .posts-grid { + /* Все сетки переходят на 2 колонки */ + .posts-grid-4, + .posts-grid-3 { grid-template-columns: repeat(2, 1fr); gap: var(--grid-gap-tablet); } - .post-card-large { + /* Большие карточки становятся обычными */ + .posts-grid-4 .post-card-large, + .posts-grid-3 .post-card-large { grid-column: span 1; aspect-ratio: 1 / 1; padding-bottom: 100%; @@ -243,18 +235,16 @@ } } -/* Мобильные: 1 колонка */ +/* Мобильные (до 767px) */ @media (max-width: 767px) { - .posts-grid { + /* Все сетки переходят на 1 колонку */ + .posts-grid-4, + .posts-grid-3 { grid-template-columns: 1fr; gap: var(--grid-gap-tablet); } - .post-card { - aspect-ratio: 2 / 1; - padding-bottom: 50%; - } - + .post-card, .post-card-large { aspect-ratio: 2 / 1; padding-bottom: 50%; @@ -275,16 +265,9 @@ .post-title-overlay { font-size: 15px; } - - .post-category-badge { - top: 12px; - right: 12px; - font-size: 10px; - padding: 4px 8px; - } } -/* Очень маленькие экраны */ +/* Очень маленькие экраны (до 480px) */ @media (max-width: 480px) { .post-card, .post-card-large { @@ -300,33 +283,22 @@ .post-title-overlay { font-size: 14px; } - - .post-category-badge { - top: 10px; - right: 10px; - padding: 3px 6px; - font-size: 9px; - } } -/* Вспомогательные классы */ -.sr-only { - position: absolute; - width: 1px; +/* ===== ИНДИКАТОРЫ ЗАГРУЗКИ ===== */ + +#infinity-scroll-sentinel { height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border: 0; + width: 100%; + visibility: hidden; + pointer-events: none; } -/* Состояния загрузки */ .loading-indicator { text-align: center; padding: 40px 0; color: #666; + min-height: auto; } .loading-spinner { @@ -352,6 +324,21 @@ font-size: 16px; border-top: 1px solid #eee; margin-top: 20px; + min-height: auto; +} + +/* ===== ВСПОМОГАТЕЛЬНЫЕ КЛАССЫ ===== */ + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; } .no-posts { @@ -361,6 +348,7 @@ font-size: 18px; } +/* Мобильные адаптации для индикаторов */ @media (max-width: 767px) { .loading-spinner { width: 30px; @@ -370,4 +358,4 @@ .no-more-posts { padding: 20px 0; } -} +} \ No newline at end of file