| Форум » Флуд » Общение » Поговорим о... |
| Поговорим о... |
Понедельник, 2026-01-12, 13:41
# 2
Понял! Нужно решение, где вся информация хранится прямо на страницах контента, а не в отдельных data-файлах. Вот несколько чистых вариантов:
Вариант 1: Улучшенный shortcode прямо в Markdown (самый простой) Создайте файл layouts/shortcodes/cardinfo.html: ```html {{/* cardinfo.html */}} {{ $link := .Get "link" }} {{ $title := .Get "title" }} {{ $desc := .Get "desc" | default "Описание отсутствует" }} {{ $date := .Get "date" | default "Дата не указана" }} {{ $audience := .Get "audience" | default "Для всех сотрудников" }} <div class="info-card"> <a href="{{ $link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <span class="info-card-title">{{ $title }}</span> <div class="info-card-tooltip-wrapper"> <span class="info-card-icon" data-description="{{ $desc }}" data-date="{{ $date }}" data-audience="{{ $audience }}"> ℹ️ </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ $desc }}</div> <div class="tooltip-details"> <div class="tooltip-date">📅 Добавлено: {{ $date }}</div> <div class="tooltip-audience">👥 Для кого: {{ $audience }}</div> </div> </div> </div> </div> </a> </div> ``` CSS (добавьте в ваш основной CSS файл): ```css /* Стили для информационных карточек */ .info-card { margin: 1rem 0; border: 1px solid #e1e8ed; border-radius: 10px; background: #fff; transition: all 0.3s ease; box-shadow: 0 2px 5px rgba(0,0,0,0.05); } .info-card:hover { box-shadow: 0 5px 15px rgba(0,0,0,0.1); transform: translateY(-2px); border-color: #4a90e2; } .info-card-link { display: block; padding: 1.2rem 1.5rem; text-decoration: none; color: #2d3748; } .info-card-header { display: flex; justify-content: space-between; align-items: center; } .info-card-title { font-size: 1.1rem; font-weight: 600; flex: 1; padding-right: 15px; } .info-card-tooltip-wrapper { position: relative; } .info-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; cursor: help; color: #718096; font-size: 0.9rem; border-radius: 50%; transition: all 0.2s; } .info-card-icon:hover { background: #edf2f7; color: #4a90e2; } .info-card-tooltip { position: absolute; top: -10px; right: 100%; width: 280px; padding: 15px; background: white; border-radius: 8px; box-shadow: 0 5px 20px rgba(0,0,0,0.15); border: 1px solid #e2e8f0; z-index: 1000; opacity: 0; visibility: hidden; transform: translateX(10px); transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); pointer-events: none; } .info-card-icon:hover + .info-card-tooltip { opacity: 1; visibility: visible; transform: translateX(0); pointer-events: auto; } .tooltip-description { font-size: 0.9rem; line-height: 1.5; color: #4a5568; margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid #e2e8f0; } .tooltip-details { font-size: 0.85rem; color: #718096; } .tooltip-date { margin-bottom: 5px; display: flex; align-items: center; gap: 5px; } .tooltip-audience { display: flex; align-items: center; gap: 5px; } /* Адаптивность */ @media (max-width: 768px) { .info-card-tooltip { position: fixed; top: auto; bottom: 50px; right: 20px; left: 20px; width: auto; transform: translateY(10px); } .info-card-icon:hover + .info-card-tooltip { transform: translateY(0); } } ``` Использование в вашем Markdown файле: ```markdown --- title: Геологический отдел toc: false layout: fssd weight: 90 --- {{< cardinfo link="http://AssayMovement" title="Движение проб" desc="Отслеживание прохождения проб от отбора до получения результатов. Ежедневное обновление данных." date="15.10.2023" audience="Геологи, руководители проектов" >}} {{< cardinfo link="http://AssayMovement1" title="Движение проб - сводный отчет по действующим объектам работ" desc="Консолидированный отчет по всем активным объектам за текущий квартал с графиками и аналитикой." date="01.02.2024" audience="Начальство отдела, плановики" >}} {{< cardinfo link="http://AssayMovement2" title="Движение проб - состояние на дату" desc="Моментальный снимок состояния проб на выбранную дату. История доступна с 2020 года." date="20.11.2023" audience="Бухгалтерия, архив, аудиторы" >}} ``` Вариант 2: Использование front matter для хранения данных (более структурированный) Если у вас много карточек, можно хранить их в front matter страницы: В вашем Markdown файле: ```yaml --- title: Геологический отдел toc: false layout: fssd_with_cards weight: 90 cards: - title: "Движение проб" link: "http://AssayMovement" desc: "Отслеживание прохождения проб от отбора до получения результатов" date: "15.10.2023" audience: "Геологи, руководители" - title: "Движение проб - сводный отчет" link: "http://AssayMovement1" desc: "Консолидированный отчет по всем активным объектам" date: "01.02.2024" audience: "Начальство отдела" - title: "Наблюдатель движения шлиховых проб" link: "http://ProbeObserver" desc: "Мониторинг шлихового опробования с картографической привязкой" date: "10.03.2024" audience: "Старшие геологи" --- <!-- Контент страницы (если нужен) --> ``` Создайте шаблон layouts/fssd_with_cards/single.html: ```html {{ define "main" }} <div class="page-container"> <h1>{{ .Title }}</h1> {{ .Content }} <div class="cards-section"> {{ range .Params.cards }} <div class="info-card"> <a href="{{ .link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <span class="info-card-title">{{ .title }}</span> <div class="info-card-tooltip-wrapper"> <span class="info-card-icon"> ℹ️ </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ .desc }}</div> <div class="tooltip-details"> <div class="tooltip-date">📅 Добавлено: {{ .date }}</div> <div class="tooltip-audience">👥 Для кого: {{ .audience }}</div> </div> </div> </div> </div> </a> </div> {{ end }} </div> </div> <style> /* Тот же CSS что и выше */ </style> {{ end }} ``` Вариант 3: Комбинированный - shortcode внутри cards Если хотите сохранить ваш текущий shortcode cards: ```markdown --- title: Геологический отдел toc: false layout: fssd weight: 90 --- {{<cards cols="1">}} {{<cardinfo link="http://AssayMovement" title="Движение проб" desc="Описание системы" date="15.10.2023" audience="Геологи" >}} {{<cardinfo link="http://AssayMovement1" title="Движение проб - сводный отчет" desc="Другое описание" date="01.02.2024" audience="Руководители" >}} {{</cards>}} ``` И тогда в CSS добавьте: ```css .cards .info-card { /* Стили для совместимости с вашим текущим cards */ margin: 0.5rem; } ``` Преимущества этого подхода: 1. Всё в одном месте - данные хранятся прямо на странице 2. Простое копирование - можно легко копировать страницы и редактировать 3. Без зависимостей - не нужны отдельные data-файлы 4. Гибкость - для каждой страницы свои данные 5. Обратная совместимость - можно постепенно переделывать страницы Какой вариант вам больше подходит? Первый (только shortcode) самый быстрый для внедрения. |
Понедельник, 2026-01-12, 14:00
# 3
Отлично! Учту все ваши требования. Давайте сделаем комплексное решение:
1. Обновленный shortcode cardinfo.html ```html {{/* layouts/shortcodes/cardinfo.html */}} {{ $link := .Get "link" }} {{ $title := .Get "title" }} {{ $desc := .Get "desc" | default "Описание отсутствует" }} {{ $date := .Get "date" | default "Дата не указана" }} {{ $audience := .Get "audience" | default "Для всех сотрудников" }} {{ $tag := .Get "tag" }} {{ $tagtype := .Get "tagtype" | default "default" }} <div class="info-card" data-theme="light"> <a href="{{ $link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <span class="info-card-title">{{ $title }}</span> <div class="info-card-right-section"> {{ if $tag }} <span class="info-card-tag info-card-tag-{{ $tagtype }}"> {{ $tag }} </span> {{ end }} <div class="info-card-tooltip-wrapper"> <span class="info-card-icon"> {{ if $.Site.Params.useFontAwesome }} <i class="fas fa-info-circle"></i> {{ else if $.Site.Params.customIcons }} {{/* Используем вашу SVG иконку */}} <svg class="custom-info-icon" width="16" height="16" viewBox="0 0 16 16"> <use xlink:href="#icon-info"></use> </svg> {{ else }} {{/* Стандартная иконка */}} <svg class="default-info-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 13A6 6 0 1 1 8 2a6 6 0 0 1 0 12z"/> <path d="M7 11h2v2H7zm0-8h2v6H7z"/> </svg> {{ end }} </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ $desc }}</div> <div class="tooltip-details"> <div class="tooltip-date"> <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </svg> <span>Добавлено: {{ $date }}</span> </div> <div class="tooltip-audience"> <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"> <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/> </svg> <span>Для кого: {{ $audience }}</span> </div> </div> </div> </div> </div> </div> </a> </div> <style> /* ===== ОСНОВНЫЕ СТИЛИ ===== */ .info-card { margin: 1rem 0; border: 1px solid var(--card-border, #e1e8ed); border-radius: 10px; background: var(--card-bg, #fff); transition: all 0.3s ease; box-shadow: var(--card-shadow, 0 2px 5px rgba(0,0,0,0.05)); position: relative; overflow: hidden; } .info-card:hover { box-shadow: var(--card-hover-shadow, 0 5px 15px rgba(0,0,0,0.1)); transform: translateY(-2px); border-color: var(--card-hover-border, #4a90e2); } .info-card-link { display: block; padding: 1.2rem 1.5rem; text-decoration: none; color: var(--card-text, #2d3748); } .info-card-header { display: flex; justify-content: space-between; align-items: center; } .info-card-title { font-size: 1.1rem; font-weight: 600; flex: 1; padding-right: 15px; color: var(--card-title, #2d3748); } /* ===== ПРАВАЯ СЕКЦИЯ (тег + иконка) ===== */ .info-card-right-section { display: flex; align-items: center; gap: 10px; } /* ===== ТЕГИ ===== */ .info-card-tag { font-size: 0.75rem; padding: 0.2rem 0.6rem; border-radius: 12px; font-weight: 500; white-space: nowrap; } .info-card-tag-default { background: var(--tag-default-bg, #e2e8f0); color: var(--tag-default-text, #4a5568); border: 1px solid var(--tag-default-border, #cbd5e0); } .info-card-tag-info { background: var(--tag-info-bg, #bee3f8); color: var(--tag-info-text, #2c5282); border: 1px solid var(--tag-info-border, #90cdf4); } .info-card-tag-warning { background: var(--tag-warning-bg, #feebc8); color: var(--tag-warning-text, #975a16); border: 1px solid var(--tag-warning-border, #fbd38d); } .info-card-tag-success { background: var(--tag-success-bg, #c6f6d5); color: var(--tag-success-text, #276749); border: 1px solid var(--tag-success-border, #9ae6b4); } .info-card-tag-error { background: var(--tag-error-bg, #fed7d7); color: var(--tag-error-text, #9b2c2c); border: 1px solid var(--tag-error-border, #fc8181); } /* ===== ИКОНКА И ТУЛТИП ===== */ .info-card-tooltip-wrapper { position: relative; display: flex; align-items: center; } .info-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; cursor: help; color: var(--icon-color, #718096); border-radius: 50%; transition: all 0.2s; } .info-card-icon:hover { background: var(--icon-hover-bg, #edf2f7); color: var(--icon-hover-color, #4a90e2); } .custom-info-icon { width: 16px; height: 16px; fill: currentColor; } .default-info-icon { width: 16px; height: 16px; } /* ===== ВСПЛЫВАЮЩАЯ ПОДСКАЗКА ===== */ .info-card-tooltip { position: absolute; top: -10px; right: 100%; width: 280px; padding: 15px; background: var(--tooltip-bg, #fff); border-radius: 8px; box-shadow: var(--tooltip-shadow, 0 5px 20px rgba(0,0,0,0.15)); border: 1px solid var(--tooltip-border, #e2e8f0); z-index: 1000; opacity: 0; visibility: hidden; transform: translateX(10px); transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); pointer-events: none; } .info-card-icon:hover + .info-card-tooltip { opacity: 1; visibility: visible; transform: translateX(0); pointer-events: auto; } .tooltip-description { font-size: 0.9rem; line-height: 1.5; color: var(--tooltip-text, #4a5568); margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid var(--tooltip-divider, #e2e8f0); } .tooltip-details { font-size: 0.85rem; color: var(--tooltip-details-text, #718096); } .tooltip-date, .tooltip-audience { margin-bottom: 5px; display: flex; align-items: center; gap: 8px; } .tooltip-date svg, .tooltip-audience svg { flex-shrink: 0; opacity: 0.7; } /* ===== ТЕМНАЯ ТЕМА ===== */ @media (prefers-color-scheme: dark) { .info-card[data-theme="light"] { --card-bg: #1a202c; --card-border: #2d3748; --card-text: #e2e8f0; --card-title: #f7fafc; --card-shadow: 0 2px 5px rgba(0,0,0,0.2); --card-hover-shadow: 0 5px 15px rgba(0,0,0,0.3); --card-hover-border: #4a90e2; --tag-default-bg: #2d3748; --tag-default-text: #cbd5e0; --tag-default-border: #4a5568; --tag-info-bg: #2c5282; --tag-info-text: #bee3f8; --tag-info-border: #3182ce; --tag-warning-bg: #975a16; --tag-warning-text: #feebc8; --tag-warning-border: #d69e2e; --tag-success-bg: #276749; --tag-success-text: #c6f6d5; --tag-success-border: #38a169; --tag-error-bg: #9b2c2c; --tag-error-text: #fed7d7; --tag-error-border: #e53e3e; --icon-color: #a0aec0; --icon-hover-bg: #2d3748; --icon-hover-color: #63b3ed; --tooltip-bg: #2d3748; --tooltip-text: #e2e8f0; --tooltip-border: #4a5568; --tooltip-shadow: 0 5px 20px rgba(0,0,0,0.4); --tooltip-divider: #4a5568; --tooltip-details-text: #a0aec0; } } /* Принудительная темная тема */ .dark-mode .info-card, body[data-theme="dark"] .info-card { --card-bg: #1a202c; --card-border: #2d3748; --card-text: #e2e8f0; /* ... остальные переменные из темной темы выше ... */ } /* ===== АДАПТИВНОСТЬ ===== */ @media (max-width: 768px) { .info-card-header { flex-direction: column; align-items: flex-start; gap: 10px; } .info-card-right-section { width: 100%; justify-content: space-between; } .info-card-tooltip { position: fixed; top: auto; bottom: 50px; right: 20px; left: 20px; width: auto; max-width: calc(100vw - 40px); transform: translateY(10px); } .info-card-icon:hover + .info-card-tooltip { transform: translateY(0); } } /* ===== ПОДДЕРЖКА ВАШЕЙ ИКОНОЧНОЙ СИСТЕМЫ ===== */ /* Если используете SVG спрайты */ .icon-info { width: 16px; height: 16px; fill: currentColor; } </style> <script> // Автоматическое определение темы document.addEventListener('DOMContentLoaded', function() { const cards = document.querySelectorAll('.info-card'); // Проверяем тему документа const isDarkTheme = document.documentElement.getAttribute('data-theme') === 'dark' || document.body.classList.contains('dark-mode') || window.matchMedia('(prefers-color-scheme: dark)').matches; cards.forEach(card => { if (isDarkTheme) { card.setAttribute('data-theme', 'dark'); } }); // Обработка клика вне тултипа для мобильных устройств document.addEventListener('click', function(e) { if (!e.target.closest('.info-card-tooltip-wrapper')) { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); }); </script> ``` 2. Пример использования в Markdown ```markdown --- title: Геологический отдел layout: default --- {{< cardinfo link="http://AssayMovement" title="Движение проб" desc="Отслеживание прохождения проб от отбора до получения результатов" date="15.10.2023" audience="Геологи, руководители" tag="Лаборатория" tagtype="info" >}} {{< cardinfo link="http://AssayMovement2" title="Движение проб - состояние на дату" desc="Моментальный снимок состояния проб на выбранную дату" date="20.11.2023" audience="Бухгалтерия" tag="Важное" tagtype="warning" >}} {{< cardinfo link="http://ProbeObserver" title="Наблюдатель движения шлиховых проб" desc="Специализированный инструмент для мониторинга" date="10.03.2024" audience="Старшие геологи" tag="Новое" tagtype="success" >}} ``` 3. Если используете свою SVG иконку Добавьте в ваш основной шаблон (обычно layouts/partials/head.html или layouts/_default/baseof.html): ```html {{/* Вставка SVG спрайта с иконками */}} <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <defs> {{/* Ваша иконка info */}} <symbol id="icon-info" viewBox="0 0 16 16"> <path fill="currentColor" d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm1 12H7V7h2v5zm0-8H7V3h2v1z"/> </symbol> {{/* Другие иконки, если нужны */}} <symbol id="icon-date" viewBox="0 0 24 24"> <path fill="currentColor" d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </symbol> </defs> </svg> ``` 4. Альтернативно: если хотите использовать Font Awesome Добавьте в конфиг сайта (config.toml): ```toml [params] useFontAwesome = true ``` Ключевые особенности этого решения: 1. Поддержка тегов с разными типами (info, warning, success, error, default) 2. Темная тема через CSS variables и media query 3. Свои SVG иконки через <use xlink:href="#icon-name"> 4. Адаптивный дизайн для мобильных устройств 5. JavaScript для определения темы (необязательный, можно удалить если не нужно) 6. Все стили в одном файле - самодостаточный shortcode Если у вас уже есть система иконок, просто замените SVG path в символе #icon-info на ваш вариант. |
Понедельник, 2026-01-12, 14:10
# 4
<style> .strat-column { font-family: 'Roboto', 'Arial', sans-serif; width: 100%; max-width: 1200px; min-width: 500px; margin: 40px auto; border: 2px solid rgb(161, 161, 161); border-radius: 10px; overflow: hidden; box-shadow: 0 5px 15px rgba(0,0,0,0.08); position: relative; } .column-header2 { font-size: 1.5em; } .column-header { background: #37474F; color: white; padding: 15px 20px; text-align: center; border-bottom: 2px solid #263238; position: relative; } .column-header h2 { margin: 0; padding: 0; font-size: 1.8em; color: #ffffff; } .toggle-container { position: absolute; right: 20px; bottom: 10px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; max-width: 200px; } .toggle-label { font-size: 0.9em; color: #B0BEC5; white-space: nowrap; } .toggle-switch { position: relative; display: inline-block; width: 50px; height: 24px; } .toggle-switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #546E7A; transition: .4s; border-radius: 24px; } .slider:before { position: absolute; content: ""; height: 16px; width: 16px; left: 4px; bottom: 4px; background-color: white; transition: .4s; border-radius: 50%; } input:checked + .slider { background-color: #4CAF50; } input:checked + .slider:before { transform: translateX(26px); } .column-titles { display: flex; background: #455A64; color: white; font-weight: 500; padding: 10px 0; border-bottom: 1px solid #37474F; } .column-titles.doc-titles { background: #546E7A; margin-top: 20px; } .column-titles.doc-titles .title-col { border-bottom: none; } .title-col { padding: 5px; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; justify-content: center; } .title-col div { width: 100%; text-align: center; } .eon-title { min-width: 80px; width: 80px; margin-left: 2px; } .era-title { min-width: 60px; width: 60px; } .period-title { min-width: 150px; width: 150px; justify-content: center; text-align: center; } .epoch-title { flex: 1; padding-left: 20px; text-align: left; } .timescale-title { min-width: 120px; width: 120px; padding-left: 10px; justify-content: center; font-size: 0.85em; } .geochronological-scale { display: flex; flex-direction: column; } .eon { display: flex; border-bottom: 1px solid #e0e0e0; } .eon-name { writing-mode: vertical-rl; transform: rotate(180deg); text-align: center; padding: 25px 12px; font-weight: 500; font-size: 1.4em; letter-spacing: 1px; border-right: 1px solid #e0e0e0; min-width: 80px; width: 80px; display: flex; align-items: center; justify-content: center; line-height: 1.4; } .eon-divider { display: flex; align-items: center; padding: 10px 0; } .divider-line { flex: 1; height: 1px; background: #bdbdbd; } .divider-label { padding: 0 20px; font-weight: 500; font-size: 1.2em; } .eras { flex: 1; display: flex; flex-direction: column; } .era { position: relative; /* Добавляем для позиционирования псевдоэлемента */ border-bottom: none; /* Убираем стандартную границу */ } /* Создаем линию между эрами */ .era::after { content: ""; position: absolute; bottom: 0; left: 0; right: 0; height: 1px; background: #888888; z-index: 2; /* Линия между эрами должна быть выше */ } .era-name { writing-mode: vertical-rl; transform: rotate(180deg); text-align: center; padding: 15px 8px; font-weight: 500; font-size: 1.3em; background:#d9e1e4; border-right: 1px solid #cfd8dc; min-width: 60px; width: 60px; display: flex; align-items: center; justify-content: center; line-height: 1.2; } .periods { flex: 1; display: flex; flex-direction: column; } .period-container { display: flex; min-height: 60px; border-bottom: 1px solid #e0e0e0; position: relative; } /* Последний период в эре не должен иметь нижней линии */ .periods > .period-container:last-child::after { display: none; } /* Последняя эра в эоне не должна иметь нижней линии */ .eon > .eras > .era:last-child::after { display: none; } .period { display: flex; min-width: 150px; width: 150px; text-decoration: none; color: inherit; transition: background 0.2s ease; } .period:hover:not([href="#"]), .period:focus:not([href="#"]) { background: rgba(0,0,0,0.02); } .period[href="#"] { cursor: default; opacity: 0.8; } .period-name { padding: 12px 8px; text-align: center; border-right: 1px solid #e0e0e0; font-size: 1.1em; display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1.4; font-weight: 500; white-space: nowrap; width: 100%; box-sizing: border-box; } .epochs { flex: 1; display: flex; flex-direction: column; padding: 8px; min-width: 0; } .epoch-block { flex: 1; padding: 8px 6px; margin: 3px; text-align: center; font-size: 0.9em; font-weight: 500; border-radius: 4px; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; text-decoration: none; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.1); position: relative; overflow: hidden; min-height: 40px; background-color: #f5f5f5; color: #757575; } .epoch-block[href="#"] { cursor: default; opacity: 0.8; box-shadow: none; } .epoch-block:not([href="#"]):hover { transform: translateY(-2px); box-shadow: 0 3px 8px rgba(0,0,0,0.15), inset 0 0 0 1px rgba(0,0,0,0.1); z-index: 10; } .epoch-name { position: relative; z-index: 1; width: 100%; line-height: 1.3; } .epoch-index { white-space: nowrap; font-size: 0.9em; display: inline-flex; align-items: center; } .epoch-index sub, .epoch-index sup { font-size: 0.7em; line-height: 1; position: relative; vertical-align: baseline; } .epoch-index sub { bottom: -0.2em; } .epoch-index sup { top: -0.2em; } .index-top, .index-bottom { display: block; line-height: 1; text-align: center; } .index-top { margin-bottom: 0.5em; display: block; } .index-bottom { margin-top: -0.2em; display: block; } .timescale { min-width: 120px; width: 120px; display: flex; flex-direction: column; align-items: center; justify-content: space-around; padding: 8px 5px; } .timescale-marker { position: relative; width: 100%; text-align: center; padding: 5px 0; font-size: 0.85em; } .timescale-marker::before { content: ""; position: absolute; left: 0; top: 50%; width: 10px; height: 1px; background: #9E9E9E; } .timescale-marker::after { content: attr(data-age); position: absolute; left: 15px; top: 50%; transform: translateY(-50%); white-space: nowrap; } /* Специфичные стили для докембрия */ .precambrian-section { margin-top: 20px; } .precambrian .eras { display: flex; flex-direction: column; } .precambrian .era { border-bottom: 1px solid #e0e0e0; display: flex; } .precambrian .era-name { min-width: 60px; width: 60px; writing-mode: vertical-rl; transform: rotate(180deg); text-align: center; padding: 15px 8px; font-weight: 500; font-size: 1.3em; border-right: 1px solid #cfd8dc; display: flex; align-items: center; justify-content: center; line-height: 1.4; } .precambrian .periods { flex: 1; display: flex; flex-direction: column; } .precambrian .period-container { display: flex; min-height: 60px; border-bottom: 1px solid #e0e0e0; position: relative; } .precambrian .period { display: flex; min-width: 150px; width: 150px; text-decoration: none; color: inherit; } .precambrian .period-name { padding: 12px 8px; text-align: center; border-right: 1px solid #e0e0e0; font-size: 1.1em; display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1.4; font-weight: 500; white-space: nowrap; width: 100%; box-sizing: border-box; } .precambrian .epochs { flex: 1; display: flex; flex-direction: column; padding: 8px; min-width: 0; } .precambrian .epoch-block { flex: 1; padding: 8px 6px; margin: 3px; text-align: center; font-size: 0.9em; font-weight: 500; border-radius: 4px; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; text-decoration: none; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.1); position: relative; overflow: hidden; min-height: 40px; } .precambrian .timescale { min-width: 120px; width: 120px; display: flex; flex-direction: column; align-items: center; justify-content: space-around; padding: 8px 5px; } /* Специфичные стили для Катархея */ .hadean-period { min-height: 60px; margin: 5px; } /* Основная логика скрытия */ .epoch-block[href="#"] { display: none; } .show-hidden .epoch-block[href="#"] { display: flex !important; } /* Скрываем родительские элементы, если нет активных эпох */ .period-container:not(:has(.epoch-block:not([href="#"]))):not(.show-hidden .period-container) { display: none; } .era:not(:has(.period-container:not(:has(.epoch-block:not([href="#"]))))):not(.show-hidden .era) { display: none; } .precambrian-section:not(:has(.era:not(:has(.period-container:not(:has(.epoch-block:not([href="#"]))))))):not(.show-hidden .precambrian-section) { display: none; } .column-titles.doc-titles:not(:has(~ .precambrian-section .era:not(:has(.period-container:not(:has(.epoch-block:not([href="#"]))))))):not(.show-hidden ~ .precambrian-section) { display: none; } /* Показываем скрытые элементы при активации переключателя */ .show-hidden .period-container, .show-hidden .era, .show-hidden .eon, .show-hidden .precambrian-section, .show-hidden .doc-titles { display: flex !important; } /* Динамические цвета эпох */ .epoch-block:not([href="#"]) { background-color: var(--epoch-color); color: var(--epoch-text-color); } /* Кайнозой */ [data-epoch-name="holocene"] { --epoch-color: #FAE6CC; --epoch-text-color: #263238; } [data-epoch-name="pleistocene"] { --epoch-color: #FCEEAF; --epoch-text-color: #263238; } [data-epoch-name="gelasian"] { --epoch-color: #FCEFC0; --epoch-text-color: #263238; } [data-epoch-name="pliocene"] { --epoch-color: #FEF8B4; --epoch-text-color: #263238; } [data-epoch-name="miocene"] { --epoch-color: #FDF143; --epoch-text-color: #263238; } [data-epoch-name="oligocene"] { --epoch-color: #F4C996; --epoch-text-color: #263238; } [data-epoch-name="eocene"] { --epoch-color: #F2BE8B; --epoch-text-color: #263238; } [data-epoch-name="paleocene"] { --epoch-color: #F0B680; --epoch-text-color: #263238; } /* Мезозой */ [data-epoch-name="upper-cretaceous"] { --epoch-color: #B6D274; --epoch-text-color: #263238; } [data-epoch-name="lower-cretaceous"] { --epoch-color: #9FC97D; --epoch-text-color: #263238; } [data-epoch-name="late-jurassic"] { --epoch-color: #B5DEF7; --epoch-text-color: #263238; } [data-epoch-name="middle-jurassic"] { --epoch-color: #85CBE9; --epoch-text-color: #263238; } [data-epoch-name="early-jurassic"] { --epoch-color: #4FB1E7; --epoch-text-color: #263238; } [data-epoch-name="late-triassic"] { --epoch-color: #B79FC7; --epoch-text-color: #263238; } [data-epoch-name="middle-triassic"] { --epoch-color: #AB84B7; --epoch-text-color: #263238; } [data-epoch-name="early-triassic"] { --epoch-color: #9763A3; --epoch-text-color: white; } /* Палеозой */ [data-epoch-name="late-permian"] { --epoch-color: #FBE9C7; --epoch-text-color: #263238; } [data-epoch-name="guadalupian"] { --epoch-color: #FADFB9; --epoch-text-color: #263238; } [data-epoch-name="cisuralian"] { --epoch-color: #F9DCB7; --epoch-text-color: #263238; } [data-epoch-name="pennsylvanian"] { --epoch-color: #DDDCD5; --epoch-text-color: #263238; } [data-epoch-name="middle-carboniferous"] { --epoch-color: #BBBBBC; --epoch-text-color: #263238; } [data-epoch-name="mississippian"] { --epoch-color: #BBBBBC; --epoch-text-color: #263238; } [data-epoch-name="late-devonian"] { --epoch-color: #EFE0B3; --epoch-text-color: #263238; } [data-epoch-name="middle-devonian"] { --epoch-color: #ECCC8B; --epoch-text-color: #263238; } [data-epoch-name="early-devonian"] { --epoch-color: #DDB574; --epoch-text-color: #263238; } [data-epoch-name="pridoli"] { --epoch-color: #E6F1E8; --epoch-text-color: #263238; } [data-epoch-name="ludlow"] { --epoch-color: #C4E0DC; --epoch-text-color: #263238; } [data-epoch-name="wenlock"] { --epoch-color: #B9DBD3; --epoch-text-color: #263238; } [data-epoch-name="llandovery"] { --epoch-color: #A4D2C9; --epoch-text-color: #263238; } [data-epoch-name="late-ordovician"] { --epoch-color: #8EC7AF; --epoch-text-color: #263238; } [data-epoch-name="middle-ordovician"] { --epoch-color: #59B79E; --epoch-text-color: #263238; } [data-epoch-name="early-ordovician"] { --epoch-color: #4BA98F; --epoch-text-color: #263238; } [data-epoch-name="furongian"] { --epoch-color: #BBD9B1; --epoch-text-color: #263238; } [data-epoch-name="miaolingian"] { --epoch-color: #B1CCA4; --epoch-text-color: #263238; } [data-epoch-name="series2"] { --epoch-color: #9AB38D; --epoch-text-color: #263238; } /* Протерозой */ [data-epoch-name="late-vendian"] { --epoch-color: #F9DCD7; --epoch-text-color: #263238; } [data-epoch-name="early-vendian"] { --epoch-color: #F9DCD7; --epoch-text-color: #263238; } [data-epoch-name="stenian"] { --epoch-color: #F09476; --epoch-text-color: white; } [data-epoch-name="ectasian"] { --epoch-color: #F09476; --epoch-text-color: white; } [data-epoch-name="calymmian"] { --epoch-color: #F09476; --epoch-text-color: white; } [data-epoch-name="rhyacian"] { --epoch-color: #F098B5; --epoch-text-color: #263238; } [data-epoch-name="siderian"] { --epoch-color: #ED7D90; --epoch-text-color: #263238; } [data-epoch-name="upper-lopian"] { --epoch-color: #ECB0C4; --epoch-text-color: #263238; } [data-epoch-name="middle-lopian"] { --epoch-color: #E48EAD; --epoch-text-color: #263238; } [data-epoch-name="lower-lopian"] { --epoch-color: #E172A6; --epoch-text-color: #263238; } [data-epoch-name="mesoarchean"] { --epoch-color: #C6368A; --epoch-text-color: white; } /* Катархей */ [data-epoch-name="prearchean"] { --epoch-color: #795548; --epoch-text-color: white; } [data-epoch-name="lunar-hadean"] { --epoch-color: #6D4C41; --epoch-text-color: white; } /* Адаптация для мобильных */ @media (max-width: 600px) { .strat-column { min-width: unset; width: 100%; } .column-titles { display: none; } .eon { flex-direction: column; } .eon-name { writing-mode: horizontal-tb; transform: none; padding: 15px; border-right: none; border-bottom: 1px solid #e0e0e0; min-width: auto; width: auto; text-align: center; font-size: 1.3em; } .era-name { writing-mode: horizontal-tb; transform: none; padding: 10px; border-right: none; border-bottom: 1px solid #e0e0e0; min-width: auto; width: auto; text-align: center; } .period-container { flex-direction: column; } .period { width: auto; min-width: auto; border-bottom: 1px solid #e0e0e0; } .period-name { width: auto; text-align: center; justify-content: center; border-right: none; flex-direction: row; align-items: center; gap: 15px; padding: 15px; white-space: normal; } .epochs { flex-direction: row; flex-wrap: wrap; justify-content: center; } .epoch-block { min-width: 160px; min-height: 70px; margin: 6px; } .timescale { width: 100%; flex-direction: row; flex-wrap: wrap; justify-content: center; gap: 10px; padding: 10px; border-top: 1px solid #e0e0e0; } .timescale-marker { position: static; padding: 5px 10px; background: #f5f5f5; border-radius: 4px; } .timescale-marker::before, .timescale-marker::after { display: none; } .precambrian .column-titles.doc-titles { display: none; } .precambrian .era { flex-direction: column; } .precambrian .era-name { writing-mode: horizontal-tb; transform: none; padding: 10px; border-right: none; border-bottom: 1px solid #e0e0e0; min-width: auto; width: auto; text-align: center; } .precambrian .period-container { flex-direction: column; } .precambrian .period { width: auto; min-width: auto; border-bottom: 1px solid #e0e0e0; } .precambrian .epochs { flex-direction: row; flex-wrap: wrap; justify-content: center; } .precambrian .epoch-block { min-width: 160px; min-height: 70px; margin: 6px; } .precambrian .timescale { width: 100%; flex-direction: row; flex-wrap: wrap; justify-content: center; gap: 10px; padding: 10px; border-top: 1px solid #e0e0e0; } } @media (max-width: 600px) { .epochs { flex-direction: column; } .epoch-block { min-width: auto; } .column-header h2 { font-size: 1.7em; } .era-name, .period-name { font-size: 1.1em; } .eon-name { font-size: 1.2em; } .timescale-title { font-size: 0.8em; } } @media (max-width: 800px) { .toggle-container { position: static; margin-top: 10px; justify-content: center; width: 100%; } .column-header { flex-direction: column; padding-bottom: 15px; } .column-header h2 { margin-bottom: 10px; } } /* Dark theme styles */ .dark .strat-column { border-color: #444; box-shadow: 0 5px 15px rgba(0,0,0,0.3); background-color: #2d3748; } .dark .column-header { background: #1a202c; border-bottom-color: #111; } .dark .column-header2 { color: #e2e8f0; } .dark .toggle-label { color: #a0aec0; } .dark .slider { background-color: #4a5568; } .dark .column-titles { background: #2d3748; border-bottom-color: #1a202c; color: #e2e8f0; } .dark .column-titles.doc-titles { background: #4a5568; } .dark .eon-name { background-color: #2d3748; color: #e2e8f0; border-right-color: #4a5568; } .dark .divider-label { color: #e2e8f0; } .dark .divider-line { background: #4a5568; } .dark .era::after { background: #e0e0e0; } .dark .era-name { background-color: #4a5568; color: #e2e8f0; border-right-color: #4a5568; } .dark .period-name { background-color: #2d3748; color: #e2e8f0; border-right-color: #4a5568; } .dark .epoch-block { box-shadow: inset 0 0 0 1px rgba(255,255,255,0.1); color: #e2e8f0; } .dark .epoch-block[href="#"] { background-color: #4a5568; } .dark .timescale-marker::before { background: #718096; } .dark .timescale-marker::after { color: #e2e8f0; } /* Mobile dark theme */ @media (max-width: 600px) { .dark .eon-name { border-bottom-color: #4a5568; } .dark .era-name { border-bottom-color: #4a5568; } .dark .period { border-bottom-color: #4a5568; } .dark .timescale { border-top-color: #4a5568; } .dark .timescale-marker { background: #4a5568; color: #e2e8f0; } } /* Сохраняем оригинальные цвета эпох в темной теме */ .dark [data-epoch-name="holocene"] { --epoch-text-color: #263238; } .dark [data-epoch-name="pleistocene"] { --epoch-text-color: #263238; } .dark [data-epoch-name="gelasian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="pliocene"] { --epoch-text-color: #263238; } .dark [data-epoch-name="miocene"] { --epoch-text-color: #263238; } .dark [data-epoch-name="oligocene"] { --epoch-text-color: #263238; } .dark [data-epoch-name="eocene"] { --epoch-text-color: #263238; } .dark [data-epoch-name="paleocene"] { --epoch-text-color: #263238; } .dark [data-epoch-name="upper-cretaceous"] { --epoch-text-color: #263238; } .dark [data-epoch-name="lower-cretaceous"] { --epoch-text-color: #263238; } .dark [data-epoch-name="late-jurassic"] { --epoch-text-color: #263238; } .dark [data-epoch-name="middle-jurassic"] { --epoch-text-color: #263238; } .dark [data-epoch-name="early-jurassic"] { --epoch-text-color: #263238; } .dark [data-epoch-name="late-triassic"] { --epoch-text-color: #263238; } .dark [data-epoch-name="middle-triassic"] { --epoch-text-color: #263238; } .dark [data-epoch-name="late-permian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="guadalupian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="cisuralian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="pennsylvanian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="middle-carboniferous"] { --epoch-text-color: #263238; } .dark [data-epoch-name="mississippian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="late-devonian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="middle-devonian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="early-devonian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="pridoli"] { --epoch-text-color: #263238; } .dark [data-epoch-name="ludlow"] { --epoch-text-color: #263238; } .dark [data-epoch-name="wenlock"] { --epoch-text-color: #263238; } .dark [data-epoch-name="llandovery"] { --epoch-text-color: #263238; } .dark [data-epoch-name="late-ordovician"] { --epoch-text-color: #263238; } .dark [data-epoch-name="middle-ordovician"] { --epoch-text-color: #263238; } .dark [data-epoch-name="early-ordovician"] { --epoch-text-color: #263238; } .dark [data-epoch-name="furongian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="miaolingian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="series2"] { --epoch-text-color: #263238; } .dark [data-epoch-name="late-vendian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="early-vendian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="stenian"] { --epoch-text-color: white; } .dark [data-epoch-name="ectasian"] { --epoch-text-color: white; } .dark [data-epoch-name="calymmian"] { --epoch-text-color: white; } .dark [data-epoch-name="rhyacian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="siderian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="upper-lopian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="middle-lopian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="lower-lopian"] { --epoch-text-color: #263238; } .dark [data-epoch-name="mesoarchean"] { --epoch-text-color: white; } .dark [data-epoch-name="prearchean"] { --epoch-text-color: white; } .dark [data-epoch-name="lunar-hadean"] { --epoch-text-color: white; } </style> <script> document.addEventListener('DOMContentLoaded', function() { // Предотвращаем переход по пустым ссылкам document.querySelectorAll('a[href="#"]').forEach(link => { link.addEventListener('click', e => e.preventDefault()); }); const toggle = document.getElementById('showHiddenToggle'); if (toggle) { // При загрузке страницы - скрываем неактивные элементы if (!toggle.checked) { hideInactiveElements(); } toggle.addEventListener('change', function() { document.body.classList.toggle('show-hidden', this.checked); // При скрытии - снова прячем неактивные элементы if (!this.checked) { hideInactiveElements(); } else { showAllElements(); } }); } function hideInactiveElements() { // Скрываем все неактивные эпохи document.querySelectorAll('.epoch-block[href="#"]').forEach(epoch => { epoch.style.display = 'none'; }); // Скрываем пустые периоды document.querySelectorAll('.period-container').forEach(period => { const hasVisibleEpochs = period.querySelector('.epoch-block:not([href="#"]), .epoch-block[style*="display: flex"]'); period.style.display = hasVisibleEpochs ? 'flex' : 'none'; }); // Скрываем пустые эры document.querySelectorAll('.era').forEach(era => { const hasVisiblePeriods = era.querySelector('.period-container:not([style*="display: none"])'); era.style.display = hasVisiblePeriods ? 'flex' : 'none'; }); // Скрываем пустые эоны и секции document.querySelectorAll('.eon, .precambrian-section').forEach(section => { const hasVisibleEras = section.querySelector('.era:not([style*="display: none"])'); section.style.display = hasVisibleEras ? 'flex' : 'none'; }); // Скрываем заголовки, если вся секция скрыта document.querySelectorAll('.column-titles.doc-titles').forEach(title => { const section = title.nextElementSibling; const isVisible = section && window.getComputedStyle(section).display !== 'none'; title.style.display = isVisible ? 'flex' : 'none'; }); } function showAllElements() { // Показываем все элементы при включенном переключателе document.querySelectorAll('.epoch-block, .period-container, .era, .eon, .precambrian-section, .column-titles.doc-titles').forEach(el => { el.style.display = 'flex'; }); } // Позиционирование маркеров временной шкалы для Архея/Катархея function positionArcheanHadeanMarkers() { const archeanHadeanTimescale = document.querySelector('.archean-hadean-timescale'); if (!archeanHadeanTimescale) return; const markers = archeanHadeanTimescale.querySelectorAll('.timescale-marker'); markers.forEach(marker => { const age = parseFloat(marker.getAttribute('data-age')); let position; const minAge = 2500; const maxAge = 4600; const normalizedAge = (Math.log10(age) - Math.log10(minAge)) / (Math.log10(maxAge) - Math.log10(minAge)); position = (1 - normalizedAge) * 100; marker.style.top = `${position}%`; }); } // Корректировка заголовков для Архея и Катархея function adjustArcheanHadeanHeaders() { const archeanHeader = document.querySelector('.era.archean .era-name'); const hadeanHeader = document.querySelector('.era.hadean .era-name'); if (archeanHeader && hadeanHeader) { archeanHeader.style.height = '66.66%'; hadeanHeader.style.height = '33.33%'; archeanHeader.style.justifyContent = 'flex-end'; hadeanHeader.style.justifyContent = 'flex-start'; } } // Инициализация позиционирования маркеров positionArcheanHadeanMarkers(); window.addEventListener('resize', positionArcheanHadeanMarkers); // Функция для определения яркости цвета function getBrightness(hexColor) { hexColor = hexColor.replace('#', ''); const r = parseInt(hexColor.substring(0, 2), 16); const g = parseInt(hexColor.substring(2, 4), 16); const b = parseInt(hexColor.substring(4, 6), 16); return (r * 299 + g * 587 + b * 114) / 1000; } // Установка цвета текста в зависимости от яркости фона document.querySelectorAll('.epoch-block:not([href="#"])').forEach(block => { const bgColor = getComputedStyle(block).backgroundColor; const rgb = bgColor.match(/\d+/g); const hexColor = rgb ? `#${((1 << 24) + (parseInt(rgb[0]) << 16) + (parseInt(rgb[1]) << 8) + parseInt(rgb[2])).toString(16).slice(1)}` : '#FFFFFF'; const brightness = getBrightness(hexColor); block.style.color = brightness > 160 ? '#333333' : '#FFFFFF'; }); // Специфичная обработка для докембрия // Инициализация обработки докембрия handlePrecambrian(); }); </script> |
Понедельник, 2026-01-12, 14:18
# 5
Понял проблемы! Посмотрел стили вашего сайта - у вас используется .dark класс для темной темы, а не data-theme="dark". Также вижу проблему с тултипами. Давайте исправим:
Исправленный shortcode cardinfo.html ```html {{/* layouts/shortcodes/cardinfo.html */}} {{ $link := .Get "link" }} {{ $title := .Get "title" }} {{ $desc := .Get "desc" | default "Описание отсутствует" }} {{ $date := .Get "date" | default "Дата не указана" }} {{ $audience := .Get "audience" | default "Для всех сотрудников" }} {{ $tag := .Get "tag" }} {{ $tagtype := .Get "tagtype" | default "default" }} <div class="info-card"> <a href="{{ $link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <span class="info-card-title">{{ $title }}</span> <div class="info-card-right-section"> {{ if $tag }} <span class="info-card-tag info-card-tag-{{ $tagtype }}"> {{ $tag }} </span> {{ end }} <div class="info-card-tooltip-wrapper"> <span class="info-card-icon"> {{/* Используем вашу иконку (настройте под вашу систему) */}} <i class="icon-info" aria-hidden="true"></i> </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ $desc }}</div> <div class="tooltip-details"> <div class="tooltip-date"> <i class="icon-date" aria-hidden="true"></i> <span>Добавлено: {{ $date }}</span> </div> <div class="tooltip-audience"> <i class="icon-user" aria-hidden="true"></i> <span>Для кого: {{ $audience }}</span> </div> </div> </div> </div> </div> </div> </a> </div> <style> /* ===== ОСНОВНЫЕ СТИЛИ КАРТОЧЕК ===== */ .info-card { margin: 1rem 0; border: 1px solid #e1e8ed; border-radius: 8px; background: #ffffff; transition: all 0.3s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.05); position: relative; } .info-card:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.1); transform: translateY(-1px); border-color: #4a90e2; } .info-card-link { display: block; padding: 1rem 1.25rem; text-decoration: none; color: #2d3748; } .info-card-header { display: flex; justify-content: space-between; align-items: center; } .info-card-title { font-size: 1rem; font-weight: 600; flex: 1; padding-right: 15px; color: #2d3748; line-height: 1.4; } /* ===== ПРАВАЯ СЕКЦИЯ (тег + иконка) ===== */ .info-card-right-section { display: flex; align-items: center; gap: 10px; flex-shrink: 0; } /* ===== ТЕГИ ===== */ .info-card-tag { font-size: 0.75rem; padding: 0.2rem 0.6rem; border-radius: 12px; font-weight: 500; white-space: nowrap; border: 1px solid; } .info-card-tag-default { background: #e2e8f0; color: #4a5568; border-color: #cbd5e0; } .info-card-tag-info { background: #bee3f8; color: #2c5282; border-color: #90cdf4; } .info-card-tag-warning { background: #feebc8; color: #975a16; border-color: #fbd38d; } .info-card-tag-success { background: #c6f6d5; color: #276749; border-color: #9ae6b4; } .info-card-tag-error { background: #fed7d7; color: #9b2c2c; border-color: #fc8181; } /* ===== ИКОНКА И ТУЛТИП ===== */ .info-card-tooltip-wrapper { position: relative; display: flex; align-items: center; } .info-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; cursor: help; color: #718096; border-radius: 50%; transition: all 0.2s; font-size: 0.9rem; } .info-card-icon:hover { background: #edf2f7; color: #4a90e2; } /* ===== ВСПЛЫВАЮЩАЯ ПОДСКАЗКА (ИСПРАВЛЕНА ПОЗИЦИЯ) ===== */ .info-card-tooltip { position: absolute; top: -10px; right: -10px; transform: translateY(-100%); width: 300px; padding: 15px; background: white; border-radius: 8px; box-shadow: 0 5px 20px rgba(0,0,0,0.15); border: 1px solid #e2e8f0; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); pointer-events: none; } /* Отображаем тултип при наведении на иконку */ .info-card-tooltip-wrapper:hover .info-card-tooltip { opacity: 1; visibility: visible; pointer-events: auto; } /* Стрелка тултипа */ .info-card-tooltip::before { content: ''; position: absolute; bottom: -6px; right: 20px; width: 12px; height: 12px; background: white; border-right: 1px solid #e2e8f0; border-bottom: 1px solid #e2e8f0; transform: rotate(45deg); z-index: -1; } .tooltip-description { font-size: 0.9rem; line-height: 1.5; color: #4a5568; margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid #e2e8f0; } .tooltip-details { font-size: 0.85rem; color: #718096; } .tooltip-date, .tooltip-audience { margin-bottom: 5px; display: flex; align-items: center; gap: 8px; } .tooltip-date i, .tooltip-audience i { flex-shrink: 0; opacity: 0.7; font-size: 0.9rem; } /* ===== ТЕМНАЯ ТЕМА (поддержка вашего .dark класса) ===== */ .dark .info-card { background: #2d3748; border-color: #4a5568; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } .dark .info-card:hover { border-color: #63b3ed; box-shadow: 0 4px 12px rgba(0,0,0,0.3); } .dark .info-card-link { color: #e2e8f0; } .dark .info-card-title { color: #f7fafc; } .dark .info-card-icon { color: #a0aec0; } .dark .info-card-icon:hover { background: #4a5568; color: #63b3ed; } .dark .info-card-tooltip { background: #1a202c; border-color: #4a5568; box-shadow: 0 5px 20px rgba(0,0,0,0.4); } .dark .info-card-tooltip::before { background: #1a202c; border-color: #4a5568; } .dark .tooltip-description { color: #e2e8f0; border-bottom-color: #4a5568; } .dark .tooltip-details { color: #a0aec0; } /* Темная тема для тегов */ .dark .info-card-tag-default { background: #4a5568; color: #cbd5e0; border-color: #718096; } .dark .info-card-tag-info { background: #2c5282; color: #bee3f8; border-color: #3182ce; } .dark .info-card-tag-warning { background: #975a16; color: #feebc8; border-color: #d69e2e; } .dark .info-card-tag-success { background: #276749; color: #c6f6d5; border-color: #38a169; } .dark .info-card-tag-error { background: #9b2c2c; color: #fed7d7; border-color: #e53e3e; } /* ===== АДАПТИВНОСТЬ ===== */ @media (max-width: 768px) { .info-card-header { flex-direction: column; align-items: flex-start; gap: 10px; } .info-card-right-section { width: 100%; justify-content: space-between; } .info-card-tooltip { position: fixed; top: auto !important; bottom: 20px; right: 20px !important; left: 20px; width: auto; max-width: calc(100vw - 40px); transform: none !important; } .info-card-tooltip::before { display: none; } } /* ===== КАСТОМИЗАЦИЯ ПОД ВАШИ ИКОНКИ ===== */ /* Если у вас используются классы типа .fa, .fas, .far и т.д. */ .icon-info::before { content: "ℹ️"; /* Или если у вас FontAwesome: content: "\f05a"; */ } .icon-date::before { content: "📅"; /* Или если у вас FontAwesome: content: "\f073"; */ } .icon-user::before { content: "👥"; /* Или если у вас FontAwesome: content: "\f0c0"; */ } /* Альтернативно, если используете SVG иконки */ .icon-info svg, .icon-date svg, .icon-user svg { width: 14px; height: 14px; fill: currentColor; } /* Если у вас уже есть стили для иконок в теме */ .info-card-icon i { font-style: normal; line-height: 1; } </style> <script> document.addEventListener('DOMContentLoaded', function() { // Позиционирование тултипов при загрузке positionTooltips(); // Перепозиционирование при изменении размера окна window.addEventListener('resize', positionTooltips); // Закрытие тултипов при клике вне их области document.addEventListener('click', function(e) { if (!e.target.closest('.info-card-tooltip-wrapper')) { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); function positionTooltips() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { const tooltip = wrapper.querySelector('.info-card-tooltip'); const icon = wrapper.querySelector('.info-card-icon'); if (!tooltip || !icon) return; // Сбрасываем позиционирование tooltip.style.right = ''; tooltip.style.top = ''; const iconRect = icon.getBoundingClientRect(); const wrapperRect = wrapper.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); // Проверяем, не выходит ли тултип за границы окна справа const spaceRight = window.innerWidth - iconRect.right; const spaceLeft = iconRect.left; if (spaceRight < tooltipRect.width + 20) { // Если места справа мало, показываем слева от иконки tooltip.style.right = 'auto'; tooltip.style.left = '-10px'; tooltip.style.transform = 'translateY(-100%)'; } else { // Показываем справа от иконки (стандартное положение) tooltip.style.right = '-10px'; tooltip.style.left = 'auto'; tooltip.style.transform = 'translateY(-100%)'; } // Проверяем, не выходит ли тултип за верхнюю границу if (iconRect.top < tooltipRect.height + 20) { // Если выходит вверх, показываем под иконкой tooltip.style.top = 'calc(100% + 10px)'; tooltip.style.transform = 'translateY(0)'; // Меняем направление стрелки tooltip.style.setProperty('--arrow-bottom', 'auto'); tooltip.style.setProperty('--arrow-top', '-6px'); tooltip.style.setProperty('--arrow-transform', 'rotate(-135deg)'); } else { // Стандартное положение (над иконкой) tooltip.style.top = '-10px'; tooltip.style.transform = 'translateY(-100%)'; // Стрелка указывает вниз tooltip.style.setProperty('--arrow-bottom', '-6px'); tooltip.style.setProperty('--arrow-top', 'auto'); tooltip.style.setProperty('--arrow-transform', 'rotate(45deg)'); } }); } // Поддержка системной темы const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)'); // Если нет явного .dark класса, но система в темной теме if (!document.documentElement.classList.contains('dark') && prefersDarkScheme.matches) { // Можно автоматически добавить dark класс или использовать другой подход document.documentElement.classList.add('dark'); } // Обработчик изменения системной темы prefersDarkScheme.addEventListener('change', (e) => { if (e.matches) { document.documentElement.classList.add('dark'); } else { document.documentElement.classList.remove('dark'); } }); }); </script> ``` Для использования с вашей системой иконок: 1. Если используете FontAwesome: ```html {{/* Внутри info-card-icon */}} <i class="fas fa-info-circle" aria-hidden="true"></i> ``` 1. Если используете свои SVG иконки: ```html {{/* Внутри info-card-icon */}} <svg class="icon" width="16" height="16" viewBox="0 0 16 16"> <use xlink:href="#icon-info"></use> </svg> ``` 1. Убедитесь, что ваш основной шаблон имеет SVG спрайт: ```html {{/* Где-то в layouts/partials/head.html или baseof.html */}} <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <defs> <symbol id="icon-info" viewBox="0 0 16 16"> <path d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm1 12H7V7h2v5zm0-8H7V3h2v1z"/> </symbol> <symbol id="icon-date" viewBox="0 0 24 24"> <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </symbol> <symbol id="icon-user" viewBox="0 0 24 24"> <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/> </symbol> </defs> </svg> ``` Ключевые исправления: 1. Темная тема: Теперь поддерживает ваш .dark класс 2. Позиция тултипов: Тулутипы теперь появляются над иконкой, а не внутри кнопки 3. Адаптивность: Правильная работа на мобильных устройствах 4. JavaScript: Исправлено позиционирование тултипов 5. Стили: Синхронизированы с вашим дизайном Теперь карточки должны правильно переключаться между светлой и темной темами вместе с остальным сайтом, а тултипы будут появляться над иконкой. |
Понедельник, 2026-01-12, 14:28
# 6
{{/* layouts/shortcodes/cardinfo.html */}}
{{ $link := .Get "link" }} {{ $title := .Get "title" }} {{ $desc := .Get "desc" | default "" }} {{ $date := .Get "date" }} {{ $audience := .Get "audience" }} {{ $tag := .Get "tag" }} {{ $tagtype := .Get "tagtype" | default "default" }} <div class="info-card"> <a href="{{ $link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <span class="info-card-title">{{ $title }}</span> <div class="info-card-right-section"> {{ if $tag }} <span class="info-card-tag info-card-tag-{{ $tagtype }}"> {{ $tag }} </span> {{ end }} {{ if $desc }} <div class="info-card-tooltip-wrapper"> <span class="info-card-icon"> <svg class="info-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 13A6 6 0 1 1 8 2a6 6 0 0 1 0 12z"/> <path d="M7 11h2v2H7zm0-8h2v6H7z"/> </svg> </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ $desc }}</div> {{ if or $date $audience }} <div class="tooltip-details"> {{ if $date }} <div class="tooltip-date"> <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </svg> <span>Добавлено: {{ $date }}</span> </div> {{ end }} {{ if $audience }} <div class="tooltip-audience"> <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"> <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/> </svg> <span>Для кого: {{ $audience }}</span> </div> {{ end }} </div> {{ end }} </div> </div> {{ end }} </div> </div> </a> </div> <style> /* ===== ОСНОВНЫЕ СТИЛИ КАРТОЧЕК ===== */ .info-card { margin: 0.75rem 0; border: 1px solid #e0e0e0; border-radius: 8px; background: #ffffff; transition: all 0.2s ease; position: relative; } .info-card:hover { border-color: #4a90e2; box-shadow: 0 2px 8px rgba(74, 144, 226, 0.15); } .info-card-link { display: block; padding: 1rem 1.25rem; text-decoration: none; color: #333333; } .info-card-link:hover { text-decoration: none; } .info-card-header { display: flex; justify-content: space-between; align-items: center; min-height: 24px; } .info-card-title { font-size: 1rem; font-weight: 600; flex: 1; padding-right: 12px; color: #333333; line-height: 1.4; } /* ===== ПРАВАЯ СЕКЦИЯ ===== */ .info-card-right-section { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } /* ===== ТЕГИ ===== */ .info-card-tag { font-size: 0.75rem; padding: 0.15rem 0.5rem; border-radius: 10px; font-weight: 500; white-space: nowrap; border: 1px solid transparent; } .info-card-tag-default { background: #f0f0f0; color: #666666; border-color: #ddd; } .info-card-tag-info { background: #e3f2fd; color: #1565c0; border-color: #90caf9; } .info-card-tag-warning { background: #fff3e0; color: #e65100; border-color: #ffcc80; } .info-card-tag-success { background: #e8f5e9; color: #2e7d32; border-color: #a5d6a7; } .info-card-tag-error { background: #ffebee; color: #c62828; border-color: #ef9a9a; } /* ===== ИКОНКА И ТУЛТИП ===== */ .info-card-tooltip-wrapper { position: relative; display: flex; align-items: center; } .info-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; cursor: help; color: #666666; border-radius: 50%; transition: all 0.15s; } .info-card-icon:hover { background: #f0f0f0; color: #4a90e2; } .info-icon { width: 16px; height: 16px; } /* ===== ВСПЛЫВАЮЩАЯ ПОДСКАЗКА ===== */ .info-card-tooltip { position: absolute; top: -8px; right: -8px; transform: translateY(-100%); width: 280px; padding: 12px; background: white; border-radius: 6px; box-shadow: 0 3px 12px rgba(0,0,0,0.15); border: 1px solid #e0e0e0; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.2s ease; pointer-events: none; } /* Показываем тултип при наведении на иконку */ .info-card-tooltip-wrapper:hover .info-card-tooltip { opacity: 1; visibility: visible; pointer-events: auto; } /* Стрелка тултипа */ .info-card-tooltip::after { content: ''; position: absolute; bottom: -5px; right: 12px; width: 10px; height: 10px; background: white; border-right: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0; transform: rotate(45deg); z-index: -1; } .tooltip-description { font-size: 0.85rem; line-height: 1.4; color: #444444; margin-bottom: 8px; } .tooltip-details { font-size: 0.8rem; color: #666666; border-top: 1px solid #f0f0f0; padding-top: 8px; } .tooltip-date, .tooltip-audience { margin-bottom: 4px; display: flex; align-items: center; gap: 6px; } .tooltip-date svg, .tooltip-audience svg { flex-shrink: 0; opacity: 0.7; } /* ===== ТЕМНАЯ ТЕМА - НЕ АКТИВИРУЕМ САМИ ===== */ /* Темная тема будет управляться вашим основным CSS сайта */ /* ===== АДАПТИВНОСТЬ ===== */ @media (max-width: 768px) { .info-card-header { flex-direction: column; align-items: flex-start; gap: 8px; } .info-card-right-section { width: 100%; justify-content: space-between; } .info-card-tooltip { position: fixed; top: auto !important; bottom: 60px; left: 50% !important; right: auto !important; transform: translateX(-50%) !important; width: calc(100vw - 40px); max-width: 400px; max-height: 60vh; overflow-y: auto; } .info-card-tooltip::after { display: none; } .info-card { margin: 0.5rem 0; } .info-card-link { padding: 0.75rem 1rem; } } </style> <script> document.addEventListener('DOMContentLoaded', function() { // УДАЛЯЕМ ВСЮ ЛОГИКУ АВТОМАТИЧЕСКОГО ВКЛЮЧЕНИЯ ТЕМНОЙ ТЕМЫ // Пусть тема управляется вашим основным скриптом сайта // Логика позиционирования тултипов positionTooltips(); window.addEventListener('resize', positionTooltips); window.addEventListener('scroll', positionTooltips); // Закрытие тултипов при клике вне их области document.addEventListener('click', function(e) { if (!e.target.closest('.info-card-tooltip-wrapper')) { hideAllTooltips(); } }); // Закрытие тултипов при нажатии ESC document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { hideAllTooltips(); } }); function positionTooltips() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { const tooltip = wrapper.querySelector('.info-card-tooltip'); const icon = wrapper.querySelector('.info-card-icon'); if (!tooltip || !icon) return; // Если тултип не видим, не позиционируем if (tooltip.style.opacity === '0' || tooltip.style.visibility === 'hidden') { return; } const iconRect = icon.getBoundingClientRect(); const wrapperRect = wrapper.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; // Проверяем доступное пространство const spaceRight = viewportWidth - iconRect.right; const spaceLeft = iconRect.left; const spaceTop = iconRect.top; const spaceBottom = viewportHeight - iconRect.bottom; let tooltipX, tooltipY; let arrowPosition = 'bottom'; // Определяем лучшую позицию по горизонтали if (spaceRight >= tooltipRect.width + 20 || spaceRight >= spaceLeft) { // Помещаем справа от иконки tooltipX = wrapperRect.right + 8; tooltip.style.left = 'auto'; tooltip.style.right = '0'; tooltip.style.transformOrigin = 'top right'; } else { // Помещаем слева от иконки tooltipX = wrapperRect.left - tooltipRect.width - 8; tooltip.style.left = '0'; tooltip.style.right = 'auto'; tooltip.style.transformOrigin = 'top left'; } // Определяем лучшую позицию по вертикали if (spaceTop >= tooltipRect.height + 20) { // Помещаем над иконкой tooltipY = wrapperRect.top - tooltipRect.height - 8; tooltip.style.top = '0'; tooltip.style.bottom = 'auto'; arrowPosition = 'bottom'; } else if (spaceBottom >= tooltipRect.height + 20) { // Помещаем под иконкой tooltipY = wrapperRect.bottom + 8; tooltip.style.top = '100%'; tooltip.style.bottom = 'auto'; arrowPosition = 'top'; } else { // Центрируем по вертикали, если места мало const centerY = wrapperRect.top + (wrapperRect.height / 2) - (tooltipRect.height / 2); tooltipY = Math.max(20, Math.min(centerY, viewportHeight - tooltipRect.height - 20)); tooltip.style.top = '50%'; tooltip.style.transform = 'translateY(-50%)'; arrowPosition = 'middle'; } // Обновляем позицию стрелки updateTooltipArrow(tooltip, arrowPosition); }); } function updateTooltipArrow(tooltip, position) { // Удаляем старую стрелку const oldArrow = tooltip.querySelector('.tooltip-arrow'); if (oldArrow) oldArrow.remove(); const arrow = document.createElement('div'); arrow.className = 'tooltip-arrow'; switch(position) { case 'bottom': arrow.style.cssText = ` position: absolute; bottom: -6px; right: 12px; width: 10px; height: 10px; background: white; border-right: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0; transform: rotate(45deg); z-index: -1; `; break; case 'top': arrow.style.cssText = ` position: absolute; top: -6px; right: 12px; width: 10px; height: 10px; background: white; border-left: 1px solid #e0e0e0; border-top: 1px solid #e0e0e0; transform: rotate(45deg); z-index: -1; `; break; case 'middle': // Для центрального позиционирования не нужна стрелка return; } tooltip.appendChild(arrow); } function hideAllTooltips() { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } // Отслеживание изменения темы сайта function handleThemeChange() { // Просто перепозиционируем тултипы при изменении темы setTimeout(positionTooltips, 100); } // Наблюдаем за изменениями класса dark у body или html const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.attributeName === 'class') { handleThemeChange(); } }); }); // Начинаем наблюдение observer.observe(document.body, { attributes: true }); observer.observe(document.documentElement, { attributes: true }); }); </script> |
Понедельник, 2026-01-12, 14:34
# 7
{{/* layouts/shortcodes/cardinfo.html */}}
{{ $link := .Get "link" }} {{ $title := .Get "title" }} {{ $desc := .Get "desc" | default "" }} {{ $date := .Get "date" }} {{ $audience := .Get "audience" }} {{ $tag := .Get "tag" }} {{ $tagtype := .Get "tagtype" | default "default" }} <div class="info-card"> <a href="{{ $link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <span class="info-card-title">{{ $title }}</span> <div class="info-card-right-section"> {{ if $tag }} <span class="info-card-tag info-card-tag-{{ $tagtype }}"> {{ $tag }} </span> {{ end }} {{ if $desc }} <div class="info-card-tooltip-wrapper"> <span class="info-card-icon" title="Показать информацию"> <svg class="info-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 13A6 6 0 1 1 8 2a6 6 0 0 1 0 12z"/> <path d="M7 11h2v2H7zm0-8h2v6H7z"/> </svg> </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ $desc }}</div> {{ if or $date $audience }} <div class="tooltip-details"> {{ if $date }} <div class="tooltip-date"> <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </svg> <span>Добавлено: {{ $date }}</span> </div> {{ end }} {{ if $audience }} <div class="tooltip-audience"> <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"> <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/> </svg> <span>Для кого: {{ $audience }}</span> </div> {{ end }} </div> {{ end }} </div> </div> {{ end }} </div> </div> </a> </div> <style> /* ===== ОСНОВНЫЕ СТИЛИ КАРТОЧЕК (будут дополнены вашим CSS) ===== */ .info-card { margin: 0.75rem 0; border: 1px solid #e0e0e0; border-radius: 8px; background: #ffffff; transition: all 0.2s ease; position: relative; } .info-card:hover { border-color: #4a90e2; box-shadow: 0 2px 8px rgba(74, 144, 226, 0.15); } .info-card-link { display: block; padding: 1rem 1.25rem; text-decoration: none; color: #333333; } .info-card-link:hover { text-decoration: none; } .info-card-header { display: flex; justify-content: space-between; align-items: center; min-height: 24px; } .info-card-title { font-size: 1rem; font-weight: 600; flex: 1; padding-right: 12px; color: #333333; line-height: 1.4; } /* ===== ПРАВАЯ СЕКЦИЯ ===== */ .info-card-right-section { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } /* ===== ТЕГИ ===== */ .info-card-tag { font-size: 0.75rem; padding: 0.15rem 0.5rem; border-radius: 10px; font-weight: 500; white-space: nowrap; border: 1px solid transparent; } .info-card-tag-default { background: #f0f0f0; color: #666666; border-color: #ddd; } .info-card-tag-info { background: #e3f2fd; color: #1565c0; border-color: #90caf9; } .info-card-tag-warning { background: #fff3e0; color: #e65100; border-color: #ffcc80; } .info-card-tag-success { background: #e8f5e9; color: #2e7d32; border-color: #a5d6a7; } .info-card-tag-error { background: #ffebee; color: #c62828; border-color: #ef9a9a; } /* ===== ИКОНКА И ТУЛТИП ===== */ .info-card-tooltip-wrapper { position: relative; display: flex; align-items: center; } .info-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; cursor: help; color: #666666; border-radius: 50%; transition: all 0.15s; } .info-card-icon:hover { background: #f0f0f0; color: #4a90e2; } .info-icon { width: 16px; height: 16px; } /* ===== ВСПЛЫВАЮЩАЯ ПОДСКАЗКА ===== */ .info-card-tooltip { position: absolute; top: 0; right: 0; transform: translateY(calc(-100% - 8px)); width: 280px; padding: 12px; background: white; border-radius: 6px; box-shadow: 0 3px 12px rgba(0,0,0,0.15); border: 1px solid #e0e0e0; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.2s ease; pointer-events: none; } /* Показываем тултип при наведении на обертку */ .info-card-tooltip-wrapper:hover .info-card-tooltip { opacity: 1; visibility: visible; pointer-events: auto; } /* Стрелка тултипа */ .info-card-tooltip::after { content: ''; position: absolute; bottom: -5px; right: 12px; width: 10px; height: 10px; background: white; border-right: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0; transform: rotate(45deg); z-index: -1; } .tooltip-description { font-size: 0.85rem; line-height: 1.4; color: #444444; margin-bottom: 8px; } .tooltip-details { font-size: 0.8rem; color: #666666; border-top: 1px solid #f0f0f0; padding-top: 8px; } .tooltip-date, .tooltip-audience { margin-bottom: 4px; display: flex; align-items: center; gap: 6px; } .tooltip-date svg, .tooltip-audience svg { flex-shrink: 0; opacity: 0.7; } /* ===== ТЕМНАЯ ТЕМА - СИНХРОНИЗАЦИЯ С ВАШИМ САЙТОМ ===== */ /* Если у вас есть .dark класс на body или html */ body.dark .info-card, html.dark .info-card { background: #2d3748; border-color: #4a5568; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } body.dark .info-card:hover, html.dark .info-card:hover { border-color: #63b3ed; box-shadow: 0 2px 8px rgba(99, 179, 237, 0.2); } body.dark .info-card-link, html.dark .info-card-link { color: #e2e8f0; } body.dark .info-card-title, html.dark .info-card-title { color: #f7fafc; } body.dark .info-card-icon, html.dark .info-card-icon { color: #a0aec0; } body.dark .info-card-icon:hover, html.dark .info-card-icon:hover { background: #4a5568; color: #63b3ed; } body.dark .info-card-tooltip, html.dark .info-card-tooltip { background: #1a202c; border-color: #4a5568; box-shadow: 0 3px 12px rgba(0,0,0,0.4); } body.dark .info-card-tooltip::after, html.dark .info-card-tooltip::after { background: #1a202c; border-color: #4a5568; } body.dark .tooltip-description, html.dark .tooltip-description { color: #e2e8f0; } body.dark .tooltip-details, html.dark .tooltip-details { color: #a0aec0; border-top-color: #4a5568; } body.dark .info-card-tag-default, html.dark .info-card-tag-default { background: #4a5568; color: #cbd5e0; border-color: #718096; } body.dark .info-card-tag-info, html.dark .info-card-tag-info { background: #2c5282; color: #bee3f8; border-color: #3182ce; } body.dark .info-card-tag-warning, html.dark .info-card-tag-warning { background: #975a16; color: #feebc8; border-color: #d69e2e; } body.dark .info-card-tag-success, html.dark .info-card-tag-success { background: #276749; color: #c6f6d5; border-color: #38a169; } body.dark .info-card-tag-error, html.dark .info-card-tag-error { background: #9b2c2c; color: #fed7d7; border-color: #e53e3e; } /* ===== АДАПТИВНОСТЬ ===== */ @media (max-width: 768px) { .info-card-header { flex-direction: column; align-items: flex-start; gap: 8px; } .info-card-right-section { width: 100%; justify-content: space-between; } .info-card-tooltip { position: fixed; top: auto !important; bottom: 60px; left: 50% !important; right: auto !important; transform: translateX(-50%) !important; width: calc(100vw - 40px); max-width: 400px; } .info-card-tooltip::after { display: none; } .info-card { margin: 0.5rem 0; } .info-card-link { padding: 0.75rem 1rem; } } </style> <script> (function() { // Создаем изолированный скрипт для каждой карточки document.addEventListener('DOMContentLoaded', function() { initTooltips(); }); // Инициализируем при каждом добавлении на страницу if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initTooltips); } else { initTooltips(); } function initTooltips() { // Находим все контейнеры с тултипами const tooltipWrappers = document.querySelectorAll('.info-card-tooltip-wrapper'); tooltipWrappers.forEach(wrapper => { // Пропускаем если уже инициализирован if (wrapper.dataset.initialized === 'true') return; const tooltip = wrapper.querySelector('.info-card-tooltip'); const icon = wrapper.querySelector('.info-card-icon'); if (!tooltip || !icon) return; // Помечаем как инициализированный wrapper.dataset.initialized = 'true'; // Показываем тултип при наведении wrapper.addEventListener('mouseenter', function() { positionTooltip(wrapper, tooltip, icon); tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; tooltip.style.pointerEvents = 'auto'; }); // Скрываем тултип при уходе мыши wrapper.addEventListener('mouseleave', function() { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; tooltip.style.pointerEvents = 'none'; }); // Позиционирование при клике (для мобильных) wrapper.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); if (window.innerWidth <= 768) { positionTooltip(wrapper, tooltip, icon); if (tooltip.style.opacity === '1') { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; } else { tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; } } }); // Позиционирование при изменении размера window.addEventListener('resize', function() { if (tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip, icon); } }); }); // Закрытие тултипов при клике вне document.addEventListener('click', function(e) { if (!e.target.closest('.info-card-tooltip-wrapper')) { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); // Закрытие при нажатии ESC document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); } function positionTooltip(wrapper, tooltip, icon) { const iconRect = icon.getBoundingClientRect(); const wrapperRect = wrapper.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; // Определяем лучшую позицию let top, right, left, transform; if (window.innerWidth <= 768) { // Для мобильных - центрируем tooltip.style.position = 'fixed'; tooltip.style.top = '50%'; tooltip.style.left = '50%'; tooltip.style.right = 'auto'; tooltip.style.transform = 'translate(-50%, -50%)'; tooltip.style.maxHeight = '70vh'; tooltip.style.overflowY = 'auto'; return; } // Сбрасываем стили tooltip.style.position = 'absolute'; tooltip.style.maxHeight = ''; tooltip.style.overflowY = ''; // Проверяем, где больше места const spaceAbove = iconRect.top; const spaceBelow = viewportHeight - iconRect.bottom; const spaceRight = viewportWidth - wrapperRect.right; // По умолчанию показываем сверху if (spaceAbove >= tooltipRect.height + 20) { // Помещаем над иконкой top = `calc(-100% - 8px)`; right = '0'; left = 'auto'; transform = 'none'; } else if (spaceBelow >= tooltipRect.height + 20) { // Помещаем под иконкой top = 'calc(100% + 8px)'; right = '0'; left = 'auto'; transform = 'none'; } else { // Не хватает места, центрируем по вертикали top = '50%'; right = spaceRight >= tooltipRect.width + 20 ? 'calc(100% + 8px)' : 'auto'; left = spaceRight >= tooltipRect.width + 20 ? 'auto' : 'calc(-100% - 8px)'; transform = 'translateY(-50%)'; } // Применяем стили tooltip.style.top = top; tooltip.style.right = right; tooltip.style.left = left; tooltip.style.transform = transform; } // Переинициализация при изменении темы (если ваш скрипт темы вызывает событие) document.addEventListener('themeChange', function() { setTimeout(initTooltips, 100); }); // Если у вас нет события themeChange, проверяем периодически let lastTheme = document.body.classList.contains('dark') ? 'dark' : 'light'; setInterval(function() { const currentTheme = document.body.classList.contains('dark') ? 'dark' : 'light'; if (currentTheme !== lastTheme) { lastTheme = currentTheme; setTimeout(initTooltips, 100); } }, 500); })(); </script> |
Понедельник, 2026-01-12, 14:41
# 8
{{/* layouts/shortcodes/cardinfo.html */}}
{{ $link := .Get "link" }} {{ $title := .Get "title" }} {{ $desc := .Get "desc" | default "" }} {{ $date := .Get "date" }} {{ $audience := .Get "audience" }} {{ $tag := .Get "tag" }} {{ $tagtype := .Get "tagtype" | default "default" }} <div class="info-card"> <a href="{{ $link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <span class="info-card-title">{{ $title }}</span> <div class="info-card-right-section"> {{ if $tag }} <span class="info-card-tag info-card-tag-{{ $tagtype }}"> {{ $tag }} </span> {{ end }} {{ if $desc }} <div class="info-card-tooltip-wrapper"> <span class="info-card-icon" title="Показать информацию"> <svg class="info-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 13A6 6 0 1 1 8 2a6 6 0 0 1 0 12z"/> <path d="M7 11h2v2H7zm0-8h2v6H7z"/> </svg> </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ $desc }}</div> {{ if or $date $audience }} <div class="tooltip-details"> {{ if $date }} <div class="tooltip-date"> <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </svg> <span>Добавлено: {{ $date }}</span> </div> {{ end }} {{ if $audience }} <div class="tooltip-audience"> <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"> <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/> </svg> <span>Для кого: {{ $audience }}</span> </div> {{ end }} </div> {{ end }} </div> </div> {{ end }} </div> </div> </a> </div> <style> /* ===== ОСНОВНЫЕ СТИЛИ КАРТОЧЕК ===== */ .info-card { margin: 0.75rem 0; border: 1px solid #e0e0e0; border-radius: 8px; background: #ffffff; transition: all 0.2s ease; position: relative; } .info-card:hover { border-color: #4a90e2; box-shadow: 0 2px 8px rgba(74, 144, 226, 0.15); } .info-card-link { display: block; padding: 1rem 1.25rem; text-decoration: none; color: #333333; } .info-card-link:hover { text-decoration: none; } .info-card-header { display: flex; justify-content: space-between; align-items: center; min-height: 24px; } .info-card-title { font-size: 1rem; font-weight: 600; flex: 1; padding-right: 12px; color: #333333; line-height: 1.4; } /* ===== ПРАВАЯ СЕКЦИЯ ===== */ .info-card-right-section { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } /* ===== ТЕГИ ===== */ .info-card-tag { font-size: 0.75rem; padding: 0.15rem 0.5rem; border-radius: 10px; font-weight: 500; white-space: nowrap; border: 1px solid transparent; } .info-card-tag-default { background: #f0f0f0; color: #666666; border-color: #ddd; } .info-card-tag-info { background: #e3f2fd; color: #1565c0; border-color: #90caf9; } .info-card-tag-warning { background: #fff3e0; color: #e65100; border-color: #ffcc80; } .info-card-tag-success { background: #e8f5e9; color: #2e7d32; border-color: #a5d6a7; } .info-card-tag-error { background: #ffebee; color: #c62828; border-color: #ef9a9a; } /* ===== ИКОНКА И ТУЛТИП ===== */ .info-card-tooltip-wrapper { position: relative; display: flex; align-items: center; } .info-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; cursor: help; color: #666666; border-radius: 50%; transition: all 0.15s; } .info-card-icon:hover { background: #f0f0f0; color: #4a90e2; } .info-icon { width: 16px; height: 16px; } /* ===== ВСПЛЫВАЮЩАЯ ПОДСКАЗКА (ИСПРАВЛЕННАЯ ПОЗИЦИЯ И РАЗМЕР) ===== */ .info-card-tooltip { position: absolute; bottom: calc(100% + 10px); /* Показываем над иконкой */ right: 50%; transform: translateX(50%) translateY(0); width: 350px; /* Шире для большего текста */ max-width: 90vw; /* Но не шире экрана */ padding: 16px; background: white; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); border: 1px solid #e0e0e0; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); pointer-events: none; } /* Показываем тултип при наведении на обертку */ .info-card-tooltip-wrapper:hover .info-card-tooltip { opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(50%) translateY(-5px); } /* Стрелка тултипа (внизу, указывает на иконку) */ .info-card-tooltip::before { content: ''; position: absolute; bottom: -6px; left: 50%; transform: translateX(-50%) rotate(45deg); width: 12px; height: 12px; background: white; border-right: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0; z-index: -1; } .tooltip-description { font-size: 0.9rem; line-height: 1.5; color: #444444; margin-bottom: 12px; max-height: 200px; overflow-y: auto; padding-right: 4px; } /* Стили для скроллбара в описании */ .tooltip-description::-webkit-scrollbar { width: 4px; } .tooltip-description::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 2px; } .tooltip-description::-webkit-scrollbar-thumb { background: #c1c1c1; border-radius: 2px; } .tooltip-details { font-size: 0.82rem; color: #666666; border-top: 1px solid #f0f0f0; padding-top: 10px; } .tooltip-date, .tooltip-audience { margin-bottom: 6px; display: flex; align-items: flex-start; gap: 8px; line-height: 1.4; } .tooltip-date svg, .tooltip-audience svg { flex-shrink: 0; opacity: 0.7; margin-top: 2px; } /* ===== ТЕМНАЯ ТЕМА ===== */ body.dark .info-card, html.dark .info-card { background: #2d3748; border-color: #4a5568; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } body.dark .info-card:hover, html.dark .info-card:hover { border-color: #63b3ed; box-shadow: 0 2px 8px rgba(99, 179, 237, 0.2); } body.dark .info-card-link, html.dark .info-card-link { color: #e2e8f0; } body.dark .info-card-title, html.dark .info-card-title { color: #f7fafc; } body.dark .info-card-icon, html.dark .info-card-icon { color: #a0aec0; } body.dark .info-card-icon:hover, html.dark .info-card-icon:hover { background: #4a5568; color: #63b3ed; } body.dark .info-card-tooltip, html.dark .info-card-tooltip { background: #1a202c; border-color: #4a5568; box-shadow: 0 4px 20px rgba(0,0,0,0.4); } body.dark .info-card-tooltip::before, html.dark .info-card-tooltip::before { background: #1a202c; border-color: #4a5568; } body.dark .tooltip-description, html.dark .tooltip-description { color: #e2e8f0; } body.dark .tooltip-description::-webkit-scrollbar-track { background: #2d3748; } body.dark .tooltip-description::-webkit-scrollbar-thumb { background: #4a5568; } body.dark .tooltip-details, html.dark .tooltip-details { color: #a0aec0; border-top-color: #4a5568; } body.dark .info-card-tag-default, html.dark .info-card-tag-default { background: #4a5568; color: #cbd5e0; border-color: #718096; } body.dark .info-card-tag-info, html.dark .info-card-tag-info { background: #2c5282; color: #bee3f8; border-color: #3182ce; } body.dark .info-card-tag-warning, html.dark .info-card-tag-warning { background: #975a16; color: #feebc8; border-color: #d69e2e; } body.dark .info-card-tag-success, html.dark .info-card-tag-success { background: #276749; color: #c6f6d5; border-color: #38a169; } body.dark .info-card-tag-error, html.dark .info-card-tag-error { background: #9b2c2c; color: #fed7d7; border-color: #e53e3e; } /* ===== АДАПТИВНОСТЬ ===== */ @media (max-width: 768px) { .info-card-header { flex-direction: column; align-items: flex-start; gap: 8px; } .info-card-right-section { width: 100%; justify-content: space-between; } .info-card-tooltip { position: fixed; bottom: auto; top: 50%; left: 50%; right: auto; transform: translate(-50%, -50%) !important; width: calc(100vw - 40px); max-width: 500px; max-height: 70vh; overflow-y: auto; } .info-card-tooltip::before { display: none; } .info-card { margin: 0.5rem 0; } .info-card-link { padding: 0.75rem 1rem; } .tooltip-description { max-height: 40vh; } } /* Для очень узких экранов */ @media (max-width: 480px) { .info-card-tooltip { width: calc(100vw - 20px); padding: 12px; } .tooltip-description { font-size: 0.85rem; } } </style> <script> (function() { // Инициализация при загрузке страницы document.addEventListener('DOMContentLoaded', function() { initCardInfoTooltips(); }); // Инициализация при динамической загрузке if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initCardInfoTooltips); } else { initCardInfoTooltips(); } function initCardInfoTooltips() { const tooltipWrappers = document.querySelectorAll('.info-card-tooltip-wrapper'); tooltipWrappers.forEach(wrapper => { // Пропускаем если уже инициализирован if (wrapper.dataset.initialized === 'true') return; const tooltip = wrapper.querySelector('.info-card-tooltip'); const icon = wrapper.querySelector('.info-card-icon'); if (!tooltip || !icon) return; // Помечаем как инициализированный wrapper.dataset.initialized = 'true'; // Событие при наведении на иконку wrapper.addEventListener('mouseenter', function() { positionTooltip(wrapper, tooltip); tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; tooltip.style.pointerEvents = 'auto'; }); // Событие при уходе с иконки wrapper.addEventListener('mouseleave', function() { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; tooltip.style.pointerEvents = 'none'; }); // Для мобильных устройств - по клику wrapper.addEventListener('click', function(e) { if (window.innerWidth <= 768) { e.preventDefault(); e.stopPropagation(); positionTooltip(wrapper, tooltip); // Переключаем видимость if (tooltip.style.opacity === '1') { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; } else { tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; } } }); }); // Закрытие всех тултипов при клике вне document.addEventListener('click', function(e) { if (!e.target.closest('.info-card-tooltip-wrapper')) { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); // Закрытие по ESC document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); } function positionTooltip(wrapper, tooltip) { if (window.innerWidth <= 768) { // Для мобильных - центрируем tooltip.style.position = 'fixed'; tooltip.style.top = '50%'; tooltip.style.left = '50%'; tooltip.style.right = 'auto'; tooltip.style.bottom = 'auto'; tooltip.style.transform = 'translate(-50%, -50%)'; return; } const wrapperRect = wrapper.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; // Центрируем горизонтально относительно иконки const centerX = wrapperRect.left + (wrapperRect.width / 2); let left = centerX - (tooltipRect.width / 2); // Проверяем, чтобы тултип не выходил за границы экрана if (left < 10) { left = 10; } else if (left + tooltipRect.width > viewportWidth - 10) { left = viewportWidth - tooltipRect.width - 10; } // Позиционируем сверху от иконки const top = wrapperRect.top - tooltipRect.height - 10; // Если не хватает места сверху, показываем снизу if (top < 10) { tooltip.style.top = (wrapperRect.bottom + 10) + 'px'; tooltip.style.bottom = 'auto'; // Меняем стрелку на верхнюю tooltip.style.setProperty('--arrow-bottom', 'auto'); tooltip.style.setProperty('--arrow-top', '-6px'); tooltip.style.setProperty('--arrow-transform', 'rotate(-135deg)'); } else { tooltip.style.top = top + 'px'; tooltip.style.bottom = 'auto'; // Стрелка внизу tooltip.style.setProperty('--arrow-bottom', '-6px'); tooltip.style.setProperty('--arrow-top', 'auto'); tooltip.style.setProperty('--arrow-transform', 'rotate(45deg)'); } tooltip.style.left = left + 'px'; tooltip.style.right = 'auto'; tooltip.style.transform = 'none'; tooltip.style.position = 'fixed'; } // Перепозиционирование при изменении размера окна window.addEventListener('resize', function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }); // Переинициализация при изменении темы let lastDarkMode = document.body.classList.contains('dark'); function checkThemeChange() { const currentDarkMode = document.body.classList.contains('dark'); if (currentDarkMode !== lastDarkMode) { lastDarkMode = currentDarkMode; // Перепозиционируем все видимые тултипы setTimeout(function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }, 50); } } // Наблюдаем за изменениями класса dark const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.attributeName === 'class') { checkThemeChange(); } }); }); observer.observe(document.body, { attributes: true }); observer.observe(document.documentElement, { attributes: true }); // Также проверяем периодически на случай, если MutationObserver не сработал setInterval(checkThemeChange, 1000); })(); </script> |
Понедельник, 2026-01-12, 14:49
# 9
{{/* layouts/shortcodes/cardinfo.html */}}
{{ $link := .Get "link" }} {{ $title := .Get "title" }} {{ $desc := .Get "desc" | default "" }} {{ $date := .Get "date" }} {{ $audience := .Get "audience" }} {{ $tag := .Get "tag" }} {{ $tagtype := .Get "tagtype" | default "default" }} <div class="info-card"> <a href="{{ $link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <span class="info-card-title">{{ $title }}</span> <div class="info-card-right-section"> {{ if $tag }} <span class="info-card-tag info-card-tag-{{ $tagtype }}"> {{ $tag }} </span> {{ end }} {{ if $desc }} <div class="info-card-tooltip-wrapper"> <span class="info-card-icon" title="Показать информацию"> <svg class="info-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 13A6 6 0 1 1 8 2a6 6 0 0 1 0 12z"/> <path d="M7 11h2v2H7zm0-8h2v6H7z"/> </svg> </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ $desc }}</div> {{ if or $date $audience }} <div class="tooltip-details"> {{ if $date }} <div class="tooltip-date"> <svg class="tooltip-icon" width="12" height="12" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </svg> <span class="tooltip-text">Добавлено: {{ $date }}</span> </div> {{ end }} {{ if $audience }} <div class="tooltip-audience"> <svg class="tooltip-icon" width="12" height="12" viewBox="0 0 24 24" fill="currentColor"> <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/> </svg> <span class="tooltip-text">Для кого: {{ $audience }}</span> </div> {{ end }} </div> {{ end }} </div> </div> {{ end }} </div> </div> </a> </div> <style> /* ===== ОСНОВНЫЕ СТИЛИ КАРТОЧЕК ===== */ .info-card { margin: 0.75rem 0; border: 1px solid #e0e0e0; border-radius: 8px; background: #ffffff; transition: all 0.2s ease; position: relative; } .info-card:hover { border-color: #4a90e2; box-shadow: 0 2px 8px rgba(74, 144, 226, 0.15); } .info-card-link { display: block; padding: 1rem 1.25rem; text-decoration: none; color: #333333; } .info-card-link:hover { text-decoration: none; } .info-card-header { display: flex; justify-content: space-between; align-items: center; min-height: 24px; } .info-card-title { font-size: 1rem; font-weight: 600; flex: 1; padding-right: 12px; color: #333333; line-height: 1.4; } /* ===== ПРАВАЯ СЕКЦИЯ ===== */ .info-card-right-section { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } /* ===== ТЕГИ ===== */ .info-card-tag { font-size: 0.75rem; padding: 0.15rem 0.5rem; border-radius: 10px; font-weight: 500; white-space: nowrap; border: 1px solid transparent; } .info-card-tag-default { background: #f0f0f0; color: #666666; border-color: #ddd; } .info-card-tag-info { background: #e3f2fd; color: #1565c0; border-color: #90caf9; } .info-card-tag-warning { background: #fff3e0; color: #e65100; border-color: #ffcc80; } .info-card-tag-success { background: #e8f5e9; color: #2e7d32; border-color: #a5d6a7; } .info-card-tag-error { background: #ffebee; color: #c62828; border-color: #ef9a9a; } /* ===== ИКОНКА И ТУЛТИП ===== */ .info-card-tooltip-wrapper { position: relative; display: flex; align-items: center; } .info-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; cursor: help; color: #666666; border-radius: 50%; transition: all 0.15s; } .info-card-icon:hover { background: #f0f0f0; color: #4a90e2; } .info-icon { width: 16px; height: 16px; } /* ===== ВСПЛЫВАЮЩАЯ ПОДСКАЗКА ===== */ .info-card-tooltip { position: absolute; bottom: calc(100% + 10px); right: 50%; transform: translateX(50%) translateY(0); width: 350px; max-width: 90vw; padding: 16px; background: white; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); border: 1px solid #e0e0e0; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); pointer-events: none; } /* Показываем тултип при наведении на обертку */ .info-card-tooltip-wrapper:hover .info-card-tooltip { opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(50%) translateY(-5px); } /* Стрелка тултипа */ .info-card-tooltip::before { content: ''; position: absolute; bottom: -6px; left: 50%; transform: translateX(-50%) rotate(45deg); width: 12px; height: 12px; background: white; border-right: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0; z-index: -1; } .tooltip-description { font-size: 0.9rem; line-height: 1.5; color: #444444; margin-bottom: 12px; max-height: 200px; overflow-y: auto; padding-right: 4px; } /* Стили для скроллбара в описании */ .tooltip-description::-webkit-scrollbar { width: 4px; } .tooltip-description::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 2px; } .tooltip-description::-webkit-scrollbar-thumb { background: #c1c1c1; border-radius: 2px; } .tooltip-details { font-size: 0.82rem; color: #666666; border-top: 1px solid #f0f0f0; padding-top: 10px; } /* ИСПРАВЛЕНИЕ: ВЕРТИКАЛЬНОЕ ВЫРАВНИВАНИЕ ИКОНОК И ТЕКСТА */ .tooltip-date, .tooltip-audience { margin-bottom: 6px; display: flex; align-items: flex-start; /* Изменено с center на flex-start */ gap: 8px; line-height: 1.4; } .tooltip-icon { flex-shrink: 0; opacity: 0.7; margin-top: 2px; /* Добавлен отступ сверху для выравнивания */ } .tooltip-text { line-height: 1.4; flex: 1; } /* ===== ТЕМНАЯ ТЕМА ===== */ body.dark .info-card, html.dark .info-card { background: #2d3748; border-color: #4a5568; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } body.dark .info-card:hover, html.dark .info-card:hover { border-color: #63b3ed; box-shadow: 0 2px 8px rgba(99, 179, 237, 0.2); } body.dark .info-card-link, html.dark .info-card-link { color: #e2e8f0; } body.dark .info-card-title, html.dark .info-card-title { color: #f7fafc; } body.dark .info-card-icon, html.dark .info-card-icon { color: #a0aec0; } body.dark .info-card-icon:hover, html.dark .info-card-icon:hover { background: #4a5568; color: #63b3ed; } body.dark .info-card-tooltip, html.dark .info-card-tooltip { background: #1a202c; border-color: #4a5568; box-shadow: 0 4px 20px rgba(0,0,0,0.4); } body.dark .info-card-tooltip::before, html.dark .info-card-tooltip::before { background: #1a202c; border-color: #4a5568; } body.dark .tooltip-description, html.dark .tooltip-description { color: #e2e8f0; } body.dark .tooltip-description::-webkit-scrollbar-track { background: #2d3748; } body.dark .tooltip-description::-webkit-scrollbar-thumb { background: #4a5568; } body.dark .tooltip-details, html.dark .tooltip-details { color: #a0aec0; border-top-color: #4a5568; } body.dark .info-card-tag-default, html.dark .info-card-tag-default { background: #4a5568; color: #cbd5e0; border-color: #718096; } body.dark .info-card-tag-info, html.dark .info-card-tag-info { background: #2c5282; color: #bee3f8; border-color: #3182ce; } body.dark .info-card-tag-warning, html.dark .info-card-tag-warning { background: #975a16; color: #feebc8; border-color: #d69e2e; } body.dark .info-card-tag-success, html.dark .info-card-tag-success { background: #276749; color: #c6f6d5; border-color: #38a169; } body.dark .info-card-tag-error, html.dark .info-card-tag-error { background: #9b2c2c; color: #fed7d7; border-color: #e53e3e; } /* ===== АДАПТИВНОСТЬ ===== */ @media (max-width: 768px) { .info-card-header { flex-direction: column; align-items: flex-start; gap: 8px; } .info-card-right-section { width: 100%; justify-content: space-between; } .info-card-tooltip { position: fixed; bottom: auto; top: 50%; left: 50%; right: auto; transform: translate(-50%, -50%) !important; width: calc(100vw - 40px); max-width: 500px; max-height: 70vh; overflow-y: auto; } .info-card-tooltip::before { display: none; } .info-card { margin: 0.5rem 0; } .info-card-link { padding: 0.75rem 1rem; } .tooltip-description { max-height: 40vh; } .tooltip-date, .tooltip-audience { align-items: flex-start; } .tooltip-icon { margin-top: 3px; /* Немного больше на мобильных */ } } /* Для очень узких экранов */ @media (max-width: 480px) { .info-card-tooltip { width: calc(100vw - 20px); padding: 12px; } .tooltip-description { font-size: 0.85rem; } .tooltip-details { font-size: 0.8rem; } } </style> <script> (function() { document.addEventListener('DOMContentLoaded', function() { initCardInfoTooltips(); }); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initCardInfoTooltips); } else { initCardInfoTooltips(); } function initCardInfoTooltips() { const tooltipWrappers = document.querySelectorAll('.info-card-tooltip-wrapper'); tooltipWrappers.forEach(wrapper => { if (wrapper.dataset.initialized === 'true') return; const tooltip = wrapper.querySelector('.info-card-tooltip'); const icon = wrapper.querySelector('.info-card-icon'); if (!tooltip || !icon) return; wrapper.dataset.initialized = 'true'; wrapper.addEventListener('mouseenter', function() { positionTooltip(wrapper, tooltip); tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; tooltip.style.pointerEvents = 'auto'; }); wrapper.addEventListener('mouseleave', function() { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; tooltip.style.pointerEvents = 'none'; }); wrapper.addEventListener('click', function(e) { if (window.innerWidth <= 768) { e.preventDefault(); e.stopPropagation(); positionTooltip(wrapper, tooltip); if (tooltip.style.opacity === '1') { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; } else { tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; } } }); }); document.addEventListener('click', function(e) { if (!e.target.closest('.info-card-tooltip-wrapper')) { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); } function positionTooltip(wrapper, tooltip) { if (window.innerWidth <= 768) { tooltip.style.position = 'fixed'; tooltip.style.top = '50%'; tooltip.style.left = '50%'; tooltip.style.right = 'auto'; tooltip.style.bottom = 'auto'; tooltip.style.transform = 'translate(-50%, -50%)'; return; } const wrapperRect = wrapper.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); const viewportWidth = window.innerWidth; const centerX = wrapperRect.left + (wrapperRect.width / 2); let left = centerX - (tooltipRect.width / 2); if (left < 10) { left = 10; } else if (left + tooltipRect.width > viewportWidth - 10) { left = viewportWidth - tooltipRect.width - 10; } const top = wrapperRect.top - tooltipRect.height - 10; if (top < 10) { tooltip.style.top = (wrapperRect.bottom + 10) + 'px'; tooltip.style.bottom = 'auto'; } else { tooltip.style.top = top + 'px'; tooltip.style.bottom = 'auto'; } tooltip.style.left = left + 'px'; tooltip.style.right = 'auto'; tooltip.style.transform = 'none'; tooltip.style.position = 'fixed'; } window.addEventListener('resize', function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }); let lastDarkMode = document.body.classList.contains('dark'); function checkThemeChange() { const currentDarkMode = document.body.classList.contains('dark'); if (currentDarkMode !== lastDarkMode) { lastDarkMode = currentDarkMode; setTimeout(function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }, 50); } } const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.attributeName === 'class') { checkThemeChange(); } }); }); observer.observe(document.body, { attributes: true }); observer.observe(document.documentElement, { attributes: true }); setInterval(checkThemeChange, 1000); })(); </script> |
Понедельник, 2026-01-12, 15:02
# 10
Понял! Давайте решим обе проблемы:
1. Исправим вертикальное выравнивание иконок в тултипе 2. Добавим возможность отображать иконки слева от названия Вот обновленная версия: ```html {{/* layouts/shortcodes/cardinfo.html */}} {{ $link := .Get "link" }} {{ $title := .Get "title" }} {{ $desc := .Get "desc" | default "" }} {{ $date := .Get "date" }} {{ $audience := .Get "audience" }} {{ $tag := .Get "tag" }} {{ $tagtype := .Get "tagtype" | default "default" }} {{ $icon := .Get "icon" }} {{ $iconsize := .Get "iconsize" | default "24" }} <div class="info-card"> <a href="{{ $link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <div class="info-card-left"> {{ if $icon }} <span class="info-card-title-icon"> {{ $iconContent := printf `<span class="custom-icon" style="width: %spx; height: %spx;">{{<icon "%s">}}</span>` $iconsize $iconsize $icon }} {{ $iconContent | safeHTML }} </span> {{ end }} <span class="info-card-title">{{ $title }}</span> </div> <div class="info-card-right-section"> {{ if $tag }} <span class="info-card-tag info-card-tag-{{ $tagtype }}"> {{ $tag }} </span> {{ end }} {{ if $desc }} <div class="info-card-tooltip-wrapper"> <span class="info-card-icon" title="Показать информацию"> <svg class="info-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 13A6 6 0 1 1 8 2a6 6 0 0 1 0 12z"/> <path d="M7 11h2v2H7zm0-8h2v6H7z"/> </svg> </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ $desc }}</div> {{ if or $date $audience }} <div class="tooltip-details"> {{ if $date }} <div class="tooltip-row"> <svg class="tooltip-row-icon" width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </svg> <span class="tooltip-row-text">Добавлено: {{ $date }}</span> </div> {{ end }} {{ if $audience }} <div class="tooltip-row"> <svg class="tooltip-row-icon" width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/> </svg> <span class="tooltip-row-text">Для кого: {{ $audience }}</span> </div> {{ end }} </div> {{ end }} </div> </div> {{ end }} </div> </div> </a> </div> <style> /* ===== ОСНОВНЫЕ СТИЛИ КАРТОЧЕК ===== */ .info-card { margin: 0.75rem 0; border: 1px solid #e0e0e0; border-radius: 8px; background: #ffffff; transition: all 0.2s ease; position: relative; } .info-card:hover { border-color: #4a90e2; box-shadow: 0 2px 8px rgba(74, 144, 226, 0.15); } .info-card-link { display: block; padding: 1rem 1.25rem; text-decoration: none; color: #333333; } .info-card-link:hover { text-decoration: none; } .info-card-header { display: flex; justify-content: space-between; align-items: center; min-height: 24px; } /* Левая часть с иконкой и заголовком */ .info-card-left { display: flex; align-items: center; flex: 1; padding-right: 12px; min-height: 24px; gap: 10px; } .info-card-title-icon { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; } .info-card-title-icon .custom-icon { display: inline-flex; align-items: center; justify-content: center; } .info-card-title-icon .custom-icon svg { width: 100%; height: 100%; fill: currentColor; color: #666666; } .info-card-title { font-size: 1rem; font-weight: 600; color: #333333; line-height: 1.4; flex: 1; } /* ===== ПРАВАЯ СЕКЦИЯ ===== */ .info-card-right-section { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } /* ===== ТЕГИ ===== */ .info-card-tag { font-size: 0.75rem; padding: 0.15rem 0.5rem; border-radius: 10px; font-weight: 500; white-space: nowrap; border: 1px solid transparent; } .info-card-tag-default { background: #f0f0f0; color: #666666; border-color: #ddd; } .info-card-tag-info { background: #e3f2fd; color: #1565c0; border-color: #90caf9; } .info-card-tag-warning { background: #fff3e0; color: #e65100; border-color: #ffcc80; } .info-card-tag-success { background: #e8f5e9; color: #2e7d32; border-color: #a5d6a7; } .info-card-tag-error { background: #ffebee; color: #c62828; border-color: #ef9a9a; } /* ===== ИКОНКА И ТУЛТИП ===== */ .info-card-tooltip-wrapper { position: relative; display: flex; align-items: center; } .info-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; cursor: help; color: #666666; border-radius: 50%; transition: all 0.15s; } .info-card-icon:hover { background: #f0f0f0; color: #4a90e2; } .info-icon { width: 16px; height: 16px; } /* ===== ВСПЛЫВАЮЩАЯ ПОДСКАЗКА ===== */ .info-card-tooltip { position: absolute; bottom: calc(100% + 10px); right: 50%; transform: translateX(50%) translateY(0); width: 350px; max-width: 90vw; padding: 16px; background: white; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); border: 1px solid #e0e0e0; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); pointer-events: none; } /* Показываем тултип при наведении на обертку */ .info-card-tooltip-wrapper:hover .info-card-tooltip { opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(50%) translateY(-5px); } /* Стрелка тултипа */ .info-card-tooltip::before { content: ''; position: absolute; bottom: -6px; left: 50%; transform: translateX(-50%) rotate(45deg); width: 12px; height: 12px; background: white; border-right: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0; z-index: -1; } .tooltip-description { font-size: 0.9rem; line-height: 1.5; color: #444444; margin-bottom: 12px; max-height: 200px; overflow-y: auto; padding-right: 4px; } /* Стили для скроллбара в описании */ .tooltip-description::-webkit-scrollbar { width: 4px; } .tooltip-description::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 2px; } .tooltip-description::-webkit-scrollbar-thumb { background: #c1c1c1; border-radius: 2px; } .tooltip-details { font-size: 0.82rem; color: #666666; border-top: 1px solid #f0f0f0; padding-top: 10px; } /* ИСПРАВЛЕНИЕ: ВЕРТИКАЛЬНОЕ ВЫРАВНИВАНИЕ ИКОНОК И ТЕКСТА В ТУЛТИПЕ */ .tooltip-row { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 6px; line-height: 1.4; } .tooltip-row:last-child { margin-bottom: 0; } .tooltip-row-icon { flex-shrink: 0; margin-top: 1px; /* Точная настройка выравнивания */ opacity: 0.7; } .tooltip-row-text { line-height: 1.4; flex: 1; } /* ===== ТЕМНАЯ ТЕМА ===== */ body.dark .info-card, html.dark .info-card { background: #2d3748; border-color: #4a5568; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } body.dark .info-card:hover, html.dark .info-card:hover { border-color: #63b3ed; box-shadow: 0 2px 8px rgba(99, 179, 237, 0.2); } body.dark .info-card-link, html.dark .info-card-link { color: #e2e8f0; } body.dark .info-card-title, html.dark .info-card-title { color: #f7fafc; } body.dark .info-card-title-icon .custom-icon svg { color: #a0aec0; } body.dark .info-card-icon, html.dark .info-card-icon { color: #a0aec0; } body.dark .info-card-icon:hover, html.dark .info-card-icon:hover { background: #4a5568; color: #63b3ed; } body.dark .info-card-tooltip, html.dark .info-card-tooltip { background: #1a202c; border-color: #4a5568; box-shadow: 0 4px 20px rgba(0,0,0,0.4); } body.dark .info-card-tooltip::before, html.dark .info-card-tooltip::before { background: #1a202c; border-color: #4a5568; } body.dark .tooltip-description, html.dark .tooltip-description { color: #e2e8f0; } body.dark .tooltip-description::-webkit-scrollbar-track { background: #2d3748; } body.dark .tooltip-description::-webkit-scrollbar-thumb { background: #4a5568; } body.dark .tooltip-details, html.dark .tooltip-details { color: #a0aec0; border-top-color: #4a5568; } body.dark .info-card-tag-default, html.dark .info-card-tag-default { background: #4a5568; color: #cbd5e0; border-color: #718096; } body.dark .info-card-tag-info, html.dark .info-card-tag-info { background: #2c5282; color: #bee3f8; border-color: #3182ce; } body.dark .info-card-tag-warning, html.dark .info-card-tag-warning { background: #975a16; color: #feebc8; border-color: #d69e2e; } body.dark .info-card-tag-success, html.dark .info-card-tag-success { background: #276749; color: #c6f6d5; border-color: #38a169; } body.dark .info-card-tag-error, html.dark .info-card-tag-error { background: #9b2c2c; color: #fed7d7; border-color: #e53e3e; } /* ===== АДАПТИВНОСТЬ ===== */ @media (max-width: 768px) { .info-card-header { flex-direction: column; align-items: flex-start; gap: 8px; } .info-card-left { width: 100%; padding-right: 0; } .info-card-right-section { width: 100%; justify-content: space-between; } .info-card-tooltip { position: fixed; bottom: auto; top: 50%; left: 50%; right: auto; transform: translate(-50%, -50%) !important; width: calc(100vw - 40px); max-width: 500px; max-height: 70vh; overflow-y: auto; } .info-card-tooltip::before { display: none; } .info-card { margin: 0.5rem 0; } .info-card-link { padding: 0.75rem 1rem; } .tooltip-description { max-height: 40vh; } .tooltip-row { align-items: flex-start; } .tooltip-row-icon { margin-top: 2px; } } /* Для очень узких экранов */ @media (max-width: 480px) { .info-card-tooltip { width: calc(100vw - 20px); padding: 12px; } .tooltip-description { font-size: 0.85rem; } .tooltip-details { font-size: 0.8rem; } .info-card-left { gap: 8px; } } </style> <script> (function() { document.addEventListener('DOMContentLoaded', function() { initCardInfoTooltips(); }); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initCardInfoTooltips); } else { initCardInfoTooltips(); } function initCardInfoTooltips() { const tooltipWrappers = document.querySelectorAll('.info-card-tooltip-wrapper'); tooltipWrappers.forEach(wrapper => { if (wrapper.dataset.initialized === 'true') return; const tooltip = wrapper.querySelector('.info-card-tooltip'); const icon = wrapper.querySelector('.info-card-icon'); if (!tooltip || !icon) return; wrapper.dataset.initialized = 'true'; wrapper.addEventListener('mouseenter', function() { positionTooltip(wrapper, tooltip); tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; tooltip.style.pointerEvents = 'auto'; }); wrapper.addEventListener('mouseleave', function() { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; tooltip.style.pointerEvents = 'none'; }); wrapper.addEventListener('click', function(e) { if (window.innerWidth <= 768) { e.preventDefault(); e.stopPropagation(); positionTooltip(wrapper, tooltip); if (tooltip.style.opacity === '1') { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; } else { tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; } } }); }); document.addEventListener('click', function(e) { if (!e.target.closest('.info-card-tooltip-wrapper')) { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); } function positionTooltip(wrapper, tooltip) { if (window.innerWidth <= 768) { tooltip.style.position = 'fixed'; tooltip.style.top = '50%'; tooltip.style.left = '50%'; tooltip.style.right = 'auto'; tooltip.style.bottom = 'auto'; tooltip.style.transform = 'translate(-50%, -50%)'; return; } const wrapperRect = wrapper.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); const viewportWidth = window.innerWidth; const centerX = wrapperRect.left + (wrapperRect.width / 2); let left = centerX - (tooltipRect.width / 2); if (left < 10) { left = 10; } else if (left + tooltipRect.width > viewportWidth - 10) { left = viewportWidth - tooltipRect.width - 10; } const top = wrapperRect.top - tooltipRect.height - 10; if (top < 10) { tooltip.style.top = (wrapperRect.bottom + 10) + 'px'; tooltip.style.bottom = 'auto'; } else { tooltip.style.top = top + 'px'; tooltip.style.bottom = 'auto'; } tooltip.style.left = left + 'px'; tooltip.style.right = 'auto'; tooltip.style.transform = 'none'; tooltip.style.position = 'fixed'; } window.addEventListener('resize', function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }); let lastDarkMode = document.body.classList.contains('dark'); function checkThemeChange() { const currentDarkMode = document.body.classList.contains('dark'); if (currentDarkMode !== lastDarkMode) { lastDarkMode = currentDarkMode; setTimeout(function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }, 50); } } const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.attributeName === 'class') { checkThemeChange(); } }); }); observer.observe(document.body, { attributes: true }); observer.observe(document.documentElement, { attributes: true }); setInterval(checkThemeChange, 1000); })(); </script> ``` Пример использования с иконкой: ```markdown {{< cardinfo link="http://AssayMovement" title="Движение проб" desc="Отслеживание прохождения проб от отбора до получения результатов" date="15.10.2023" audience="Геологи" tag="Лаборатория" tagtype="info" icon="lab-icon" <!-- Название вашей SVG иконки --> iconsize="24" >}} <!-- Размер иконки в пикселях --> {{< cardinfo link="http://AssayMovement1" title="Движение проб - сводный отчет" desc="Консолидированный отчет по всем активным объектам" <!-- Без иконки - она не отобразится --> tag="Важное" tagtype="warning" >}} ``` Ключевые изменения: 1. Исправлено вертикальное выравнивание в тултипе: · Используем класс .tooltip-row для строк · Добавлен margin-top: 1px для иконок для точного выравнивания · Используем align-items: flex-start вместо center 2. Добавлена поддержка иконок слева от заголовка: · Параметр icon="название-иконки" · Параметр iconsize="24" (по умолчанию 24px) · Иконка отображается только если указана · Использует ваш shortcode {{<icon "название">}} 3. Улучшена структура HTML: · Добавлен .info-card-left контейнер для иконки и заголовка · Иконка и текст выровнены по вертикали · Поддержка темной темы для иконок Теперь иконки в тултипе должны быть точно выровнены с текстом, а также можно добавлять иконки к заголовкам карточек. |
Понедельник, 2026-01-12, 15:11
# 11
{{/* layouts/shortcodes/cardinfo.html */}}
{{ $link := .Get "link" }} {{ $title := .Get "title" }} {{ $desc := .Get "desc" | default "" }} {{ $date := .Get "date" }} {{ $audience := .Get "audience" }} {{ $tag := .Get "tag" }} {{ $tagtype := .Get "tagtype" | default "default" }} {{ $icon := .Get "icon" }} {{ $iconsize := .Get "iconsize" | default "24" }} <div class="info-card"> <a href="{{ $link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <div class="info-card-left"> {{ if $icon }} <span class="info-card-title-icon"> {{ if eq $icon "database" }} <svg class="custom-icon" style="width: {{ $iconsize }}px; height: {{ $iconsize }}px;" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 3C7.58 3 4 4.79 4 7s3.58 4 8 4 8-1.79 8-4-3.58-4-8-4zm0 6c-3.87 0-7-1.79-7-4s3.13-4 7-4 7 1.79 7 4-3.13 4-7 4zm0 1c-3.87 0-7 1.79-7 4v3h14v-3c0-2.21-3.13-4-7-4zm6 5H6v-.99c.2-.72 3.3-2.01 6-2.01s5.8 1.29 6 2v1z"/> </svg> {{ else if eq $icon "chart" }} <svg class="custom-icon" style="width: {{ $iconsize }}px; height: {{ $iconsize }}px;" viewBox="0 0 24 24" fill="currentColor"> <path d="M3.5 18.49l6-6.01 4 4L22 6.92l-1.41-1.41-7.09 7.97-4-4L2 16.99z"/> </svg> {{ else if eq $icon "lab" }} <svg class="custom-icon" style="width: {{ $iconsize }}px; height: {{ $iconsize }}px;" viewBox="0 0 24 24" fill="currentColor"> <path d="M19.3 14.89l-4.08-4.08c-.56.35-1.2.57-1.88.57-1.93 0-3.5-1.57-3.5-3.5 0-.68.22-1.32.57-1.88L4.89 5.7A7.47 7.47 0 0 0 2.5 12c0 4.14 3.36 7.5 7.5 7.5 1.71 0 3.28-.58 4.53-1.55l3.85 3.85 1.41-1.41-3.85-3.85c.97-1.25 1.55-2.82 1.55-4.54 0-1.08-.24-2.11-.67-3.04zM12 17.5c-3.03 0-5.5-2.47-5.5-5.5 0-1.33.48-2.55 1.28-3.5l7.22 7.22c-.95.8-2.17 1.28-3.5 1.28z"/> </svg> {{ else if eq $icon "document" }} <svg class="custom-icon" style="width: {{ $iconsize }}px; height: {{ $iconsize }}px;" viewBox="0 0 24 24" fill="currentColor"> <path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/> </svg> {{ else if eq $icon "map" }} <svg class="custom-icon" style="width: {{ $iconsize }}px; height: {{ $iconsize }}px;" viewBox="0 0 24 24" fill="currentColor"> <path d="M20.5 3l-.16.03L15 5.1 9 3 3.36 4.9c-.21.07-.36.25-.36.48V20.5c0 .28.22.5.5.5l.16-.03L9 18.9l6 2.1 5.64-1.9c.21-.07.36-.25.36-.48V3.5c0-.28-.22-.5-.5-.5zM15 19l-6-2.11V5l6 2.11V19z"/> </svg> {{ else if eq $icon "settings" }} <svg class="custom-icon" style="width: {{ $iconsize }}px; height: {{ $iconsize }}px;" viewBox="0 0 24 24" fill="currentColor"> <path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/> </svg> {{ else if eq $icon "report" }} <svg class="custom-icon" style="width: {{ $iconsize }}px; height: {{ $iconsize }}px;" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/> </svg> {{ else if eq $icon "user" }} <svg class="custom-icon" style="width: {{ $iconsize }}px; height: {{ $iconsize }}px;" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/> </svg> {{ else if eq $icon "time" }} <svg class="custom-icon" style="width: {{ $iconsize }}px; height: {{ $iconsize }}px;" viewBox="0 0 24 24" fill="currentColor"> <path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/> </svg> {{ else if eq $icon "calendar" }} <svg class="custom-icon" style="width: {{ $iconsize }}px; height: {{ $iconsize }}px;" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </svg> {{ else if eq $icon "warning" }} <svg class="custom-icon" style="width: {{ $iconsize }}px; height: {{ $iconsize }}px;" viewBox="0 0 24 24" fill="currentColor"> <path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/> </svg> {{ else }} <!-- Если иконка не найдена, можно использовать иконку по умолчанию или ничего --> <svg class="custom-icon" style="width: {{ $iconsize }}px; height: {{ $iconsize }}px;" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/> </svg> {{ end }} </span> {{ end }} <span class="info-card-title">{{ $title }}</span> </div> <div class="info-card-right-section"> {{ if $tag }} <span class="info-card-tag info-card-tag-{{ $tagtype }}"> {{ $tag }} </span> {{ end }} {{ if $desc }} <div class="info-card-tooltip-wrapper"> <span class="info-card-icon" title="Показать информацию"> <svg class="info-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 13A6 6 0 1 1 8 2a6 6 0 0 1 0 12z"/> <path d="M7 11h2v2H7zm0-8h2v6H7z"/> </svg> </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ $desc }}</div> {{ if or $date $audience }} <div class="tooltip-details"> {{ if $date }} <div class="tooltip-row"> <svg class="tooltip-row-icon" width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </svg> <span class="tooltip-row-text">Добавлено: {{ $date }}</span> </div> {{ end }} {{ if $audience }} <div class="tooltip-row"> <svg class="tooltip-row-icon" width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/> </svg> <span class="tooltip-row-text">Для кого: {{ $audience }}</span> </div> {{ end }} </div> {{ end }} </div> </div> {{ end }} </div> </div> </a> </div> <style> /* ===== ОСНОВНЫЕ СТИЛИ КАРТОЧЕК ===== */ .info-card { margin: 0.75rem 0; border: 1px solid #e0e0e0; border-radius: 8px; background: #ffffff; transition: all 0.2s ease; position: relative; } .info-card:hover { border-color: #4a90e2; box-shadow: 0 2px 8px rgba(74, 144, 226, 0.15); } .info-card-link { display: block; padding: 1rem 1.25rem; text-decoration: none; color: #333333; } .info-card-link:hover { text-decoration: none; } .info-card-header { display: flex; justify-content: space-between; align-items: center; min-height: 24px; } /* Левая часть с иконкой и заголовком */ .info-card-left { display: flex; align-items: center; flex: 1; padding-right: 12px; min-height: 24px; gap: 10px; } .info-card-title-icon { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; } .info-card-title-icon .custom-icon { display: inline-flex; align-items: center; justify-content: center; } .info-card-title-icon .custom-icon svg { width: 100%; height: 100%; fill: currentColor; color: #666666; } .info-card-title { font-size: 1rem; font-weight: 600; color: #333333; line-height: 1.4; flex: 1; } /* ===== ПРАВАЯ СЕКЦИЯ ===== */ .info-card-right-section { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } /* ===== ТЕГИ ===== */ .info-card-tag { font-size: 0.75rem; padding: 0.15rem 0.5rem; border-radius: 10px; font-weight: 500; white-space: nowrap; border: 1px solid transparent; } .info-card-tag-default { background: #f0f0f0; color: #666666; border-color: #ddd; } .info-card-tag-info { background: #e3f2fd; color: #1565c0; border-color: #90caf9; } .info-card-tag-warning { background: #fff3e0; color: #e65100; border-color: #ffcc80; } .info-card-tag-success { background: #e8f5e9; color: #2e7d32; border-color: #a5d6a7; } .info-card-tag-error { background: #ffebee; color: #c62828; border-color: #ef9a9a; } /* ===== ИКОНКА И ТУЛТИП ===== */ .info-card-tooltip-wrapper { position: relative; display: flex; align-items: center; } .info-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; cursor: help; color: #666666; border-radius: 50%; transition: all 0.15s; } .info-card-icon:hover { background: #f0f0f0; color: #4a90e2; } .info-icon { width: 16px; height: 16px; } /* ===== ВСПЛЫВАЮЩАЯ ПОДСКАЗКА ===== */ .info-card-tooltip { position: absolute; bottom: calc(100% + 10px); right: 50%; transform: translateX(50%) translateY(0); width: 350px; max-width: 90vw; padding: 16px; background: white; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); border: 1px solid #e0e0e0; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); pointer-events: none; } /* Показываем тултип при наведении на обертку */ .info-card-tooltip-wrapper:hover .info-card-tooltip { opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(50%) translateY(-5px); } /* Стрелка тултипа */ .info-card-tooltip::before { content: ''; position: absolute; bottom: -6px; left: 50%; transform: translateX(-50%) rotate(45deg); width: 12px; height: 12px; background: white; border-right: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0; z-index: -1; } .tooltip-description { font-size: 0.9rem; line-height: 1.5; color: #444444; margin-bottom: 12px; max-height: 200px; overflow-y: auto; padding-right: 4px; } /* Стили для скроллбара в описании */ .tooltip-description::-webkit-scrollbar { width: 4px; } .tooltip-description::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 2px; } .tooltip-description::-webkit-scrollbar-thumb { background: #c1c1c1; border-radius: 2px; } .tooltip-details { font-size: 0.82rem; color: #666666; border-top: 1px solid #f0f0f0; padding-top: 10px; } /* ИСПРАВЛЕНИЕ: ВЕРТИКАЛЬНОЕ ВЫРАВНИВАНИЕ ИКОНОК И ТЕКСТА В ТУЛТИПЕ */ .tooltip-row { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 6px; line-height: 1.4; } .tooltip-row:last-child { margin-bottom: 0; } .tooltip-row-icon { flex-shrink: 0; margin-top: 1px; /* Точная настройка выравнивания */ opacity: 0.7; } .tooltip-row-text { line-height: 1.4; flex: 1; } /* ===== ТЕМНАЯ ТЕМА ===== */ body.dark .info-card, html.dark .info-card { background: #2d3748; border-color: #4a5568; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } body.dark .info-card:hover, html.dark .info-card:hover { border-color: #63b3ed; box-shadow: 0 2px 8px rgba(99, 179, 237, 0.2); } body.dark .info-card-link, html.dark .info-card-link { color: #e2e8f0; } body.dark .info-card-title, html.dark .info-card-title { color: #f7fafc; } body.dark .info-card-title-icon .custom-icon svg { color: #a0aec0; } body.dark .info-card-icon, html.dark .info-card-icon { color: #a0aec0; } body.dark .info-card-icon:hover, html.dark .info-card-icon:hover { background: #4a5568; color: #63b3ed; } body.dark .info-card-tooltip, html.dark .info-card-tooltip { background: #1a202c; border-color: #4a5568; box-shadow: 0 4px 20px rgba(0,0,0,0.4); } body.dark .info-card-tooltip::before, html.dark .info-card-tooltip::before { background: #1a202c; border-color: #4a5568; } body.dark .tooltip-description, html.dark .tooltip-description { color: #e2e8f0; } body.dark .tooltip-description::-webkit-scrollbar-track { background: #2d3748; } body.dark .tooltip-description::-webkit-scrollbar-thumb { background: #4a5568; } body.dark .tooltip-details, html.dark .tooltip-details { color: #a0aec0; border-top-color: #4a5568; } body.dark .info-card-tag-default, html.dark .info-card-tag-default { background: #4a5568; color: #cbd5e0; border-color: #718096; } body.dark .info-card-tag-info, html.dark .info-card-tag-info { background: #2c5282; color: #bee3f8; border-color: #3182ce; } body.dark .info-card-tag-warning, html.dark .info-card-tag-warning { background: #975a16; color: #feebc8; border-color: #d69e2e; } body.dark .info-card-tag-success, html.dark .info-card-tag-success { background: #276749; color: #c6f6d5; border-color: #38a169; } body.dark .info-card-tag-error, html.dark .info-card-tag-error { background: #9b2c2c; color: #fed7d7; border-color: #e53e3e; } /* ===== АДАПТИВНОСТЬ ===== */ @media (max-width: 768px) { .info-card-header { flex-direction: column; align-items: flex-start; gap: 8px; } .info-card-left { width: 100%; padding-right: 0; } .info-card-right-section { width: 100%; justify-content: space-between; } .info-card-tooltip { position: fixed; bottom: auto; top: 50%; left: 50%; right: auto; transform: translate(-50%, -50%) !important; width: calc(100vw - 40px); max-width: 500px; max-height: 70vh; overflow-y: auto; } .info-card-tooltip::before { display: none; } .info-card { margin: 0.5rem 0; } .info-card-link { padding: 0.75rem 1rem; } .tooltip-description { max-height: 40vh; } .tooltip-row { align-items: flex-start; } .tooltip-row-icon { margin-top: 2px; } } /* Для очень узких экранов */ @media (max-width: 480px) { .info-card-tooltip { width: calc(100vw - 20px); padding: 12px; } .tooltip-description { font-size: 0.85rem; } .tooltip-details { font-size: 0.8rem; } .info-card-left { gap: 8px; } } </style> <script> (function() { document.addEventListener('DOMContentLoaded', function() { initCardInfoTooltips(); }); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initCardInfoTooltips); } else { initCardInfoTooltips(); } function initCardInfoTooltips() { const tooltipWrappers = document.querySelectorAll('.info-card-tooltip-wrapper'); tooltipWrappers.forEach(wrapper => { if (wrapper.dataset.initialized === 'true') return; const tooltip = wrapper.querySelector('.info-card-tooltip'); const icon = wrapper.querySelector('.info-card-icon'); if (!tooltip || !icon) return; wrapper.dataset.initialized = 'true'; wrapper.addEventListener('mouseenter', function() { positionTooltip(wrapper, tooltip); tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; tooltip.style.pointerEvents = 'auto'; }); wrapper.addEventListener('mouseleave', function() { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; tooltip.style.pointerEvents = 'none'; }); wrapper.addEventListener('click', function(e) { if (window.innerWidth <= 768) { e.preventDefault(); e.stopPropagation(); positionTooltip(wrapper, tooltip); if (tooltip.style.opacity === '1') { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; } else { tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; } } }); }); document.addEventListener('click', function(e) { if (!e.target.closest('.info-card-tooltip-wrapper')) { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); } function positionTooltip(wrapper, tooltip) { if (window.innerWidth <= 768) { tooltip.style.position = 'fixed'; tooltip.style.top = '50%'; tooltip.style.left = '50%'; tooltip.style.right = 'auto'; tooltip.style.bottom = 'auto'; tooltip.style.transform = 'translate(-50%, -50%)'; return; } const wrapperRect = wrapper.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); const viewportWidth = window.innerWidth; const centerX = wrapperRect.left + (wrapperRect.width / 2); let left = centerX - (tooltipRect.width / 2); if (left < 10) { left = 10; } else if (left + tooltipRect.width > viewportWidth - 10) { left = viewportWidth - tooltipRect.width - 10; } const top = wrapperRect.top - tooltipRect.height - 10; if (top < 10) { tooltip.style.top = (wrapperRect.bottom + 10) + 'px'; tooltip.style.bottom = 'auto'; } else { tooltip.style.top = top + 'px'; tooltip.style.bottom = 'auto'; } tooltip.style.left = left + 'px'; tooltip.style.right = 'auto'; tooltip.style.transform = 'none'; tooltip.style.position = 'fixed'; } window.addEventListener('resize', function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }); let lastDarkMode = document.body.classList.contains('dark'); function checkThemeChange() { const currentDarkMode = document.body.classList.contains('dark'); if (currentDarkMode !== lastDarkMode) { lastDarkMode = currentDarkMode; setTimeout(function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }, 50); } } const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.attributeName === 'class') { checkThemeChange(); } }); }); observer.observe(document.body, { attributes: true }); observer.observe(document.documentElement, { attributes: true }); setInterval(checkThemeChange, 1000); })(); </script> |
Понедельник, 2026-01-12, 15:13
# 12
{{- /* Обрабатываем параметры */ -}}
{{- $name := "" -}} {{- $size := "19px" -}} {{- if .IsNamedParams -}} {{- /* Именованные параметры: {{<icon name="..." size="...">}} */ -}} {{- $name = .Get "name" -}} {{- $size = .Get "size" | default "1em" -}} {{- else -}} {{- /* Позиционные параметры: {{<icon "name" "size">}} */ -}} {{- $name = .Get 0 -}} {{- if ge (len .Params) 2 -}} {{- $size = .Get 1 -}} {{- end -}} {{- end -}} {{- $icon := index site.Data.icons $name -}} {{- if not $icon -}} {{- errorf "icon %q not found" $name -}} {{- end -}} {{- /* Добавляем размер к SVG */ -}} {{- $icon = replaceRE "<svg" (printf "<svg width='%s' height='%s'" $size $size) $icon -}} <span class="hx-inline-block hx-align-text-bottom icon"> {{- $icon | safeHTML -}} </span> |
Понедельник, 2026-01-12, 15:18
# 13
Отлично! Теперь понятно. У вас есть shortcode icon, который берет иконки из site.Data.icons. Нужно использовать его правильно. Вот исправленная версия:
```html {{/* layouts/shortcodes/cardinfo.html */}} {{ $link := .Get "link" }} {{ $title := .Get "title" }} {{ $desc := .Get "desc" | default "" }} {{ $date := .Get "date" }} {{ $audience := .Get "audience" }} {{ $tag := .Get "tag" }} {{ $tagtype := .Get "tagtype" | default "default" }} {{ $icon := .Get "icon" }} {{ $iconsize := .Get "iconsize" | default "24px" }} <div class="info-card"> <a href="{{ $link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <div class="info-card-left"> {{ if $icon }} <span class="info-card-title-icon"> {{/* Используем ваш существующий shortcode icon */}} {{ if .Site.Data.icons }} {{ $iconData := index .Site.Data.icons $icon }} {{ if $iconData }} {{ $iconSvg := replaceRE "<svg" (printf "<svg width='%s' height='%s'" $iconsize $iconsize) $iconData }} <span class="custom-icon">{{ $iconSvg | safeHTML }}</span> {{ else }} {{/* Если иконка не найдена, используем placeholder */}} <svg class="custom-icon" style="width: {{ $iconsize }}; height: {{ $iconsize }};" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/> </svg> {{ end }} {{ else }} {{/* Если data.icons не существует */}} <svg class="custom-icon" style="width: {{ $iconsize }}; height: {{ $iconsize }};" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/> </svg> {{ end }} </span> {{ end }} <span class="info-card-title">{{ $title }}</span> </div> <div class="info-card-right-section"> {{ if $tag }} <span class="info-card-tag info-card-tag-{{ $tagtype }}"> {{ $tag }} </span> {{ end }} {{ if $desc }} <div class="info-card-tooltip-wrapper"> <span class="info-card-icon" title="Показать информацию"> <svg class="info-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 13A6 6 0 1 1 8 2a6 6 0 0 1 0 12z"/> <path d="M7 11h2v2H7zm0-8h2v6H7z"/> </svg> </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ $desc }}</div> {{ if or $date $audience }} <div class="tooltip-details"> {{ if $date }} <div class="tooltip-row"> <svg class="tooltip-row-icon" width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </svg> <span class="tooltip-row-text">Добавлено: {{ $date }}</span> </div> {{ end }} {{ if $audience }} <div class="tooltip-row"> <svg class="tooltip-row-icon" width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/> </svg> <span class="tooltip-row-text">Для кого: {{ $audience }}</span> </div> {{ end }} </div> {{ end }} </div> </div> {{ end }} </div> </div> </a> </div> <style> /* ===== ОСНОВНЫЕ СТИЛИ КАРТОЧЕК ===== */ .info-card { margin: 0.75rem 0; border: 1px solid #e0e0e0; border-radius: 8px; background: #ffffff; transition: all 0.2s ease; position: relative; } .info-card:hover { border-color: #4a90e2; box-shadow: 0 2px 8px rgba(74, 144, 226, 0.15); } .info-card-link { display: block; padding: 1rem 1.25rem; text-decoration: none; color: #333333; } .info-card-link:hover { text-decoration: none; } .info-card-header { display: flex; justify-content: space-between; align-items: center; min-height: 24px; } /* Левая часть с иконкой и заголовком */ .info-card-left { display: flex; align-items: center; flex: 1; padding-right: 12px; min-height: 24px; gap: 10px; } .info-card-title-icon { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; } .info-card-title-icon .custom-icon { display: inline-flex; align-items: center; justify-content: center; line-height: 0; /* Важно для SVG */ } .info-card-title-icon .custom-icon svg { width: 100%; height: 100%; fill: currentColor; color: #666666; vertical-align: middle; /* Выравнивание по вертикали */ } .info-card-title { font-size: 1rem; font-weight: 600; color: #333333; line-height: 1.4; flex: 1; } /* ===== ПРАВАЯ СЕКЦИЯ ===== */ .info-card-right-section { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } /* ===== ТЕГИ ===== */ .info-card-tag { font-size: 0.75rem; padding: 0.15rem 0.5rem; border-radius: 10px; font-weight: 500; white-space: nowrap; border: 1px solid transparent; } .info-card-tag-default { background: #f0f0f0; color: #666666; border-color: #ddd; } .info-card-tag-info { background: #e3f2fd; color: #1565c0; border-color: #90caf9; } .info-card-tag-warning { background: #fff3e0; color: #e65100; border-color: #ffcc80; } .info-card-tag-success { background: #e8f5e9; color: #2e7d32; border-color: #a5d6a7; } .info-card-tag-error { background: #ffebee; color: #c62828; border-color: #ef9a9a; } /* ===== ИКОНКА И ТУЛТИП ===== */ .info-card-tooltip-wrapper { position: relative; display: flex; align-items: center; } .info-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; cursor: help; color: #666666; border-radius: 50%; transition: all 0.15s; } .info-card-icon:hover { background: #f0f0f0; color: #4a90e2; } .info-icon { width: 16px; height: 16px; } /* ===== ВСПЛЫВАЮЩАЯ ПОДСКАЗКА ===== */ .info-card-tooltip { position: absolute; bottom: calc(100% + 10px); right: 50%; transform: translateX(50%) translateY(0); width: 350px; max-width: 90vw; padding: 16px; background: white; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); border: 1px solid #e0e0e0; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); pointer-events: none; } /* Показываем тултип при наведении на обертку */ .info-card-tooltip-wrapper:hover .info-card-tooltip { opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(50%) translateY(-5px); } /* Стрелка тултипа */ .info-card-tooltip::before { content: ''; position: absolute; bottom: -6px; left: 50%; transform: translateX(-50%) rotate(45deg); width: 12px; height: 12px; background: white; border-right: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0; z-index: -1; } .tooltip-description { font-size: 0.9rem; line-height: 1.5; color: #444444; margin-bottom: 12px; max-height: 200px; overflow-y: auto; padding-right: 4px; } /* Стили для скроллбара в описании */ .tooltip-description::-webkit-scrollbar { width: 4px; } .tooltip-description::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 2px; } .tooltip-description::-webkit-scrollbar-thumb { background: #c1c1c1; border-radius: 2px; } .tooltip-details { font-size: 0.82rem; color: #666666; border-top: 1px solid #f0f0f0; padding-top: 10px; } /* ИСПРАВЛЕНИЕ: ВЕРТИКАЛЬНОЕ ВЫРАВНИВАНИЕ ИКОНОК И ТЕКСТА В ТУЛТИПЕ */ .tooltip-row { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 6px; line-height: 1.4; } .tooltip-row:last-child { margin-bottom: 0; } .tooltip-row-icon { flex-shrink: 0; margin-top: 2px; /* Исправлено: точное выравнивание */ opacity: 0.7; } .tooltip-row-text { line-height: 1.4; flex: 1; padding-top: 1px; /* Компенсируем выравнивание */ } /* ===== ТЕМНАЯ ТЕМА ===== */ body.dark .info-card, html.dark .info-card { background: #2d3748; border-color: #4a5568; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } body.dark .info-card:hover, html.dark .info-card:hover { border-color: #63b3ed; box-shadow: 0 2px 8px rgba(99, 179, 237, 0.2); } body.dark .info-card-link, html.dark .info-card-link { color: #e2e8f0; } body.dark .info-card-title, html.dark .info-card-title { color: #f7fafc; } body.dark .info-card-title-icon .custom-icon svg { color: #a0aec0; } body.dark .info-card-icon, html.dark .info-card-icon { color: #a0aec0; } body.dark .info-card-icon:hover, html.dark .info-card-icon:hover { background: #4a5568; color: #63b3ed; } body.dark .info-card-tooltip, html.dark .info-card-tooltip { background: #1a202c; border-color: #4a5568; box-shadow: 0 4px 20px rgba(0,0,0,0.4); } body.dark .info-card-tooltip::before, html.dark .info-card-tooltip::before { background: #1a202c; border-color: #4a5568; } body.dark .tooltip-description, html.dark .tooltip-description { color: #e2e8f0; } body.dark .tooltip-description::-webkit-scrollbar-track { background: #2d3748; } body.dark .tooltip-description::-webkit-scrollbar-thumb { background: #4a5568; } body.dark .tooltip-details, html.dark .tooltip-details { color: #a0aec0; border-top-color: #4a5568; } body.dark .info-card-tag-default, html.dark .info-card-tag-default { background: #4a5568; color: #cbd5e0; border-color: #718096; } body.dark .info-card-tag-info, html.dark .info-card-tag-info { background: #2c5282; color: #bee3f8; border-color: #3182ce; } body.dark .info-card-tag-warning, html.dark .info-card-tag-warning { background: #975a16; color: #feebc8; border-color: #d69e2e; } body.dark .info-card-tag-success, html.dark .info-card-tag-success { background: #276749; color: #c6f6d5; border-color: #38a169; } body.dark .info-card-tag-error, html.dark .info-card-tag-error { background: #9b2c2c; color: #fed7d7; border-color: #e53e3e; } /* ===== АДАПТИВНОСТЬ ===== */ @media (max-width: 768px) { .info-card-header { flex-direction: column; align-items: flex-start; gap: 8px; } .info-card-left { width: 100%; padding-right: 0; } .info-card-right-section { width: 100%; justify-content: space-between; } .info-card-tooltip { position: fixed; bottom: auto; top: 50%; left: 50%; right: auto; transform: translate(-50%, -50%) !important; width: calc(100vw - 40px); max-width: 500px; max-height: 70vh; overflow-y: auto; } .info-card-tooltip::before { display: none; } .info-card { margin: 0.5rem 0; } .info-card-link { padding: 0.75rem 1rem; } .tooltip-description { max-height: 40vh; } .tooltip-row { align-items: flex-start; } .tooltip-row-icon { margin-top: 2px; } .tooltip-row-text { padding-top: 2px; } } /* Для очень узких экранов */ @media (max-width: 480px) { .info-card-tooltip { width: calc(100vw - 20px); padding: 12px; } .tooltip-description { font-size: 0.85rem; } .tooltip-details { font-size: 0.8rem; } .info-card-left { gap: 8px; } } </style> <script> (function() { document.addEventListener('DOMContentLoaded', function() { initCardInfoTooltips(); }); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initCardInfoTooltips); } else { initCardInfoTooltips(); } function initCardInfoTooltips() { const tooltipWrappers = document.querySelectorAll('.info-card-tooltip-wrapper'); tooltipWrappers.forEach(wrapper => { if (wrapper.dataset.initialized === 'true') return; const tooltip = wrapper.querySelector('.info-card-tooltip'); const icon = wrapper.querySelector('.info-card-icon'); if (!tooltip || !icon) return; wrapper.dataset.initialized = 'true'; wrapper.addEventListener('mouseenter', function() { positionTooltip(wrapper, tooltip); tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; tooltip.style.pointerEvents = 'auto'; }); wrapper.addEventListener('mouseleave', function() { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; tooltip.style.pointerEvents = 'none'; }); wrapper.addEventListener('click', function(e) { if (window.innerWidth <= 768) { e.preventDefault(); e.stopPropagation(); positionTooltip(wrapper, tooltip); if (tooltip.style.opacity === '1') { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; } else { tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; } } }); }); document.addEventListener('click', function(e) { if (!e.target.closest('.info-card-tooltip-wrapper')) { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); } function positionTooltip(wrapper, tooltip) { if (window.innerWidth <= 768) { tooltip.style.position = 'fixed'; tooltip.style.top = '50%'; tooltip.style.left = '50%'; tooltip.style.right = 'auto'; tooltip.style.bottom = 'auto'; tooltip.style.transform = 'translate(-50%, -50%)'; return; } const wrapperRect = wrapper.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); const viewportWidth = window.innerWidth; const centerX = wrapperRect.left + (wrapperRect.width / 2); let left = centerX - (tooltipRect.width / 2); if (left < 10) { left = 10; } else if (left + tooltipRect.width > viewportWidth - 10) { left = viewportWidth - tooltipRect.width - 10; } const top = wrapperRect.top - tooltipRect.height - 10; if (top < 10) { tooltip.style.top = (wrapperRect.bottom + 10) + 'px'; tooltip.style.bottom = 'auto'; } else { tooltip.style.top = top + 'px'; tooltip.style.bottom = 'auto'; } tooltip.style.left = left + 'px'; tooltip.style.right = 'auto'; tooltip.style.transform = 'none'; tooltip.style.position = 'fixed'; } window.addEventListener('resize', function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }); let lastDarkMode = document.body.classList.contains('dark'); function checkThemeChange() { const currentDarkMode = document.body.classList.contains('dark'); if (currentDarkMode !== lastDarkMode) { lastDarkMode = currentDarkMode; setTimeout(function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }, 50); } } const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.attributeName === 'class') { checkThemeChange(); } }); }); observer.observe(document.body, { attributes: true }); observer.observe(document.documentElement, { attributes: true }); setInterval(checkThemeChange, 1000); })(); </script> ``` Пример использования: ```markdown {{< cardinfo link="http://AssayMovement" title="Движение проб" desc="Отслеживание прохождения проб от отбора до получения результатов" date="15.10.2023" audience="Геологи" tag="Лаборатория" tagtype="info" icon="database" <!-- Название иконки из site.Data.icons --> iconsize="24px" >}} {{< cardinfo link="http://AssayMovement1" title="Отчеты по геологии" desc="Сводные отчеты по геологическим работам" icon="chart" iconsize="20px" >}} <!-- Можно указать любой размер --> ``` Ключевые исправления: 1. Исправлено выравнивание иконок в тултипе - добавлен padding-top: 1px для текста 2. Исправлена работа с вашей системой иконок - теперь берет из site.Data.icons 3. Исправлены размеры - теперь использует CSS строки (например, "24px", "2em") 4. Добавлена проверка существования иконки в site.Data.icons 5. Улучшено вертикальное выравнивание SVG иконок Теперь должно работать правильно с вашей системой иконок! |
Понедельник, 2026-01-12, 15:26
# 14
{{/* layouts/shortcodes/cardinfo.html */}}
{{ $link := .Get "link" }} {{ $title := .Get "title" }} {{ $desc := .Get "desc" | default "" }} {{ $date := .Get "date" }} {{ $audience := .Get "audience" }} {{ $tag := .Get "tag" }} {{ $tagtype := .Get "tagtype" | default "default" }} {{ $icon := .Get "icon" }} {{ $iconsize := .Get "iconsize" | default "24px" }} <div class="info-card"> <a href="{{ $link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <div class="info-card-left"> {{ if $icon }} <span class="info-card-title-icon"> {{/* Используем ваш существующий shortcode icon */}} {{ if .Site.Data.icons }} {{ $iconData := index .Site.Data.icons $icon }} {{ if $iconData }} {{ $iconSvg := replaceRE "<svg" (printf "<svg width='%s' height='%s'" $iconsize $iconsize) $iconData }} <span class="custom-icon">{{ $iconSvg | safeHTML }}</span> {{ else }} {{/* Если иконка не найдена, используем placeholder */}} <svg class="custom-icon" style="width: {{ $iconsize }}; height: {{ $iconsize }};" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/> </svg> {{ end }} {{ else }} {{/* Если data.icons не существует */}} <svg class="custom-icon" style="width: {{ $iconsize }}; height: {{ $iconsize }};" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/> </svg> {{ end }} </span> {{ end }} <span class="info-card-title">{{ $title }}</span> </div> <div class="info-card-right-section"> {{ if $tag }} <span class="info-card-tag info-card-tag-{{ $tagtype }}"> {{ $tag }} </span> {{ end }} {{ if $desc }} <div class="info-card-tooltip-wrapper"> <span class="info-card-icon" title="Показать информацию"> <svg class="info-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 13A6 6 0 1 1 8 2a6 6 0 0 1 0 12z"/> <path d="M7 11h2v2H7zm0-8h2v6H7z"/> </svg> </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ $desc | safeHTML }}</div> <!-- Добавлен safeHTML --> {{ if or $date $audience }} <div class="tooltip-details"> {{ if $date }} <div class="tooltip-row"> <svg class="tooltip-row-icon" width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </svg> <span class="tooltip-row-text">Добавлено: {{ $date }}</span> </div> {{ end }} {{ if $audience }} <div class="tooltip-row"> <svg class="tooltip-row-icon" width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/> </svg> <span class="tooltip-row-text">Для кого: {{ $audience }}</span> </div> {{ end }} </div> {{ end }} </div> </div> {{ end }} </div> </div> </a> </div> <style> /* ===== ОСНОВНЫЕ СТИЛИ КАРТОЧЕК ===== */ .info-card { margin: 0.75rem 0; border: 1px solid #e0e0e0; border-radius: 8px; background: #ffffff; transition: all 0.2s ease; position: relative; } .info-card:hover { border-color: #4a90e2; box-shadow: 0 2px 8px rgba(74, 144, 226, 0.15); } .info-card-link { display: block; padding: 1rem 1.25rem; text-decoration: none; color: #333333; } .info-card-link:hover { text-decoration: none; } .info-card-header { display: flex; justify-content: space-between; align-items: center; min-height: 24px; } /* Левая часть с иконкой и заголовком */ .info-card-left { display: flex; align-items: center; flex: 1; padding-right: 12px; min-height: 24px; gap: 10px; } .info-card-title-icon { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; } .info-card-title-icon .custom-icon { display: inline-flex; align-items: center; justify-content: center; line-height: 0; /* Важно для SVG */ } .info-card-title-icon .custom-icon svg { width: 100%; height: 100%; fill: currentColor; color: #666666; vertical-align: middle; /* Выравнивание по вертикали */ } .info-card-title { font-size: 1rem; font-weight: 600; color: #333333; line-height: 1.4; flex: 1; } /* ===== ПРАВАЯ СЕКЦИЯ ===== */ .info-card-right-section { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } /* ===== ТЕГИ ===== */ .info-card-tag { font-size: 0.75rem; padding: 0.15rem 0.5rem; border-radius: 10px; font-weight: 500; white-space: nowrap; border: 1px solid transparent; } .info-card-tag-default { background: #f0f0f0; color: #666666; border-color: #ddd; } .info-card-tag-info { background: #e3f2fd; color: #1565c0; border-color: #90caf9; } .info-card-tag-warning { background: #fff3e0; color: #e65100; border-color: #ffcc80; } .info-card-tag-success { background: #e8f5e9; color: #2e7d32; border-color: #a5d6a7; } .info-card-tag-error { background: #ffebee; color: #c62828; border-color: #ef9a9a; } /* ===== ИКОНКА И ТУЛТИП ===== */ .info-card-tooltip-wrapper { position: relative; display: flex; align-items: center; } .info-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; cursor: help; color: #666666; border-radius: 50%; transition: all 0.15s; } .info-card-icon:hover { background: #f0f0f0; color: #4a90e2; } .info-icon { width: 16px; height: 16px; } /* ===== ВСПЛЫВАЮЩАЯ ПОДСКАЗКА ===== */ .info-card-tooltip { position: absolute; bottom: calc(100% + 10px); right: 50%; transform: translateX(50%) translateY(0); width: 350px; max-width: 90vw; padding: 16px; background: white; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); border: 1px solid #e0e0e0; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); pointer-events: none; } /* Показываем тултип при наведении на обертку */ .info-card-tooltip-wrapper:hover .info-card-tooltip { opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(50%) translateY(-5px); } /* Стрелка тултипа */ .info-card-tooltip::before { content: ''; position: absolute; bottom: -6px; left: 50%; transform: translateX(-50%) rotate(45deg); width: 12px; height: 12px; background: white; border-right: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0; z-index: -1; } /* СТИЛИ ДЛЯ HTML В ОПИСАНИИ */ .tooltip-description { font-size: 0.9rem; line-height: 1.5; color: #444444; margin-bottom: 12px; max-height: 200px; overflow-y: auto; padding-right: 4px; } /* Стили для HTML элементов внутри описания */ .tooltip-description p { margin: 0 0 8px 0; } .tooltip-description p:last-child { margin-bottom: 0; } .tooltip-description br { content: ""; display: block; margin-bottom: 4px; } .tooltip-description strong, .tooltip-description b { font-weight: 600; color: #333; } .tooltip-description em, .tooltip-description i { font-style: italic; } .tooltip-description u { text-decoration: underline; } .tooltip-description code { background: #f5f5f5; padding: 2px 4px; border-radius: 3px; font-family: monospace; font-size: 0.85em; } .tooltip-description pre { background: #f5f5f5; padding: 8px; border-radius: 4px; overflow-x: auto; margin: 8px 0; font-size: 0.85em; } .tooltip-description ul, .tooltip-description ol { margin: 8px 0; padding-left: 20px; } .tooltip-description li { margin-bottom: 4px; } .tooltip-description a { color: #4a90e2; text-decoration: none; border-bottom: 1px dotted #4a90e2; } .tooltip-description a:hover { text-decoration: none; border-bottom: 1px solid #4a90e2; } /* Стили для скроллбара в описании */ .tooltip-description::-webkit-scrollbar { width: 4px; } .tooltip-description::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 2px; } .tooltip-description::-webkit-scrollbar-thumb { background: #c1c1c1; border-radius: 2px; } .tooltip-details { font-size: 0.82rem; color: #666666; border-top: 1px solid #f0f0f0; padding-top: 10px; } /* ИСПРАВЛЕНИЕ: ВЕРТИКАЛЬНОЕ ВЫРАВНИВАНИЕ ИКОНОК И ТЕКСТА В ТУЛТИПЕ */ .tooltip-row { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 6px; line-height: 1.4; } .tooltip-row:last-child { margin-bottom: 0; } .tooltip-row-icon { flex-shrink: 0; margin-top: 2px; /* Исправлено: точное выравнивание */ opacity: 0.7; } .tooltip-row-text { line-height: 1.4; flex: 1; padding-top: 1px; /* Компенсируем выравнивание */ } /* ===== ТЕМНАЯ ТЕМА ===== */ body.dark .info-card, html.dark .info-card { background: #2d3748; border-color: #4a5568; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } body.dark .info-card:hover, html.dark .info-card:hover { border-color: #63b3ed; box-shadow: 0 2px 8px rgba(99, 179, 237, 0.2); } body.dark .info-card-link, html.dark .info-card-link { color: #e2e8f0; } body.dark .info-card-title, html.dark .info-card-title { color: #f7fafc; } body.dark .info-card-title-icon .custom-icon svg { color: #a0aec0; } body.dark .info-card-icon, html.dark .info-card-icon { color: #a0aec0; } body.dark .info-card-icon:hover, html.dark .info-card-icon:hover { background: #4a5568; color: #63b3ed; } body.dark .info-card-tooltip, html.dark .info-card-tooltip { background: #1a202c; border-color: #4a5568; box-shadow: 0 4px 20px rgba(0,0,0,0.4); } body.dark .info-card-tooltip::before, html.dark .info-card-tooltip::before { background: #1a202c; border-color: #4a5568; } /* Темная тема для HTML в описании */ body.dark .tooltip-description, html.dark .tooltip-description { color: #e2e8f0; } body.dark .tooltip-description strong, body.dark .tooltip-description b, html.dark .tooltip-description strong, html.dark .tooltip-description b { color: #f7fafc; } body.dark .tooltip-description code, html.dark .tooltip-description code { background: #2d3748; color: #e2e8f0; border: 1px solid #4a5568; } body.dark .tooltip-description pre, html.dark .tooltip-description pre { background: #2d3748; border: 1px solid #4a5568; color: #e2e8f0; } body.dark .tooltip-description a, html.dark .tooltip-description a { color: #63b3ed; border-bottom-color: #63b3ed; } body.dark .tooltip-description::-webkit-scrollbar-track { background: #2d3748; } body.dark .tooltip-description::-webkit-scrollbar-thumb { background: #4a5568; } body.dark .tooltip-details, html.dark .tooltip-details { color: #a0aec0; border-top-color: #4a5568; } body.dark .info-card-tag-default, html.dark .info-card-tag-default { background: #4a5568; color: #cbd5e0; border-color: #718096; } body.dark .info-card-tag-info, html.dark .info-card-tag-info { background: #2c5282; color: #bee3f8; border-color: #3182ce; } body.dark .info-card-tag-warning, html.dark .info-card-tag-warning { background: #975a16; color: #feebc8; border-color: #d69e2e; } body.dark .info-card-tag-success, html.dark .info-card-tag-success { background: #276749; color: #c6f6d5; border-color: #38a169; } body.dark .info-card-tag-error, html.dark .info-card-tag-error { background: #9b2c2c; color: #fed7d7; border-color: #e53e3e; } /* ===== АДАПТИВНОСТЬ ===== */ @media (max-width: 768px) { .info-card-header { flex-direction: column; align-items: flex-start; gap: 8px; } .info-card-left { width: 100%; padding-right: 0; } .info-card-right-section { width: 100%; justify-content: space-between; } .info-card-tooltip { position: fixed; bottom: auto; top: 50%; left: 50%; right: auto; transform: translate(-50%, -50%) !important; width: calc(100vw - 40px); max-width: 500px; max-height: 70vh; overflow-y: auto; } .info-card-tooltip::before { display: none; } .info-card { margin: 0.5rem 0; } .info-card-link { padding: 0.75rem 1rem; } .tooltip-description { max-height: 40vh; } .tooltip-row { align-items: flex-start; } .tooltip-row-icon { margin-top: 2px; } .tooltip-row-text { padding-top: 2px; } /* Адаптивные стили для HTML */ .tooltip-description p { margin-bottom: 6px; } .tooltip-description br { margin-bottom: 3px; } .tooltip-description ul, .tooltip-description ol { padding-left: 16px; } } /* Для очень узких экранов */ @media (max-width: 480px) { .info-card-tooltip { width: calc(100vw - 20px); padding: 12px; } .tooltip-description { font-size: 0.85rem; } .tooltip-details { font-size: 0.8rem; } .info-card-left { gap: 8px; } .tooltip-description code { font-size: 0.8em; padding: 1px 3px; } .tooltip-description pre { padding: 6px; font-size: 0.8em; } } </style> <script> (function() { document.addEventListener('DOMContentLoaded', function() { initCardInfoTooltips(); }); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initCardInfoTooltips); } else { initCardInfoTooltips(); } function initCardInfoTooltips() { const tooltipWrappers = document.querySelectorAll('.info-card-tooltip-wrapper'); tooltipWrappers.forEach(wrapper => { if (wrapper.dataset.initialized === 'true') return; const tooltip = wrapper.querySelector('.info-card-tooltip'); const icon = wrapper.querySelector('.info-card-icon'); if (!tooltip || !icon) return; wrapper.dataset.initialized = 'true'; wrapper.addEventListener('mouseenter', function() { positionTooltip(wrapper, tooltip); tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; tooltip.style.pointerEvents = 'auto'; }); wrapper.addEventListener('mouseleave', function() { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; tooltip.style.pointerEvents = 'none'; }); wrapper.addEventListener('click', function(e) { if (window.innerWidth <= 768) { e.preventDefault(); e.stopPropagation(); positionTooltip(wrapper, tooltip); if (tooltip.style.opacity === '1') { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; } else { tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; } } }); }); document.addEventListener('click', function(e) { if (!e.target.closest('.info-card-tooltip-wrapper')) { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); } function positionTooltip(wrapper, tooltip) { if (window.innerWidth <= 768) { tooltip.style.position = 'fixed'; tooltip.style.top = '50%'; tooltip.style.left = '50%'; tooltip.style.right = 'auto'; tooltip.style.bottom = 'auto'; tooltip.style.transform = 'translate(-50%, -50%)'; return; } const wrapperRect = wrapper.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); const viewportWidth = window.innerWidth; const centerX = wrapperRect.left + (wrapperRect.width / 2); let left = centerX - (tooltipRect.width / 2); if (left < 10) { left = 10; } else if (left + tooltipRect.width > viewportWidth - 10) { left = viewportWidth - tooltipRect.width - 10; } const top = wrapperRect.top - tooltipRect.height - 10; if (top < 10) { tooltip.style.top = (wrapperRect.bottom + 10) + 'px'; tooltip.style.bottom = 'auto'; } else { tooltip.style.top = top + 'px'; tooltip.style.bottom = 'auto'; } tooltip.style.left = left + 'px'; tooltip.style.right = 'auto'; tooltip.style.transform = 'none'; tooltip.style.position = 'fixed'; } window.addEventListener('resize', function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }); let lastDarkMode = document.body.classList.contains('dark'); function checkThemeChange() { const currentDarkMode = document.body.classList.contains('dark'); if (currentDarkMode !== lastDarkMode) { lastDarkMode = currentDarkMode; setTimeout(function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }, 50); } } const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.attributeName === 'class') { checkThemeChange(); } }); }); observer.observe(document.body, { attributes: true }); observer.observe(document.documentElement, { attributes: true }); setInterval(checkThemeChange, 1000); })(); </script> |
Понедельник, 2026-01-12, 15:56
# 15
{{/* layouts/shortcodes/cardinfo.html */}}
{{ $link := .Get "link" }} {{ $title := .Get "title" }} {{ $desc := .Get "desc" | default "" }} {{ $date := .Get "date" }} {{ $audience := .Get "audience" }} {{ $tag := .Get "tag" }} {{ $tagtype := .Get "tagtype" | default "default" }} {{ $icon := .Get "icon" }} {{ $iconsize := .Get "iconsize" | default "24px" }} <div class="info-card"> <a href="{{ $link }}" class="info-card-link" target="_blank"> <div class="info-card-header"> <div class="info-card-left"> {{ if $icon }} <span class="info-card-title-icon"> {{/* Используем ваш существующий shortcode icon */}} {{ if .Site.Data.icons }} {{ $iconData := index .Site.Data.icons $icon }} {{ if $iconData }} {{ $iconSvg := replaceRE "<svg" (printf "<svg width='%s' height='%s'" $iconsize $iconsize) $iconData }} <span class="custom-icon">{{ $iconSvg | safeHTML }}</span> {{ else }} {{/* Если иконка не найдена, используем placeholder */}} <svg class="custom-icon" style="width: {{ $iconsize }}; height: {{ $iconsize }};" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/> </svg> {{ end }} {{ else }} {{/* Если data.icons не существует */}} <svg class="custom-icon" style="width: {{ $iconsize }}; height: {{ $iconsize }};" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/> </svg> {{ end }} </span> {{ end }} <span class="info-card-title">{{ $title }}</span> </div> <div class="info-card-right-section"> {{ if $tag }} <span class="info-card-tag info-card-tag-{{ $tagtype }}"> {{ $tag }} </span> {{ end }} {{ if $desc }} <div class="info-card-tooltip-wrapper"> <span class="info-card-icon" title="Показать информацию"> <svg class="info-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"> <path d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm0 13A6 6 0 1 1 8 2a6 6 0 0 1 0 12z"/> <path d="M7 11h2v2H7zm0-8h2v6H7z"/> </svg> </span> <div class="info-card-tooltip"> <div class="tooltip-description">{{ $desc | safeHTML }}</div> {{ if or $date $audience }} <div class="tooltip-details"> {{ if $date }} <div class="tooltip-row"> <svg class="tooltip-row-icon" width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/> </svg> <span class="tooltip-row-text">Добавлено: {{ $date }}</span> </div> {{ end }} {{ if $audience }} <div class="tooltip-row"> <svg class="tooltip-row-icon" width="14" height="14" viewBox="0 0 24 24" fill="currentColor"> <path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/> </svg> <span class="tooltip-row-text">Для кого: {{ $audience }}</span> </div> {{ end }} </div> {{ end }} </div> </div> {{ end }} </div> </div> </a> </div> <style> /* ===== ОСНОВНЫЕ СТИЛИ КАРТОЧЕК ===== */ .info-card { margin: 0.75rem 0; border: 1px solid #e0e0e0; border-radius: 8px; background: #ffffff; transition: all 0.2s ease; position: relative; } .info-card:hover { border-color: #4a90e2; box-shadow: 0 2px 8px rgba(74, 144, 226, 0.15); } .info-card-link { display: block; padding: 1rem 1.25rem; text-decoration: none; color: #333333; } .info-card-link:hover { text-decoration: none; } .info-card-header { display: flex; justify-content: space-between; align-items: center; min-height: 24px; } /* Левая часть с иконкой и заголовком */ .info-card-left { display: flex; align-items: center; flex: 1; padding-right: 12px; min-height: 24px; gap: 10px; } .info-card-title-icon { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; } .info-card-title-icon .custom-icon { display: inline-flex; align-items: center; justify-content: center; line-height: 0; /* Важно для SVG */ } .info-card-title-icon .custom-icon svg { width: 100%; height: 100%; fill: currentColor; color: #666666; vertical-align: middle; /* Выравнивание по вертикали */ } .info-card-title { font-size: 1rem; font-weight: 600; color: #333333; line-height: 1.4; flex: 1; } /* ===== ПРАВАЯ СЕКЦИЯ ===== */ .info-card-right-section { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } /* ===== ТЕГИ ===== */ .info-card-tag { font-size: 0.75rem; padding: 0.15rem 0.5rem; border-radius: 10px; font-weight: 500; white-space: nowrap; border: 1px solid transparent; } .info-card-tag-default { background: #f0f0f0; color: #666666; border-color: #ddd; } .info-card-tag-info { background: #e3f2fd; color: #1565c0; border-color: #90caf9; } .info-card-tag-warning { background: #fff3e0; color: #e65100; border-color: #ffcc80; } .info-card-tag-success { background: #e8f5e9; color: #2e7d32; border-color: #a5d6a7; } .info-card-tag-error { background: #ffebee; color: #c62828; border-color: #ef9a9a; } /* ===== ИКОНКА И ТУЛТИП ===== */ .info-card-tooltip-wrapper { position: relative; display: flex; align-items: center; } .info-card-icon { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; cursor: help; color: #666666; border-radius: 50%; transition: all 0.15s; } .info-card-icon:hover { background: #f0f0f0; color: #4a90e2; } .info-icon { width: 16px; height: 16px; } /* ===== ВСПЛЫВАЮЩАЯ ПОДСКАЗКА (УВЕЛИЧЕННАЯ ШИРИНА) ===== */ .info-card-tooltip { position: absolute; bottom: calc(100% + 10px); right: 50%; transform: translateX(50%) translateY(0); width: 420px; /* Увеличенная ширина: было 350px, стало 420px */ max-width: 90vw; padding: 18px; /* Немного больше padding */ background: white; border-radius: 8px; box-shadow: 0 5px 25px rgba(0,0,0,0.15); /* Усиленная тень */ border: 1px solid #e0e0e0; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); /* Немного медленнее для плавности */ pointer-events: none; } /* Показываем тултип при наведении на обертку */ .info-card-tooltip-wrapper:hover .info-card-tooltip { opacity: 1; visibility: visible; pointer-events: auto; transform: translateX(50%) translateY(-8px); /* Больше смещение для эффекта */ } /* Стрелка тултипа */ .info-card-tooltip::before { content: ''; position: absolute; bottom: -7px; /* Немного больше для более широкого тултипа */ left: 50%; transform: translateX(-50%) rotate(45deg); width: 14px; /* Немного больше стрелка */ height: 14px; background: white; border-right: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0; z-index: -1; } /* СТИЛИ ДЛЯ HTML В ОПИСАНИИ */ .tooltip-description { font-size: 0.92rem; /* Немного больше текст */ line-height: 1.6; /* Больше межстрочный интервал */ color: #444444; margin-bottom: 14px; /* Больше отступ */ max-height: 250px; /* Увеличенная максимальная высота */ overflow-y: auto; padding-right: 6px; /* Больше padding для скроллбара */ } /* Улучшенные стили для скроллбара */ .tooltip-description::-webkit-scrollbar { width: 6px; /* Шире скроллбар */ } .tooltip-description::-webkit-scrollbar-track { background: #f5f5f5; border-radius: 3px; } .tooltip-description::-webkit-scrollbar-thumb { background: #b0b0b0; border-radius: 3px; transition: background 0.2s; } .tooltip-description::-webkit-scrollbar-thumb:hover { background: #909090; } /* Стили для HTML элементов внутри описания */ .tooltip-description p { margin: 0 0 10px 0; /* Больше отступ между параграфами */ } .tooltip-description p:last-child { margin-bottom: 0; } .tooltip-description br { content: ""; display: block; margin-bottom: 6px; /* Больше отступ после переноса строки */ } .tooltip-description strong, .tooltip-description b { font-weight: 700; /* Более жирный текст */ color: #333; } .tooltip-description em, .tooltip-description i { font-style: italic; } .tooltip-description u { text-decoration: underline; } .tooltip-description code { background: #f7f7f7; padding: 3px 6px; /* Больше padding для кода */ border-radius: 4px; font-family: 'Consolas', 'Monaco', monospace; font-size: 0.88em; border: 1px solid #e0e0e0; } .tooltip-description pre { background: #f7f7f7; padding: 12px; /* Больше padding для pre */ border-radius: 6px; overflow-x: auto; margin: 10px 0; /* Больше отступ */ font-size: 0.88em; border: 1px solid #e0e0e0; line-height: 1.5; } .tooltip-description ul, .tooltip-description ol { margin: 10px 0; /* Больше отступ для списков */ padding-left: 24px; /* Больше отступ слева */ } .tooltip-description li { margin-bottom: 6px; /* Больше отступ между элементами списка */ line-height: 1.5; } .tooltip-description a { color: #4a90e2; text-decoration: none; border-bottom: 1px dotted #4a90e2; transition: all 0.2s; } .tooltip-description a:hover { text-decoration: none; border-bottom: 1px solid #4a90e2; color: #357abd; } /* Заголовки в описании */ .tooltip-description h1, .tooltip-description h2, .tooltip-description h3, .tooltip-description h4 { margin: 15px 0 10px 0; color: #333; font-weight: 600; line-height: 1.3; } .tooltip-description h1 { font-size: 1.3em; } .tooltip-description h2 { font-size: 1.2em; } .tooltip-description h3 { font-size: 1.1em; } .tooltip-description h4 { font-size: 1em; } .tooltip-details { font-size: 0.85rem; /* Немного больше текст в деталях */ color: #666666; border-top: 1px solid #f0f0f0; padding-top: 12px; /* Больше отступ сверху */ } /* ИСПРАВЛЕНИЕ: ВЕРТИКАЛЬНОЕ ВЫРАВНИВАНИЕ ИКОНОК И ТЕКСТА В ТУЛТИПЕ */ .tooltip-row { display: flex; align-items: flex-start; gap: 10px; /* Больше расстояние между иконкой и текстом */ margin-bottom: 8px; /* Больше отступ между строками */ line-height: 1.5; } .tooltip-row:last-child { margin-bottom: 0; } .tooltip-row-icon { flex-shrink: 0; margin-top: 3px; /* Лучшее выравнивание для увеличенного текста */ opacity: 0.8; /* Немного больше прозрачности */ } .tooltip-row-text { line-height: 1.5; flex: 1; padding-top: 2px; /* Компенсируем выравнивание */ } /* ===== ТЕМНАЯ ТЕМА ===== */ body.dark .info-card, html.dark .info-card { background: #2d3748; border-color: #4a5568; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } body.dark .info-card:hover, html.dark .info-card:hover { border-color: #63b3ed; box-shadow: 0 2px 8px rgba(99, 179, 237, 0.2); } body.dark .info-card-link, html.dark .info-card-link { color: #e2e8f0; } body.dark .info-card-title, html.dark .info-card-title { color: #f7fafc; } body.dark .info-card-title-icon .custom-icon svg { color: #a0aec0; } body.dark .info-card-icon, html.dark .info-card-icon { color: #a0aec0; } body.dark .info-card-icon:hover, html.dark .info-card-icon:hover { background: #4a5568; color: #63b3ed; } body.dark .info-card-tooltip, html.dark .info-card-tooltip { background: #1a202c; border-color: #4a5568; box-shadow: 0 5px 25px rgba(0,0,0,0.5); /* Усиленная тень в темной теме */ } body.dark .info-card-tooltip::before, html.dark .info-card-tooltip::before { background: #1a202c; border-color: #4a5568; } /* Темная тема для HTML в описании */ body.dark .tooltip-description, html.dark .tooltip-description { color: #e2e8f0; } body.dark .tooltip-description strong, body.dark .tooltip-description b, html.dark .tooltip-description strong, html.dark .tooltip-description b { color: #f7fafc; } body.dark .tooltip-description code, html.dark .tooltip-description code { background: #2d3748; color: #e2e8f0; border: 1px solid #4a5568; } body.dark .tooltip-description pre, html.dark .tooltip-description pre { background: #2d3748; border: 1px solid #4a5568; color: #e2e8f0; } body.dark .tooltip-description a, html.dark .tooltip-description a { color: #63b3ed; border-bottom-color: #63b3ed; } body.dark .tooltip-description a:hover { color: #90cdf4; border-bottom-color: #90cdf4; } body.dark .tooltip-description h1, body.dark .tooltip-description h2, body.dark .tooltip-description h3, body.dark .tooltip-description h4, html.dark .tooltip-description h1, html.dark .tooltip-description h2, html.dark .tooltip-description h3, html.dark .tooltip-description h4 { color: #f7fafc; } body.dark .tooltip-description::-webkit-scrollbar-track { background: #2d3748; } body.dark .tooltip-description::-webkit-scrollbar-thumb { background: #4a5568; } body.dark .tooltip-description::-webkit-scrollbar-thumb:hover { background: #5a6576; } body.dark .tooltip-details, html.dark .tooltip-details { color: #a0aec0; border-top-color: #4a5568; } body.dark .info-card-tag-default, html.dark .info-card-tag-default { background: #4a5568; color: #cbd5e0; border-color: #718096; } body.dark .info-card-tag-info, html.dark .info-card-tag-info { background: #2c5282; color: #bee3f8; border-color: #3182ce; } body.dark .info-card-tag-warning, html.dark .info-card-tag-warning { background: #975a16; color: #feebc8; border-color: #d69e2e; } body.dark .info-card-tag-success, html.dark .info-card-tag-success { background: #276749; color: #c6f6d5; border-color: #38a169; } body.dark .info-card-tag-error, html.dark .info-card-tag-error { background: #9b2c2c; color: #fed7d7; border-color: #e53e3e; } /* ===== АДАПТИВНОСТЬ ===== */ @media (max-width: 768px) { .info-card-header { flex-direction: column; align-items: flex-start; gap: 8px; } .info-card-left { width: 100%; padding-right: 0; } .info-card-right-section { width: 100%; justify-content: space-between; } .info-card-tooltip { position: fixed; bottom: auto; top: 50%; left: 50%; right: auto; transform: translate(-50%, -50%) !important; width: calc(100vw - 40px); max-width: 500px; max-height: 70vh; overflow-y: auto; } .info-card-tooltip::before { display: none; } .info-card { margin: 0.5rem 0; } .info-card-link { padding: 0.75rem 1rem; } .tooltip-description { max-height: 40vh; font-size: 0.9rem; } .tooltip-row { align-items: flex-start; } .tooltip-row-icon { margin-top: 2px; } .tooltip-row-text { padding-top: 2px; } /* Адаптивные стили для HTML */ .tooltip-description p { margin-bottom: 8px; } .tooltip-description br { margin-bottom: 4px; } .tooltip-description ul, .tooltip-description ol { padding-left: 20px; } .tooltip-description h1 { font-size: 1.2em; } .tooltip-description h2 { font-size: 1.1em; } .tooltip-description h3 { font-size: 1em; } .tooltip-description h4 { font-size: 0.95em; } } /* Для очень узких экранов */ @media (max-width: 480px) { .info-card-tooltip { width: calc(100vw - 20px); padding: 14px; } .tooltip-description { font-size: 0.88rem; } .tooltip-details { font-size: 0.82rem; } .info-card-left { gap: 8px; } .tooltip-description code { font-size: 0.85em; padding: 2px 4px; } .tooltip-description pre { padding: 10px; font-size: 0.85em; } } /* Для широких экранов */ @media (min-width: 1200px) { .info-card-tooltip { width: 450px; /* Еще шире на больших экранах */ } } @media (min-width: 1400px) { .info-card-tooltip { width: 480px; /* Максимальная ширина на очень широких экранах */ } } </style> <script> (function() { document.addEventListener('DOMContentLoaded', function() { initCardInfoTooltips(); }); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initCardInfoTooltips); } else { initCardInfoTooltips(); } function initCardInfoTooltips() { const tooltipWrappers = document.querySelectorAll('.info-card-tooltip-wrapper'); tooltipWrappers.forEach(wrapper => { if (wrapper.dataset.initialized === 'true') return; const tooltip = wrapper.querySelector('.info-card-tooltip'); const icon = wrapper.querySelector('.info-card-icon'); if (!tooltip || !icon) return; wrapper.dataset.initialized = 'true'; wrapper.addEventListener('mouseenter', function() { positionTooltip(wrapper, tooltip); tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; tooltip.style.pointerEvents = 'auto'; }); wrapper.addEventListener('mouseleave', function() { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; tooltip.style.pointerEvents = 'none'; }); wrapper.addEventListener('click', function(e) { if (window.innerWidth <= 768) { e.preventDefault(); e.stopPropagation(); positionTooltip(wrapper, tooltip); if (tooltip.style.opacity === '1') { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; } else { tooltip.style.opacity = '1'; tooltip.style.visibility = 'visible'; } } }); }); document.addEventListener('click', function(e) { if (!e.target.closest('.info-card-tooltip-wrapper')) { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { document.querySelectorAll('.info-card-tooltip').forEach(tooltip => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; }); } }); } function positionTooltip(wrapper, tooltip) { if (window.innerWidth <= 768) { tooltip.style.position = 'fixed'; tooltip.style.top = '50%'; tooltip.style.left = '50%'; tooltip.style.right = 'auto'; tooltip.style.bottom = 'auto'; tooltip.style.transform = 'translate(-50%, -50%)'; return; } const wrapperRect = wrapper.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect(); const viewportWidth = window.innerWidth; const centerX = wrapperRect.left + (wrapperRect.width / 2); let left = centerX - (tooltipRect.width / 2); // Минимальный отступ от краев const minMargin = 15; if (left < minMargin) { left = minMargin; } else if (left + tooltipRect.width > viewportWidth - minMargin) { left = viewportWidth - tooltipRect.width - minMargin; } const top = wrapperRect.top - tooltipRect.height - 12; // Больше отступ сверху if (top < minMargin) { tooltip.style.top = (wrapperRect.bottom + 12) + 'px'; tooltip.style.bottom = 'auto'; } else { tooltip.style.top = top + 'px'; tooltip.style.bottom = 'auto'; } tooltip.style.left = left + 'px'; tooltip.style.right = 'auto'; tooltip.style.transform = 'none'; tooltip.style.position = 'fixed'; } window.addEventListener('resize', function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }); let lastDarkMode = document.body.classList.contains('dark'); function checkThemeChange() { const currentDarkMode = document.body.classList.contains('dark'); if (currentDarkMode !== lastDarkMode) { lastDarkMode = currentDarkMode; setTimeout(function() { document.querySelectorAll('.info-card-tooltip-wrapper').forEach(wrapper => { if (wrapper.dataset.initialized === 'true') { const tooltip = wrapper.querySelector('.info-card-tooltip'); if (tooltip && tooltip.style.opacity === '1') { positionTooltip(wrapper, tooltip); } } }); }, 50); } } const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.attributeName === 'class') { checkThemeChange(); } }); }); observer.observe(document.body, { attributes: true }); observer.observe(document.documentElement, { attributes: true }); setInterval(checkThemeChange, 1000); })(); </script> |
| |||


