feat: 添加站点卡片悬停提示功能
- 为所有站点卡片添加 data-tooltip 属性,包含完整的标题和描述信息 - tooltip 显示逻辑: * 鼠标悬停在整个卡片上即可触发(触发区域大,操作自然) * 跟随鼠标移动,实时更新位置 * 智能边界检测,避免 tooltip 超出视口范围 * 鼠标移出时自动隐藏 - 解决文本截断问题,用户可通过悬停查看完整内容 实现: - 模板层:在 site-card.hbs 中为卡片添加 data-tooltip 属性 - 交互层:在 script.js 中实现 tooltip 的创建、显示、移动和隐藏逻辑 - 样式层:通过 CSS 类控制 tooltip 的可见性和位置 Issue: #31
This commit is contained in:
347
assets/style.css
347
assets/style.css
@@ -92,8 +92,10 @@ body.light-theme {
|
|||||||
|
|
||||||
/* 预加载主题 - 在JS完全加载前显示正确的主题 */
|
/* 预加载主题 - 在JS完全加载前显示正确的主题 */
|
||||||
html.theme-preload body {
|
html.theme-preload body {
|
||||||
background-color: #e0e0d8; /* 明亮主题背景色 */
|
background-color: #e0e0d8;
|
||||||
color: #333333; /* 明亮主题文本色 */
|
/* 明亮主题背景色 */
|
||||||
|
color: #333333;
|
||||||
|
/* 明亮主题文本色 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 预加载侧边栏状态 - 在JS完全加载前显示正确的侧边栏宽度 */
|
/* 预加载侧边栏状态 - 在JS完全加载前显示正确的侧边栏宽度 */
|
||||||
@@ -169,13 +171,16 @@ html.preload * {
|
|||||||
|
|
||||||
/* 通用滚动条样式 */
|
/* 通用滚动条样式 */
|
||||||
.custom-scrollbar {
|
.custom-scrollbar {
|
||||||
scrollbar-width: thin; /* Firefox */
|
scrollbar-width: thin;
|
||||||
scrollbar-color: var(--scrollbar-color) transparent; /* Firefox */
|
/* Firefox */
|
||||||
|
scrollbar-color: var(--scrollbar-color) transparent;
|
||||||
|
/* Firefox */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Webkit滚动条样式(Chrome, Safari, Edge等) */
|
/* Webkit滚动条样式(Chrome, Safari, Edge等) */
|
||||||
.custom-scrollbar::-webkit-scrollbar {
|
.custom-scrollbar::-webkit-scrollbar {
|
||||||
width: 7px; /* 统一滚动条宽度 */
|
width: 7px;
|
||||||
|
/* 统一滚动条宽度 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-scrollbar::-webkit-scrollbar-track {
|
.custom-scrollbar::-webkit-scrollbar-track {
|
||||||
@@ -183,18 +188,22 @@ html.preload * {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.custom-scrollbar::-webkit-scrollbar-thumb {
|
.custom-scrollbar::-webkit-scrollbar-thumb {
|
||||||
background-color: var(--scrollbar-color); /* 使用变量 */
|
background-color: var(--scrollbar-color);
|
||||||
|
/* 使用变量 */
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
|
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
|
||||||
background-color: var(--scrollbar-hover-color); /* 使用变量 */
|
background-color: var(--scrollbar-hover-color);
|
||||||
|
/* 使用变量 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 防止滚动条导致的布局偏移 */
|
/* 防止滚动条导致的布局偏移 */
|
||||||
html {
|
html {
|
||||||
overflow-y: hidden; /* 改为hidden,移除强制显示的滚动条 */
|
overflow-y: hidden;
|
||||||
scrollbar-width: thin; /* Firefox */
|
/* 改为hidden,移除强制显示的滚动条 */
|
||||||
|
scrollbar-width: thin;
|
||||||
|
/* Firefox */
|
||||||
/* 明确 rem 基准字号:便于用 rem 统一管理字号(1rem = 16px) */
|
/* 明确 rem 基准字号:便于用 rem 统一管理字号(1rem = 16px) */
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
@@ -216,8 +225,10 @@ body {
|
|||||||
background-color: var(--bg-color);
|
background-color: var(--bg-color);
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
min-height: var(--app-height, 100vh);
|
min-height: var(--app-height, 100vh);
|
||||||
overflow: hidden; /* 防止body滚动 */
|
overflow: hidden;
|
||||||
padding-right: 0 !important; /* 防止滚动条导致的布局偏移 */
|
/* 防止body滚动 */
|
||||||
|
padding-right: 0 !important;
|
||||||
|
/* 防止滚动条导致的布局偏移 */
|
||||||
transition: background-color 0.3s ease, color 0.3s ease;
|
transition: background-color 0.3s ease, color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +238,8 @@ body {
|
|||||||
min-height: var(--app-height, 100vh);
|
min-height: var(--app-height, 100vh);
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
overflow: hidden; /* 防止layout滚动 */
|
overflow: hidden;
|
||||||
|
/* 防止layout滚动 */
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.3s ease;
|
transition: opacity 0.3s ease;
|
||||||
}
|
}
|
||||||
@@ -291,7 +303,8 @@ body.loaded .layout {
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
z-index: 950; /* 调整遮罩层z-index,处于按钮与弹出面板之间 */
|
z-index: 950;
|
||||||
|
/* 调整遮罩层z-index,处于按钮与弹出面板之间 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay.active {
|
.overlay.active {
|
||||||
@@ -338,14 +351,17 @@ body.loaded .layout {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 3.75rem; /* 确保与展开状态高度一致 */
|
height: 3.75rem;
|
||||||
margin-bottom: 0.8rem; /* 收起态同样拉开与按钮的间距 */
|
/* 确保与展开状态高度一致 */
|
||||||
|
margin-bottom: 0.8rem;
|
||||||
|
/* 收起态同样拉开与按钮的间距 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 折叠状态下的侧边栏内容区域调整 */
|
/* 折叠状态下的侧边栏内容区域调整 */
|
||||||
.sidebar.collapsed .sidebar-content {
|
.sidebar.collapsed .sidebar-content {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
scrollbar-width: none; /* 隐藏滚动条 */
|
scrollbar-width: none;
|
||||||
|
/* 隐藏滚动条 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 调整折叠侧边栏的部分元素间距 */
|
/* 调整折叠侧边栏的部分元素间距 */
|
||||||
@@ -364,20 +380,27 @@ body.loaded .layout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sidebar.collapsed .sidebar-content::-webkit-scrollbar {
|
.sidebar.collapsed .sidebar-content::-webkit-scrollbar {
|
||||||
display: none; /* 隐藏WebKit浏览器的滚动条 */
|
display: none;
|
||||||
|
/* 隐藏WebKit浏览器的滚动条 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 侧边栏头部区域 */
|
/* 侧边栏头部区域 */
|
||||||
.sidebar .logo {
|
.sidebar .logo {
|
||||||
grid-area: header;
|
grid-area: header;
|
||||||
padding: 1.2rem 1.2rem 0.6rem; /* 调整上下padding更紧凑 */
|
padding: 1.2rem 1.2rem 0.6rem;
|
||||||
|
/* 调整上下padding更紧凑 */
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow: hidden; /* 防止内容溢出 */
|
overflow: hidden;
|
||||||
position: relative; /* 添加相对定位,作为按钮的参考 */
|
/* 防止内容溢出 */
|
||||||
height: 3.75rem; /* 固定高度 60px */
|
position: relative;
|
||||||
margin-bottom: 0.8rem; /* 与下方按钮区域拉开间距 */
|
/* 添加相对定位,作为按钮的参考 */
|
||||||
transition: padding 0.3s ease; /* 添加padding过渡,避免突变 */
|
height: 3.75rem;
|
||||||
|
/* 固定高度 60px */
|
||||||
|
margin-bottom: 0.8rem;
|
||||||
|
/* 与下方按钮区域拉开间距 */
|
||||||
|
transition: padding 0.3s ease;
|
||||||
|
/* 添加padding过渡,避免突变 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-brand {
|
.logo-brand {
|
||||||
@@ -386,7 +409,8 @@ body.loaded .layout {
|
|||||||
gap: 0.6rem;
|
gap: 0.6rem;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding-right: 2.2rem; /* 预留右侧折叠按钮空间 */
|
padding-right: 2.2rem;
|
||||||
|
/* 预留右侧折叠按钮空间 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-brand h1 {
|
.logo-brand h1 {
|
||||||
@@ -428,13 +452,18 @@ body.loaded .layout {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background 0.3s ease; /* 只过渡背景色,移除all避免位置过渡 */
|
transition: background 0.3s ease;
|
||||||
|
/* 只过渡背景色,移除all避免位置过渡 */
|
||||||
padding: 0;
|
padding: 0;
|
||||||
flex-shrink: 0; /* 防止按钮被压缩 */
|
flex-shrink: 0;
|
||||||
position: absolute; /* 在两种状态下都使用绝对定位 */
|
/* 防止按钮被压缩 */
|
||||||
right: 1.2rem; /* 展开状态下固定在右侧 */
|
position: absolute;
|
||||||
|
/* 在两种状态下都使用绝对定位 */
|
||||||
|
right: 1.2rem;
|
||||||
|
/* 展开状态下固定在右侧 */
|
||||||
top: 60%;
|
top: 60%;
|
||||||
transform: translateY(-50%); /* 垂直居中 */
|
transform: translateY(-50%);
|
||||||
|
/* 垂直居中 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-toggle .toggle-icon {
|
.sidebar-toggle .toggle-icon {
|
||||||
@@ -457,9 +486,12 @@ body.loaded .layout {
|
|||||||
|
|
||||||
/* 收起状态下按钮居中 */
|
/* 收起状态下按钮居中 */
|
||||||
.sidebar.collapsed .sidebar-toggle {
|
.sidebar.collapsed .sidebar-toggle {
|
||||||
left: 50%; /* 水平居中 */
|
left: 50%;
|
||||||
right: auto; /* 移除右侧定位 */
|
/* 水平居中 */
|
||||||
transform: translate(-50%, -50%); /* 同时水平和垂直居中 */
|
right: auto;
|
||||||
|
/* 移除右侧定位 */
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
/* 同时水平和垂直居中 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar.collapsed .sidebar-toggle:hover {
|
.sidebar.collapsed .sidebar-toggle:hover {
|
||||||
@@ -478,28 +510,35 @@ body.loaded .layout {
|
|||||||
/* 侧边栏内容区域 - 可滚动 */
|
/* 侧边栏内容区域 - 可滚动 */
|
||||||
.sidebar-content {
|
.sidebar-content {
|
||||||
grid-area: content;
|
grid-area: content;
|
||||||
min-height: 0; /* 允许在 CSS Grid 内正确收缩与滚动,避免把 footer 挤出可视区域 */
|
min-height: 0;
|
||||||
overflow-y: auto; /* 只有内容区域可滚动 */
|
/* 允许在 CSS Grid 内正确收缩与滚动,避免把 footer 挤出可视区域 */
|
||||||
|
overflow-y: auto;
|
||||||
|
/* 只有内容区域可滚动 */
|
||||||
padding: 0 1.2rem;
|
padding: 0 1.2rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.6rem; /* 从1rem减小到0.6rem */
|
gap: 0.6rem;
|
||||||
|
/* 从1rem减小到0.6rem */
|
||||||
/* 隐藏滚动条但保持滚动功能 */
|
/* 隐藏滚动条但保持滚动功能 */
|
||||||
scrollbar-width: none; /* Firefox */
|
scrollbar-width: none;
|
||||||
|
/* Firefox */
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-content::-webkit-scrollbar {
|
.sidebar-content::-webkit-scrollbar {
|
||||||
display: none; /* Webkit browsers */
|
display: none;
|
||||||
|
/* Webkit browsers */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 折叠状态下的内容区域调整 */
|
/* 折叠状态下的内容区域调整 */
|
||||||
.sidebar.collapsed .sidebar-content {
|
.sidebar.collapsed .sidebar-content {
|
||||||
padding: 0 0.5rem;
|
padding: 0 0.5rem;
|
||||||
scrollbar-width: none; /* 隐藏滚动条 */
|
scrollbar-width: none;
|
||||||
|
/* 隐藏滚动条 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar.collapsed .sidebar-content::-webkit-scrollbar {
|
.sidebar.collapsed .sidebar-content::-webkit-scrollbar {
|
||||||
display: none; /* 隐藏WebKit浏览器的滚动条 */
|
display: none;
|
||||||
|
/* 隐藏WebKit浏览器的滚动条 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 折叠状态下的Logo文本 */
|
/* 折叠状态下的Logo文本 */
|
||||||
@@ -507,22 +546,27 @@ body.loaded .layout {
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(-20px);
|
transform: translateX(-20px);
|
||||||
width: 0;
|
width: 0;
|
||||||
visibility: hidden; /* 确保完全隐藏,防止干扰布局 */
|
visibility: hidden;
|
||||||
pointer-events: none; /* 禁用交互,避免影响布局 */
|
/* 确保完全隐藏,防止干扰布局 */
|
||||||
|
pointer-events: none;
|
||||||
|
/* 禁用交互,避免影响布局 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 导航区域样式 */
|
/* 导航区域样式 */
|
||||||
.nav-section {
|
.nav-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.4rem; /* 增大按钮间距 */
|
gap: 0.4rem;
|
||||||
|
/* 增大按钮间距 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-title {
|
.section-title {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
color: var(--accent-color);
|
color: var(--accent-color);
|
||||||
padding: 0.4rem 0.5rem; /* 减小上下padding */
|
padding: 0.4rem 0.5rem;
|
||||||
margin-bottom: 0.2rem; /* 增大与下方按钮组的间距 */
|
/* 减小上下padding */
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
|
/* 增大与下方按钮组的间距 */
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
@@ -539,7 +583,8 @@ body.loaded .layout {
|
|||||||
/* 统一与展开态的垂直间距 */
|
/* 统一与展开态的垂直间距 */
|
||||||
padding: 0.4rem 0;
|
padding: 0.4rem 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 0.2rem; /* 与展开态保持一致且更大 */
|
margin-bottom: 0.2rem;
|
||||||
|
/* 与展开态保持一致且更大 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar.collapsed .section-title i {
|
.sidebar.collapsed .section-title i {
|
||||||
@@ -556,12 +601,15 @@ body.loaded .layout {
|
|||||||
.sidebar.collapsed .nav-item {
|
.sidebar.collapsed .nav-item {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 2.75rem; /* 增大按钮方块尺寸 44px */
|
width: 2.75rem;
|
||||||
height: 2.75rem; /* 增大按钮方块尺寸 44px */
|
/* 增大按钮方块尺寸 44px */
|
||||||
|
height: 2.75rem;
|
||||||
|
/* 增大按钮方块尺寸 44px */
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
border-radius: var(--radius-md); /* 略增圆角 */
|
border-radius: var(--radius-md);
|
||||||
|
/* 略增圆角 */
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -589,7 +637,8 @@ body.loaded .layout {
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(-10px);
|
transform: translateX(-10px);
|
||||||
width: 0;
|
width: 0;
|
||||||
display: none; /* 完全移除,防止干扰布局 */
|
display: none;
|
||||||
|
/* 完全移除,防止干扰布局 */
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,19 +711,23 @@ body.loaded .layout {
|
|||||||
padding: 2rem 1.5rem;
|
padding: 2rem 1.5rem;
|
||||||
background-color: var(--bg-color);
|
background-color: var(--bg-color);
|
||||||
position: relative;
|
position: relative;
|
||||||
height: var(--app-height, 100vh); /* 固定高度(移动端避免 100vh 问题) */
|
height: var(--app-height, 100vh);
|
||||||
overflow-y: auto; /* 使用auto替代scroll,只在需要时显示滚动条 */
|
/* 固定高度(移动端避免 100vh 问题) */
|
||||||
|
overflow-y: auto;
|
||||||
|
/* 使用auto替代scroll,只在需要时显示滚动条 */
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
width: calc(100vw - var(--sidebar-width));
|
width: calc(100vw - var(--sidebar-width));
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
/* 隐藏滚动条但保持滚动功能 */
|
/* 隐藏滚动条但保持滚动功能 */
|
||||||
scrollbar-width: none; /* Firefox */
|
scrollbar-width: none;
|
||||||
|
/* Firefox */
|
||||||
}
|
}
|
||||||
|
|
||||||
.content::-webkit-scrollbar {
|
.content::-webkit-scrollbar {
|
||||||
display: none; /* Webkit browsers */
|
display: none;
|
||||||
|
/* Webkit browsers */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 优化内容区域在侧边栏折叠状态下的边距 */
|
/* 优化内容区域在侧边栏折叠状态下的边距 */
|
||||||
@@ -1097,12 +1150,11 @@ body .content.expanded {
|
|||||||
|
|
||||||
@keyframes glow {
|
@keyframes glow {
|
||||||
from {
|
from {
|
||||||
filter: drop-shadow(0 0 2px rgba(118, 148, 185, 0.2))
|
filter: drop-shadow(0 0 2px rgba(118, 148, 185, 0.2)) drop-shadow(0 0 4px rgba(168, 85, 247, 0.2));
|
||||||
drop-shadow(0 0 4px rgba(168, 85, 247, 0.2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
filter: drop-shadow(0 0 4px rgba(118, 148, 185, 0.4))
|
filter: drop-shadow(0 0 4px rgba(118, 148, 185, 0.4)) drop-shadow(0 0 8px rgba(168, 85, 247, 0.4));
|
||||||
drop-shadow(0 0 8px rgba(168, 85, 247, 0.4));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1131,8 +1183,8 @@ body .content.expanded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 标题前图标固定宽度:避免不同图标宽度导致标题文本不对齐 */
|
/* 标题前图标固定宽度:避免不同图标宽度导致标题文本不对齐 */
|
||||||
.category-header [data-editable="category-name"] > i,
|
.category-header [data-editable="category-name"]>i,
|
||||||
.group-header [data-editable="group-name"] > i {
|
.group-header [data-editable="group-name"]>i {
|
||||||
width: 1.25em;
|
width: 1.25em;
|
||||||
min-width: 1.25em;
|
min-width: 1.25em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -1181,13 +1233,13 @@ body .content.expanded {
|
|||||||
transition: color 0.3s ease;
|
transition: color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category h2 > i {
|
.category h2>i {
|
||||||
color: var(--accent-color);
|
color: var(--accent-color);
|
||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-header[data-toggle="category"]:hover h2 > i {
|
.category-header[data-toggle="category"]:hover h2>i {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
color: var(--accent-hover);
|
color: var(--accent-hover);
|
||||||
}
|
}
|
||||||
@@ -1233,14 +1285,15 @@ body .content.expanded {
|
|||||||
gap: 0.8rem;
|
gap: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-level-2 .category-header h3 > i {
|
.category-level-2 .category-header h3>i {
|
||||||
color: var(--accent-color);
|
color: var(--accent-color);
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 层级3: 分组 */
|
/* 层级3: 分组 */
|
||||||
.group-level-3, .category-level-3 {
|
.group-level-3,
|
||||||
|
.category-level-3 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
padding-left: 0.5rem;
|
padding-left: 0.5rem;
|
||||||
@@ -1271,24 +1324,25 @@ body .content.expanded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 层级4: 子分组 */
|
/* 层级4: 子分组 */
|
||||||
.group-level-4, .category-level-4 {
|
.group-level-4,
|
||||||
|
.category-level-4 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
padding-left: 0.5rem;
|
padding-left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 嵌套层级间距:仅在同级相邻时增加间距,避免首项被额外下推 */
|
/* 嵌套层级间距:仅在同级相邻时增加间距,避免首项被额外下推 */
|
||||||
.subcategories-container > .category-level-2 + .category-level-2 {
|
.subcategories-container>.category-level-2+.category-level-2 {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.groups-container > .group-level-3 + .group-level-3,
|
.groups-container>.group-level-3+.group-level-3,
|
||||||
.groups-container > .category-level-3 + .category-level-3 {
|
.groups-container>.category-level-3+.category-level-3 {
|
||||||
margin-top: 0.8rem;
|
margin-top: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subgroups-container > .group-level-4 + .group-level-4,
|
.subgroups-container>.group-level-4+.group-level-4,
|
||||||
.subcategories-container > .category-level-4 + .category-level-4 {
|
.subcategories-container>.category-level-4+.category-level-4 {
|
||||||
margin-top: 0.6rem;
|
margin-top: 0.6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1317,7 +1371,7 @@ body .content.expanded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 移除悬停时的缩放效果,保持简洁 */
|
/* 移除悬停时的缩放效果,保持简洁 */
|
||||||
.category-level-2 .category-header:hover h3 > i,
|
.category-level-2 .category-header:hover h3>i,
|
||||||
.group-level-3 .group-header:hover h4 i,
|
.group-level-3 .group-header:hover h4 i,
|
||||||
.category-level-3 .category-header:hover h4 i,
|
.category-level-3 .category-header:hover h4 i,
|
||||||
.group-level-4 .group-header:hover h5 i,
|
.group-level-4 .group-header:hover h5 i,
|
||||||
@@ -1345,8 +1399,8 @@ body .content.expanded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 展开态:图标旋转 180°(类似参考样式1) */
|
/* 展开态:图标旋转 180°(类似参考样式1) */
|
||||||
.category:not(.collapsed) > .category-header .toggle-icon i,
|
.category:not(.collapsed)>.category-header .toggle-icon i,
|
||||||
.group:not(.collapsed) > .group-header .toggle-icon i {
|
.group:not(.collapsed)>.group-header .toggle-icon i {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
color: var(--text-bright);
|
color: var(--text-bright);
|
||||||
}
|
}
|
||||||
@@ -1358,6 +1412,7 @@ body .content.expanded {
|
|||||||
|
|
||||||
/* 分类/分组折叠图标:桌面端默认隐藏,悬停/收起时显示,避免按钮过多 */
|
/* 分类/分组折叠图标:桌面端默认隐藏,悬停/收起时显示,避免按钮过多 */
|
||||||
@media (hover: hover) and (pointer: fine) {
|
@media (hover: hover) and (pointer: fine) {
|
||||||
|
|
||||||
.category-header .toggle-icon,
|
.category-header .toggle-icon,
|
||||||
.group-header .toggle-icon {
|
.group-header .toggle-icon {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@@ -1365,15 +1420,16 @@ body .content.expanded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.category-header[data-toggle="category"]:hover .toggle-icon,
|
.category-header[data-toggle="category"]:hover .toggle-icon,
|
||||||
.category.collapsed > .category-header .toggle-icon,
|
.category.collapsed>.category-header .toggle-icon,
|
||||||
.group-header[data-toggle="group"]:hover .toggle-icon,
|
.group-header[data-toggle="group"]:hover .toggle-icon,
|
||||||
.group.collapsed > .group-header .toggle-icon {
|
.group.collapsed>.group-header .toggle-icon {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 展开/折叠动画 */
|
/* 展开/折叠动画 */
|
||||||
.category-content, .group-content {
|
.category-content,
|
||||||
|
.group-content {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
@@ -1390,22 +1446,22 @@ body .content.expanded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 收起状态下调整header的下边距 */
|
/* 收起状态下调整header的下边距 */
|
||||||
.category.collapsed > .category-header {
|
.category.collapsed>.category-header {
|
||||||
margin-bottom: -0.5rem;
|
margin-bottom: -0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-level-2.collapsed > .category-header {
|
.category-level-2.collapsed>.category-header {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-level-3.collapsed > .group-header,
|
.group-level-3.collapsed>.group-header,
|
||||||
.category-level-3.collapsed > .category-header {
|
.category-level-3.collapsed>.category-header {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-level-4.collapsed > .group-header,
|
.group-level-4.collapsed>.group-header,
|
||||||
.category-level-4.collapsed > .category-header {
|
.category-level-4.collapsed>.category-header {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1427,14 +1483,14 @@ body .content.expanded {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 当分类同时包含子分类和站点时的样式优化 */
|
/* 当分类同时包含子分类和站点时的样式优化 */
|
||||||
.category-content .subcategories-container + .sites-grid {
|
.category-content .subcategories-container+.sites-grid {
|
||||||
margin-top: 1.2rem;
|
margin-top: 1.2rem;
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
border-top: 1px solid var(--border-color);
|
border-top: 1px solid var(--border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 当分类同时包含分组和站点时的样式优化 */
|
/* 当分类同时包含分组和站点时的样式优化 */
|
||||||
.category-content .groups-container + .sites-grid {
|
.category-content .groups-container+.sites-grid {
|
||||||
margin-top: 1.2rem;
|
margin-top: 1.2rem;
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
border-top: 1px solid var(--border-color);
|
border-top: 1px solid var(--border-color);
|
||||||
@@ -1464,25 +1520,27 @@ body .content.expanded {
|
|||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-level-3, .category-level-3 {
|
.group-level-3,
|
||||||
|
.category-level-3 {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-level-4, .category-level-4 {
|
.group-level-4,
|
||||||
|
.category-level-4 {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subcategories-container > .category-level-2 + .category-level-2 {
|
.subcategories-container>.category-level-2+.category-level-2 {
|
||||||
margin-top: 0.8rem;
|
margin-top: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.groups-container > .group-level-3 + .group-level-3,
|
.groups-container>.group-level-3+.group-level-3,
|
||||||
.groups-container > .category-level-3 + .category-level-3 {
|
.groups-container>.category-level-3+.category-level-3 {
|
||||||
margin-top: 0.7rem;
|
margin-top: 0.7rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subgroups-container > .group-level-4 + .group-level-4,
|
.subgroups-container>.group-level-4+.group-level-4,
|
||||||
.subcategories-container > .category-level-4 + .category-level-4 {
|
.subcategories-container>.category-level-4+.category-level-4 {
|
||||||
margin-top: 0.55rem;
|
margin-top: 0.55rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1503,13 +1561,16 @@ body .content.expanded {
|
|||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-level-2, .group-level-3, .category-level-3 {
|
.category-level-2,
|
||||||
|
.group-level-3,
|
||||||
|
.category-level-3 {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-level-4, .category-level-4 {
|
.group-level-4,
|
||||||
|
.category-level-4 {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -1611,6 +1672,8 @@ body .content.expanded {
|
|||||||
-webkit-line-clamp: 3;
|
-webkit-line-clamp: 3;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
/* Ensure tooltip positioning context */
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-card.site-card-repo .repo-stats {
|
.site-card.site-card-repo .repo-stats {
|
||||||
@@ -1928,6 +1991,43 @@ body .content.expanded {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
/* Ensure tooltip positioning context */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tooltip styles */
|
||||||
|
/* Tooltip styles */
|
||||||
|
.site-card p[data-tooltip],
|
||||||
|
.site-card .repo-desc[data-tooltip] {
|
||||||
|
cursor: default;
|
||||||
|
/* Indicate interactivity */
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tooltip {
|
||||||
|
position: fixed;
|
||||||
|
background: rgba(47, 48, 53, 0.95);
|
||||||
|
/* Fallback dark */
|
||||||
|
background: rgba(var(--card-bg-rgb), 0.95);
|
||||||
|
color: var(--text-bright);
|
||||||
|
padding: 0.5rem 0.8rem;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
box-shadow: 0 4px 12px var(--shadow-color);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
white-space: normal;
|
||||||
|
line-height: 1.4;
|
||||||
|
z-index: 9999;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s ease-out;
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
-webkit-backdrop-filter: blur(4px);
|
||||||
|
max-width: 300px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tooltip.visible {
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 添加编辑按钮 */
|
/* 添加编辑按钮 */
|
||||||
@@ -1945,7 +2045,8 @@ body .content.expanded {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-btn, .delete-btn {
|
.edit-btn,
|
||||||
|
.delete-btn {
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
@@ -1955,7 +2056,8 @@ body .content.expanded {
|
|||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-btn:hover, .delete-btn:hover {
|
.edit-btn:hover,
|
||||||
|
.delete-btn:hover {
|
||||||
color: var(--text-bright);
|
color: var(--text-bright);
|
||||||
background-color: var(--secondary-bg);
|
background-color: var(--secondary-bg);
|
||||||
}
|
}
|
||||||
@@ -2080,7 +2182,8 @@ body .content.expanded {
|
|||||||
transition: color 0.3s ease;
|
transition: color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group input, .form-group select {
|
.form-group input,
|
||||||
|
.form-group select {
|
||||||
background-color: var(--secondary-bg);
|
background-color: var(--secondary-bg);
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
@@ -2091,7 +2194,8 @@ body .content.expanded {
|
|||||||
box-shadow: 0 2px 6px var(--shadow-color);
|
box-shadow: 0 2px 6px var(--shadow-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group input:focus, .form-group select:focus {
|
.form-group input:focus,
|
||||||
|
.form-group select:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
background-color: var(--secondary-bg);
|
background-color: var(--secondary-bg);
|
||||||
border-color: var(--accent-color);
|
border-color: var(--accent-color);
|
||||||
@@ -2191,7 +2295,8 @@ body .content.expanded {
|
|||||||
.sidebar.active {
|
.sidebar.active {
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
box-shadow: 2px 0 10px var(--shadow-color);
|
box-shadow: 2px 0 10px var(--shadow-color);
|
||||||
z-index: 1000; /* 增加侧边栏激活时的z-index,确保显示在按钮之上 */
|
z-index: 1000;
|
||||||
|
/* 增加侧边栏激活时的z-index,确保显示在按钮之上 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 重置移动端下的侧边栏展开状态 */
|
/* 重置移动端下的侧边栏展开状态 */
|
||||||
@@ -2243,7 +2348,8 @@ body .content.expanded {
|
|||||||
|
|
||||||
.search-container.active {
|
.search-container.active {
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
z-index: 1000; /* 增加搜索容器激活时的z-index,确保显示在按钮之上 */
|
z-index: 1000;
|
||||||
|
/* 增加搜索容器激活时的z-index,确保显示在按钮之上 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-box {
|
.search-box {
|
||||||
@@ -2284,7 +2390,8 @@ body .content.expanded {
|
|||||||
/* 欢迎区域样式 */
|
/* 欢迎区域样式 */
|
||||||
.welcome-section {
|
.welcome-section {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
margin-top: 1rem; /* 增加顶部间距 */
|
margin-top: 1rem;
|
||||||
|
/* 增加顶部间距 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
@@ -2383,7 +2490,8 @@ body .content.expanded {
|
|||||||
|
|
||||||
/* 移动端滚动进度条调整 */
|
/* 移动端滚动进度条调整 */
|
||||||
.scroll-progress {
|
.scroll-progress {
|
||||||
height: var(--radius-sm); /* 移动端略粗一些 */
|
height: var(--radius-sm);
|
||||||
|
/* 移动端略粗一些 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar .submenu {
|
.sidebar .submenu {
|
||||||
@@ -2538,6 +2646,7 @@ body .content.expanded {
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(10px);
|
transform: translateY(10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
@@ -2552,8 +2661,10 @@ body .content.expanded {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
z-index: 15;
|
z-index: 15;
|
||||||
transform: none !important; /* 确保没有变换 */
|
transform: none !important;
|
||||||
min-height: 400px; /* 确保最小高度,防止内容过少时的布局跳动 */
|
/* 确保没有变换 */
|
||||||
|
min-height: 400px;
|
||||||
|
/* 确保最小高度,防止内容过少时的布局跳动 */
|
||||||
}
|
}
|
||||||
|
|
||||||
#search-results.active {
|
#search-results.active {
|
||||||
@@ -2620,6 +2731,7 @@ body .content.expanded {
|
|||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
@@ -2630,6 +2742,7 @@ body .content.expanded {
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(0.9);
|
transform: scale(0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
@@ -2689,7 +2802,8 @@ body .content.expanded {
|
|||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
border-top: 1px solid var(--border-color);
|
border-top: 1px solid var(--border-color);
|
||||||
background-color: var(--sidebar-bg); /* 使用变量 */
|
background-color: var(--sidebar-bg);
|
||||||
|
/* 使用变量 */
|
||||||
transition: background-color 0.3s ease, color 0.3s ease, opacity 0.3s ease;
|
transition: background-color 0.3s ease, color 0.3s ease, opacity 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2747,11 +2861,14 @@ body .content.expanded {
|
|||||||
|
|
||||||
/* 子菜单展开状态 */
|
/* 子菜单展开状态 */
|
||||||
.nav-item-wrapper.expanded .submenu {
|
.nav-item-wrapper.expanded .submenu {
|
||||||
max-height: 300px; /* 设置合理的最大高度 */
|
max-height: 300px;
|
||||||
overflow-y: scroll; /* 改为scroll确保始终能滚动 */
|
/* 设置合理的最大高度 */
|
||||||
|
overflow-y: scroll;
|
||||||
|
/* 改为scroll确保始终能滚动 */
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
scrollbar-width: none; /* Firefox隐藏滚动条 */
|
scrollbar-width: none;
|
||||||
|
/* Firefox隐藏滚动条 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 为WebKit浏览器隐藏滚动条 */
|
/* 为WebKit浏览器隐藏滚动条 */
|
||||||
@@ -2800,7 +2917,8 @@ body .content.expanded {
|
|||||||
使用display: none确保完全隐藏,避免任何可能的视觉问题 */
|
使用display: none确保完全隐藏,避免任何可能的视觉问题 */
|
||||||
.sidebar.collapsed .submenu {
|
.sidebar.collapsed .submenu {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: var(--sidebar-collapsed-width); /* 使用变量确保与侧边栏宽度一致 */
|
left: var(--sidebar-collapsed-width);
|
||||||
|
/* 使用变量确保与侧边栏宽度一致 */
|
||||||
top: 0;
|
top: 0;
|
||||||
background-color: var(--sidebar-bg);
|
background-color: var(--sidebar-bg);
|
||||||
border-radius: 0 8px 8px 0;
|
border-radius: 0 8px 8px 0;
|
||||||
@@ -2814,7 +2932,8 @@ body .content.expanded {
|
|||||||
z-index: 200;
|
z-index: 200;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
display: none; /* 添加 display: none 确保完全隐藏 */
|
display: none;
|
||||||
|
/* 添加 display: none 确保完全隐藏 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 确保子菜单项在悬停时不会漏出
|
/* 确保子菜单项在悬停时不会漏出
|
||||||
@@ -2831,7 +2950,8 @@ body .content.expanded {
|
|||||||
使用static定位是为了让子菜单相对于侧边栏定位,而不是相对于nav-item-wrapper,
|
使用static定位是为了让子菜单相对于侧边栏定位,而不是相对于nav-item-wrapper,
|
||||||
这样可以避免子菜单在折叠状态下漏出的问题 */
|
这样可以避免子菜单在折叠状态下漏出的问题 */
|
||||||
.sidebar.collapsed .nav-item-wrapper {
|
.sidebar.collapsed .nav-item-wrapper {
|
||||||
position: static; /* 改为static,防止子菜单定位问题 */
|
position: static;
|
||||||
|
/* 改为static,防止子菜单定位问题 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 修改子菜单在悬停时的显示位置
|
/* 修改子菜单在悬停时的显示位置
|
||||||
@@ -2845,9 +2965,12 @@ body .content.expanded {
|
|||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
display: block;
|
display: block;
|
||||||
left: var(--sidebar-collapsed-width); /* 确保与侧边栏宽度一致 */
|
left: var(--sidebar-collapsed-width);
|
||||||
top: 0; /* 确保从顶部开始 */
|
/* 确保与侧边栏宽度一致 */
|
||||||
position: absolute; /* 使用绝对定位,更符合文档流 */
|
top: 0;
|
||||||
|
/* 确保从顶部开始 */
|
||||||
|
position: absolute;
|
||||||
|
/* 使用绝对定位,更符合文档流 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 为WebKit浏览器隐藏滚动条 */
|
/* 为WebKit浏览器隐藏滚动条 */
|
||||||
|
|||||||
@@ -274,6 +274,7 @@ window.MeNav = {
|
|||||||
|
|
||||||
newSite.href = siteUrl;
|
newSite.href = siteUrl;
|
||||||
newSite.title = siteName + (siteDescription ? ' - ' + siteDescription : '');
|
newSite.title = siteName + (siteDescription ? ' - ' + siteDescription : '');
|
||||||
|
newSite.setAttribute('data-tooltip', siteName + (siteDescription ? ' - ' + siteDescription : '')); // 添加自定义 tooltip
|
||||||
if (/^https?:\/\//i.test(siteUrl)) {
|
if (/^https?:\/\//i.test(siteUrl)) {
|
||||||
newSite.target = '_blank';
|
newSite.target = '_blank';
|
||||||
newSite.rel = 'noopener';
|
newSite.rel = 'noopener';
|
||||||
@@ -1909,3 +1910,73 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Tooltip functionality for truncated text
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
// Create tooltip element
|
||||||
|
const tooltip = document.createElement('div');
|
||||||
|
tooltip.className = 'custom-tooltip';
|
||||||
|
document.body.appendChild(tooltip);
|
||||||
|
|
||||||
|
let activeElement = null;
|
||||||
|
|
||||||
|
// Show tooltip on hover
|
||||||
|
document.addEventListener('mouseover', (e) => {
|
||||||
|
const target = e.target.closest('[data-tooltip]');
|
||||||
|
if (target) {
|
||||||
|
const tooltipText = target.getAttribute('data-tooltip');
|
||||||
|
if (tooltipText) {
|
||||||
|
activeElement = target;
|
||||||
|
tooltip.textContent = tooltipText;
|
||||||
|
tooltip.classList.add('visible');
|
||||||
|
updateTooltipPosition(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Move tooltip with cursor
|
||||||
|
document.addEventListener('mousemove', (e) => {
|
||||||
|
if (activeElement) {
|
||||||
|
updateTooltipPosition(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hide tooltip on mouse out
|
||||||
|
document.addEventListener('mouseout', (e) => {
|
||||||
|
const target = e.target.closest('[data-tooltip]');
|
||||||
|
if (target && target === activeElement) {
|
||||||
|
// Check if we really left the element (not just went to a child)
|
||||||
|
if (!target.contains(e.relatedTarget)) {
|
||||||
|
activeElement = null;
|
||||||
|
tooltip.classList.remove('visible');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateTooltipPosition(e) {
|
||||||
|
// Position tooltip 15px below/right of cursor
|
||||||
|
const x = e.clientX + 15;
|
||||||
|
const y = e.clientY + 15;
|
||||||
|
|
||||||
|
// Boundary checks to keep inside viewport
|
||||||
|
const rect = tooltip.getBoundingClientRect();
|
||||||
|
const winWidth = window.innerWidth;
|
||||||
|
const winHeight = window.innerHeight;
|
||||||
|
|
||||||
|
let finalX = x;
|
||||||
|
let finalY = y;
|
||||||
|
|
||||||
|
// If tooltip goes off right edge
|
||||||
|
if (x + rect.width > winWidth) {
|
||||||
|
finalX = e.clientX - rect.width - 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If tooltip goes off bottom edge
|
||||||
|
if (y + rect.height > winHeight) {
|
||||||
|
finalY = e.clientY - rect.height - 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip.style.left = finalX + 'px';
|
||||||
|
tooltip.style.top = finalY + 'px';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
{{#if url}}
|
{{#if url}}
|
||||||
<a href="{{url}}" class="site-card{{#if style}} site-card-{{style}}{{/if}}"
|
<a href="{{url}}" class="site-card{{#if style}} site-card-{{style}}{{/if}}" {{#if external}}target="_blank"
|
||||||
{{#if external}}target="_blank" rel="noopener"{{/if}}
|
rel="noopener" {{/if}} data-type="{{#if type}}{{type}}{{else}}site{{/if}}" data-name="{{name}}" data-url="{{url}}"
|
||||||
data-type="{{#if type}}{{type}}{{else}}site{{/if}}"
|
data-icon="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}}" {{#if faviconUrl}}data-favicon-url="{{faviconUrl}}"
|
||||||
data-name="{{name}}"
|
{{/if}} {{#if forceIconMode}}data-force-icon-mode="{{forceIconMode}}" {{/if}}
|
||||||
data-url="{{url}}"
|
|
||||||
data-icon="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}}"
|
|
||||||
{{#if faviconUrl}}data-favicon-url="{{faviconUrl}}"{{/if}}
|
|
||||||
{{#if forceIconMode}}data-force-icon-mode="{{forceIconMode}}"{{/if}}
|
|
||||||
data-description="{{#if description}}{{description}}{{else}}{{extractDomain url}}{{/if}}"
|
data-description="{{#if description}}{{description}}{{else}}{{extractDomain url}}{{/if}}"
|
||||||
{{#if publishedAt}}data-published-at="{{publishedAt}}"{{/if}}
|
data-tooltip="{{#if name}}{{name}}{{else}}未命名站点{{/if}}{{#if description}} - {{description}}{{else}} - {{extractDomain url}}{{/if}}"
|
||||||
{{#if source}}data-source="{{source}}"{{/if}}>
|
{{#if publishedAt}}data-published-at="{{publishedAt}}" {{/if}} {{#if source}}data-source="{{source}}" {{/if}}>
|
||||||
{{!-- articles:首行图标+标题;下方“时间/来源 + 简介”全宽对齐,不被图标列缩进 --}}
|
{{!-- articles:首行图标+标题;下方“时间/来源 + 简介”全宽对齐,不被图标列缩进 --}}
|
||||||
{{#ifEquals type "article"}}
|
{{#ifEquals type "article"}}
|
||||||
<div class="article-card-header">
|
<div class="article-card-header">
|
||||||
@@ -18,14 +14,9 @@
|
|||||||
{{#if faviconUrl}}
|
{{#if faviconUrl}}
|
||||||
<div class="icon-container">
|
<div class="icon-container">
|
||||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||||
<img
|
<img class="favicon-icon" src="{{faviconUrl}}" alt="{{name}} favicon" loading="lazy"
|
||||||
class="favicon-icon"
|
|
||||||
src="{{faviconUrl}}"
|
|
||||||
alt="{{name}} favicon"
|
|
||||||
loading="lazy"
|
|
||||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||||
onerror="this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
onerror="this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');" />
|
||||||
/>
|
|
||||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
@@ -36,14 +27,9 @@
|
|||||||
{{#ifHttpUrl url}}
|
{{#ifHttpUrl url}}
|
||||||
<div class="icon-container">
|
<div class="icon-container">
|
||||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||||
<img
|
<img class="favicon-icon" src="{{faviconUrl url}}" alt="{{name}} favicon" loading="lazy"
|
||||||
class="favicon-icon"
|
|
||||||
src="{{faviconUrl url}}"
|
|
||||||
alt="{{name}} favicon"
|
|
||||||
loading="lazy"
|
|
||||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||||
onerror="if (!this.dataset.faviconFallbackTried) { this.dataset.faviconFallbackTried = '1'; this.src = '{{faviconFallbackUrl url}}'; return; } this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
onerror="if (!this.dataset.faviconFallbackTried) { this.dataset.faviconFallbackTried = '1'; this.src = '{{faviconFallbackUrl url}}'; return; } this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');" />
|
||||||
/>
|
|
||||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
@@ -54,14 +40,9 @@
|
|||||||
{{#ifHttpUrl url}}
|
{{#ifHttpUrl url}}
|
||||||
<div class="icon-container">
|
<div class="icon-container">
|
||||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||||
<img
|
<img class="favicon-icon" src="{{faviconUrl url}}" alt="{{name}} favicon" loading="lazy"
|
||||||
class="favicon-icon"
|
|
||||||
src="{{faviconUrl url}}"
|
|
||||||
alt="{{name}} favicon"
|
|
||||||
loading="lazy"
|
|
||||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||||
onerror="if (!this.dataset.faviconFallbackTried) { this.dataset.faviconFallbackTried = '1'; this.src = '{{faviconFallbackUrl url}}'; return; } this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
onerror="if (!this.dataset.faviconFallbackTried) { this.dataset.faviconFallbackTried = '1'; this.src = '{{faviconFallbackUrl url}}'; return; } this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');" />
|
||||||
/>
|
|
||||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
@@ -93,7 +74,8 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/ifCond}}
|
{{/ifCond}}
|
||||||
<p>{{#if description}}{{description}}{{else}}{{extractDomain url}}{{/if}}</p>
|
<p>{{#if
|
||||||
|
description}}{{description}}{{else}}{{extractDomain url}}{{/if}}</p>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{!-- projects:代码仓库风格卡片(保留 data-* 结构,便于扩展识别与写回) --}}
|
{{!-- projects:代码仓库风格卡片(保留 data-* 结构,便于扩展识别与写回) --}}
|
||||||
@@ -103,13 +85,15 @@
|
|||||||
<div class="repo-title">{{#if name}}{{name}}{{else}}未命名项目{{/if}}</div>
|
<div class="repo-title">{{#if name}}{{name}}{{else}}未命名项目{{/if}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="repo-desc">{{#if description}}{{description}}{{else}}{{extractDomain url}}{{/if}}</div>
|
<div class="repo-desc">{{#if
|
||||||
|
description}}{{description}}{{else}}{{extractDomain url}}{{/if}}</div>
|
||||||
|
|
||||||
{{#ifCond language '||' stars}}
|
{{#ifCond language '||' stars}}
|
||||||
<div class="repo-stats">
|
<div class="repo-stats">
|
||||||
{{#if language}}
|
{{#if language}}
|
||||||
<div class="stat-item">
|
<div class="stat-item">
|
||||||
<span class="lang-dot" style="background-color: {{#if languageColor}}{{languageColor}}{{else}}#909296{{/if}};"></span>
|
<span class="lang-dot"
|
||||||
|
style="background-color: {{#if languageColor}}{{languageColor}}{{else}}#909296{{/if}};"></span>
|
||||||
{{language}}
|
{{language}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@@ -136,14 +120,9 @@
|
|||||||
{{#if faviconUrl}}
|
{{#if faviconUrl}}
|
||||||
<div class="icon-container">
|
<div class="icon-container">
|
||||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||||
<img
|
<img class="favicon-icon" src="{{faviconUrl}}" alt="{{name}} favicon" loading="lazy"
|
||||||
class="favicon-icon"
|
|
||||||
src="{{faviconUrl}}"
|
|
||||||
alt="{{name}} favicon"
|
|
||||||
loading="lazy"
|
|
||||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||||
onerror="this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
onerror="this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');" />
|
||||||
/>
|
|
||||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
@@ -154,14 +133,9 @@
|
|||||||
{{#ifHttpUrl url}}
|
{{#ifHttpUrl url}}
|
||||||
<div class="icon-container">
|
<div class="icon-container">
|
||||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||||
<img
|
<img class="favicon-icon" src="{{faviconUrl url}}" alt="{{name}} favicon" loading="lazy"
|
||||||
class="favicon-icon"
|
|
||||||
src="{{faviconUrl url}}"
|
|
||||||
alt="{{name}} favicon"
|
|
||||||
loading="lazy"
|
|
||||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||||
onerror="if (!this.dataset.faviconFallbackTried) { this.dataset.faviconFallbackTried = '1'; this.src = '{{faviconFallbackUrl url}}'; return; } this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
onerror="if (!this.dataset.faviconFallbackTried) { this.dataset.faviconFallbackTried = '1'; this.src = '{{faviconFallbackUrl url}}'; return; } this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');" />
|
||||||
/>
|
|
||||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
@@ -172,14 +146,9 @@
|
|||||||
{{#ifHttpUrl url}}
|
{{#ifHttpUrl url}}
|
||||||
<div class="icon-container">
|
<div class="icon-container">
|
||||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||||
<img
|
<img class="favicon-icon" src="{{faviconUrl url}}" alt="{{name}} favicon" loading="lazy"
|
||||||
class="favicon-icon"
|
|
||||||
src="{{faviconUrl url}}"
|
|
||||||
alt="{{name}} favicon"
|
|
||||||
loading="lazy"
|
|
||||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||||
onerror="if (!this.dataset.faviconFallbackTried) { this.dataset.faviconFallbackTried = '1'; this.src = '{{faviconFallbackUrl url}}'; return; } this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
onerror="if (!this.dataset.faviconFallbackTried) { this.dataset.faviconFallbackTried = '1'; this.src = '{{faviconFallbackUrl url}}'; return; } this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');" />
|
||||||
/>
|
|
||||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
@@ -195,7 +164,8 @@
|
|||||||
|
|
||||||
<div class="site-card-content">
|
<div class="site-card-content">
|
||||||
<h3>{{#if name}}{{name}}{{else}}未命名站点{{/if}}</h3>
|
<h3>{{#if name}}{{name}}{{else}}未命名站点{{/if}}</h3>
|
||||||
<p>{{#if description}}{{description}}{{else}}{{extractDomain url}}{{/if}}</p>
|
<p>{{#if
|
||||||
|
description}}{{description}}{{else}}{{extractDomain url}}{{/if}}</p>
|
||||||
</div>
|
</div>
|
||||||
{{/ifEquals}}
|
{{/ifEquals}}
|
||||||
{{/ifEquals}}
|
{{/ifEquals}}
|
||||||
|
|||||||
Reference in New Issue
Block a user