Files
ComfyUI-Lora-Manager/static/css/style.css

844 lines
18 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

:root {
--bg-color: #ffffff;
--text-color: #333333;
--card-bg: #ffffff;
--border-color: #e0e0e0;
/* Color System */
--lora-accent: oklch(68% 0.28 256);
--lora-surface: oklch(100% 0 0 / 0.95);
--lora-border: oklch(90% 0.02 256 / 0.15);
--lora-text: oklch(95% 0.02 256);
--lora-error: oklch(75% 0.32 29);
/* Spacing Scale */
--space-1: calc(8px * 1);
--space-2: calc(8px * 2);
--space-3: calc(8px * 3);
/* Z-index Scale */
--z-base: 10;
--z-modal: 30;
--z-overlay: 50;
/* Border Radius */
--border-radius-base: 12px;
--border-radius-sm: 8px;
--border-radius-xs: 4px;
}
[data-theme="dark"] {
--bg-color: #1a1a1a;
--text-color: #e0e0e0;
--card-bg: #2d2d2d;
--border-color: #404040;
--lora-accent: oklch(68% 0.28 256);
--lora-surface: oklch(25% 0.02 256 / 0.85);
--lora-border: oklch(90% 0.02 256 / 0.15);
--lora-text: oklch(98% 0.02 256);
}
body {
margin: 0;
font-family: 'Segoe UI', sans-serif;
background: var(--bg-color);
color: var(--text-color);
}
.container {
max-width: 1400px;
margin: 20px auto;
padding: 0 15px;
}
/* 文件夹标签样式 */
.folder-tags {
display: flex;
gap: 4px;
overflow-x: auto;
padding: 4px 0;
flex-wrap: wrap;
}
.tag {
cursor: pointer;
padding: 2px 8px;
margin: 2px;
border: 1px solid #ccc;
border-radius: var(--border-radius-xs);
display: inline-block;
line-height: 1.2;
font-size: 14px;
}
.tag.active {
background-color: #007bff;
color: white;
}
/* 卡片网格布局 */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); /* Adjusted from 320px */
gap: 12px; /* Reduced from var(--space-2) for tighter horizontal spacing */
margin-top: var(--space-2);
max-width: 1400px; /* Container width control */
margin-left: auto;
margin-right: auto;
}
.lora-card {
background: var(--lora-surface);
border: 1px solid var(--lora-border);
border-radius: var(--border-radius-base);
backdrop-filter: blur(16px);
transition: transform 160ms ease-out;
aspect-ratio: 896/1152;
max-width: 260px; /* Adjusted from 320px to fit 5 cards */
margin: 0 auto;
}
.lora-card:hover {
transform: translateY(-2px);
background: oklch(100% 0 0 / 0.6);
}
.lora-card:focus-visible {
outline: 2px solid var(--lora-accent);
outline-offset: 2px;
}
/* Responsive adjustments */
@media (max-width: 1400px) {
.card-grid {
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.lora-card {
max-width: 240px;
}
}
@media (max-width: 768px) {
.card-grid {
grid-template-columns: minmax(260px, 1fr);
}
.lora-card {
max-width: 100%;
}
}
/* Card Preview and Footer Overlay */
.card-preview {
position: relative;
width: 100%;
height: 100%;
border-radius: var(--border-radius-base);
overflow: hidden; /* 添加此行以限制子元素不超出边界 */
}
.card-preview img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: var(--border-radius-base); /* 与容器相同的圆角 */
}
.card-preview video {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: var(--border-radius-base); /* 与容器相同的圆角 */
}
.card-footer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(transparent 15%, oklch(0% 0 0 / 0.75));
backdrop-filter: blur(8px);
color: white;
padding: var(--space-1);
display: flex;
justify-content: space-between;
align-items: flex-start; /* Changed from flex-end to allow for text wrapping */
min-height: 32px;
gap: var(--space-1); /* Add gap between model info and actions */
}
.model-name {
font-weight: bold;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
font-size: 0.95em;
word-break: break-word; /* Allow long words to break */
display: block; /* Ensure the text wraps */
max-height: 2.8em; /* Limit to roughly 2 lines */
overflow: hidden;
}
.model-meta {
font-size: 0.9em;
opacity: 0.9;
}
.card-header {
position: absolute;
top: 0;
left: 0;
right: 0;
background: linear-gradient(oklch(0% 0 0 / 0.75), transparent 85%);
backdrop-filter: blur(8px);
color: white;
padding: var(--space-1);
display: flex;
justify-content: space-between;
align-items: center;
z-index: 1;
min-height: 20px;
}
.card-actions i {
margin-left: var(--space-1);
cursor: pointer;
color: white;
transition: opacity 0.2s;
font-size: 0.9em;
}
.card-actions i:hover {
opacity: 0.8;
}
/* 响应式设计 */
@media (max-width: 768px) {
.card-grid {
grid-template-columns: minmax(260px, 1fr); /* Adjusted minimum size for mobile */
}
.controls {
flex-direction: column;
gap: 15px;
}
.lora-card {
max-width: 100%; /* Allow cards to fill available space on mobile */
}
}
/* 新增元数据相关样式 */
.model-info {
flex: 1;
min-width: 0; /* Allow flex item to shrink below content size */
overflow: hidden; /* Prevent content from spilling out */
padding-bottom: 4px; /* 为了与底部对齐的图标留出一些空间 */
}
.model-meta {
font-size: 0.8em;
color: #666;
margin-top: 4px;
}
.base-model {
display: inline-block;
background: #f0f0f0;
padding: 2px 6px;
border-radius: var(--border-radius-xs);
margin-right: 6px;
}
.file-size,
.modified {
display: block;
margin-top: 2px;
}
.tooltip {
position: relative;
cursor: help;
}
.tooltip::after {
content: attr(data-tooltip);
position: absolute;
bottom: 120%;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 0.8em;
white-space: nowrap;
opacity: 0;
transition: opacity 0.2s;
pointer-events: none;
}
.tooltip:hover::after {
opacity: 1;
}
/* 模态窗口样式 */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
z-index: 1000;
overflow-y: auto; /* 允许模态窗口内容滚动 */
}
/* 当模态窗口打开时禁止body滚动 */
body.modal-open {
overflow: hidden;
}
.modal-content {
position: relative;
max-width: 800px;
margin: 2rem auto;
background: var(--lora-surface);
border-radius: var(--border-radius-base);
padding: var(--space-3);
border: 1px solid var(--lora-border);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}
/* Delete Modal specific styles */
.delete-modal-content {
max-width: 500px;
text-align: center;
}
.delete-message {
color: var(--text-color);
margin: var(--space-2) 0;
}
.delete-model-info {
background: var(--lora-surface);
border: 1px solid var(--lora-border);
border-radius: var(--border-radius-sm);
padding: var(--space-2);
margin: var(--space-2) 0;
color: var(--text-color);
word-break: break-all;
}
/* Update delete modal styles */
.delete-modal {
display: none; /* Set initial display to none */
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
z-index: var(--z-overlay);
}
/* Add new style for when modal is shown */
.delete-modal.show {
display: flex;
align-items: center;
justify-content: center;
}
.delete-modal-content {
max-width: 500px;
width: 90%;
text-align: center;
margin: 0 auto;
position: relative;
animation: modalFadeIn 0.2s ease-out;
}
.delete-model-info {
/* Update info display styling */
background: var(--lora-surface);
border: 1px solid var(--lora-border);
border-radius: var(--border-radius-sm);
padding: var(--space-2);
margin: var(--space-2) 0;
color: var(--text-color);
word-break: break-all;
text-align: left;
line-height: 1.5;
}
@keyframes modalFadeIn {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.modal-actions {
display: flex;
gap: var(--space-2);
justify-content: center;
margin-top: var(--space-3);
}
.cancel-btn, .delete-btn {
padding: 8px var(--space-2);
border-radius: 6px;
border: none;
cursor: pointer;
font-weight: 500;
min-width: 100px;
}
.cancel-btn {
background: var(--lora-surface);
border: 1px solid var(--lora-border);
color: var(--text-color);
}
.delete-btn {
background: var(--lora-error);
color: white;
}
.cancel-btn:hover {
background: var(--lora-border);
}
.delete-btn:hover {
opacity: 0.9;
}
.carousel {
display: grid;
grid-auto-flow: column;
gap: 1rem;
overflow-x: auto;
scroll-snap-type: x mandatory;
}
.carousel img {
scroll-snap-align: start;
max-height: 60vh;
object-fit: contain;
}
.carousel video {
scroll-snap-align: start;
max-height: 60vh;
object-fit: contain;
}
/* 主题切换按钮 */
.theme-toggle {
position: fixed;
top: 20px;
right: 20px;
cursor: pointer;
padding: 8px;
border-radius: 50%;
background: var(--card-bg);
}
.base-model-label {
max-width: 120px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
color: white;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
background: rgba(255, 255, 255, 0.2);
padding: 2px var(--space-1);
border-radius: var(--border-radius-xs);
backdrop-filter: blur(2px);
font-size: 0.85em;
}
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: oklch(0% 0 0 / 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: var(--z-overlay);
}
.loading-content {
background: var(--lora-surface);
backdrop-filter: blur(24px);
padding: var(--space-3);
border-radius: var(--border-radius-base);
text-align: center;
border: 1px solid var(--lora-border);
width: min(400px, 90vw); /* 固定最大宽度,但保持响应式 */
}
.loading-spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 0 auto 1rem;
}
.loading-status {
margin-bottom: 1rem;
color: var(--text-color); /* 使用主题文本颜色 */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
padding: 0 var(--space-2);
}
.progress-container {
width: 280px; /* 固定进度条宽度 */
background-color: var(--lora-border); /* 使用主题边框颜色 */
border-radius: 4px;
overflow: hidden;
margin: 0 auto; /* 居中显示 */
}
.progress-bar {
width: 0%;
height: var(--space-2);
background-color: var(--lora-accent);
transition: width 200ms ease-out;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
.lora-card,
.progress-bar {
transition: none;
}
}
.card-actions {
flex-shrink: 0; /* Prevent actions from shrinking */
display: flex;
align-items: center;
gap: var(--space-1);
align-items: flex-end; /* 将图标靠下对齐 */
align-self: flex-end; /* 将整个actions容器靠下对齐 */
}
.model-link {
margin-top: var(--space-1);
}
.model-link a {
color: var(--lora-accent);
text-decoration: none;
font-size: 1.1em;
transition: opacity 0.2s;
text-shadow: none;
}
.model-link a:hover {
opacity: 0.8;
text-decoration: none;
}
.modal-content h2 {
color: var(--text-color);
margin-bottom: var(--space-2);
font-size: 1.5em;
}
.description {
color: var(--text-color);
margin: var(--space-2) 0;
line-height: 1.4;
}
.trigger-words {
display: flex;
gap: var(--space-2);
background: var(--lora-surface);
border: 1px solid var(--lora-border);
border-radius: var(--border-radius-sm);
padding: var(--space-2);
margin: var(--space-2) 0;
}
.trigger-words-categories {
flex: 0 0 200px;
border-right: 1px solid var(--lora-border);
padding-right: var(--space-2);
}
.trigger-category {
padding: 8px;
margin-bottom: 4px;
border-radius: var(--border-radius-xs);
cursor: pointer;
color: var(--text-color);
font-size: 0.9em;
transition: background-color 0.2s;
}
.trigger-category:hover {
background: var(--lora-border);
}
.trigger-category.active {
background: var(--lora-accent);
color: white;
}
.trigger-words-list {
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
overflow-y: auto;
max-height: 300px;
}
.trigger-word-tag {
display: flex;
align-items: center;
padding: 8px 12px;
background: var(--lora-surface);
border: 1px solid var(--lora-border);
border-radius: var(--border-radius-xs);
cursor: pointer;
transition: all 0.2s ease;
font-size: 0.85em;
color: var(--text-color);
position: relative;
gap: var(--space-1);
}
.trigger-word-tag:hover {
background: oklch(var(--lora-accent) / 0.1);
border-color: var(--lora-accent);
}
.trigger-word-tag:active {
transform: scale(0.98);
}
.trigger-word-content {
flex: 1;
word-break: break-word;
line-height: 1.4;
}
.trigger-word-copy {
opacity: 0.5;
color: var(--text-color);
display: flex;
align-items: center;
justify-content: center;
}
.trigger-word-tag:hover .trigger-word-copy {
opacity: 0.8;
}
/* Update toast animation for trigger word copy */
.toast.toast-copy {
background: var(--lora-accent);
color: white;
border: none;
padding: 8px 16px;
font-size: 0.9em;
transform: translateX(-50%) translateY(20px);
}
.toast.toast-copy.show {
transform: translateX(-50%) translateY(0);
}
.copy-btn {
background: transparent;
border: none;
cursor: pointer;
padding: var(--space-1);
margin-left: var(--space-1);
color: var(--lora-accent);
opacity: 0.8;
transition: opacity 0.2s;
}
.copy-btn:hover {
opacity: 1;
}
.close {
position: absolute;
top: var(--space-2);
right: var(--space-2);
background: transparent;
border: none;
color: var(--text-color);
font-size: 1.5em;
cursor: pointer;
opacity: 0.7;
transition: opacity 0.2s;
}
.close:hover {
opacity: 1;
}
/* Toast Notifications */
.toast {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%) translateY(100px);
background: var(--lora-surface);
color: var(--text-color);
padding: 12px 24px;
border-radius: var(--border-radius-sm);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: calc(var(--z-overlay) + 10); /* 确保 toast 显示在模态窗口之上 */
opacity: 0;
transition: transform 0.3s ease-out, opacity 0.3s ease-out;
text-align: center;
max-width: 90%;
backdrop-filter: blur(8px);
border: 1px solid var(--lora-border);
}
/* 当模态窗口打开时的 toast 样式 */
body.modal-open .toast {
bottom: 50% !important; /* 强制覆盖默认位置 */
transform: translate(-50%, 50%) !important; /* 强制覆盖默认变换 */
background: var(--lora-accent);
color: white;
z-index: 9999; /* 确保显示在最上层 */
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25);
}
.toast.show {
transform: translateX(-50%) translateY(0);
opacity: 1;
}
/* 确保在模态窗口打开时,不同类型的 toast 依然可辨识 */
body.modal-open .toast-success {
background: oklch(65% 0.2 142); /* 绿色 */
}
body.modal-open .toast-error {
background: oklch(65% 0.2 29); /* 红色 */
}
body.modal-open .toast-info {
background: oklch(65% 0.2 256); /* 蓝色 */
}
.toast-success {
border-left: 4px solid #4caf50;
}
.toast-error {
border-left: 4px solid #f44336;
}
.toast-info {
border-left: 4px solid #2196f3;
}
/* Ensure toasts are visible in both themes */
[data-theme="dark"] .toast {
background: var(--lora-surface);
color: var(--lora-text);
}
/* Updated Trigger Words Section */
.trigger-words-container {
display: grid;
grid-template-columns: 200px 1fr;
align-items: flex-start;
gap: var(--space-2);
margin: var(--space-2) 0;
padding: var(--space-2);
background: var(--lora-surface);
border: 1px solid var(--lora-border);
border-radius: var(--border-radius-sm);
}
.trigger-words-title {
font-size: 0.95em;
color: var(--text-color);
text-align: center;
display: flex;
align-items: center;
justify-content: center;
min-height: 100%;
}
.trigger-words-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: flex-start;
}
.trigger-word-tag {
display: inline-flex;
align-items: center;
background: var(--lora-surface);
border: 1px solid var(--lora-border);
border-radius: var(--border-radius-xs);
padding: 6px 10px;
cursor: pointer;
transition: all 0.2s ease;
gap: 8px;
max-width: 100%;
}
.trigger-word-content {
color: oklch(65% 0.2 256); /* Accent color for trigger words */
font-size: 0.85em;
line-height: 1.4;
word-break: break-word;
}
.trigger-word-copy {
display: flex;
align-items: center;
color: var(--text-color);
opacity: 0.5;
flex-shrink: 0;
transition: opacity 0.2s;
}
.trigger-word-tag:hover {
background: oklch(var(--lora-accent) / 0.1);
border-color: var(--lora-accent);
}
.trigger-word-tag:hover .trigger-word-copy {
opacity: 0.8;
}
.trigger-word-tag:active {
transform: scale(0.98);
}