Files
yawiii-ComfyUI-Prompt-Assis…/js/css/assistant.css
T
2025-12-21 22:52:38 +08:00

670 lines
17 KiB
CSS

/**
* 提示词小助手 (PromptAssistant) 样式表
* 包含所有组件样式和动画定义
*/
/* ==========================================================================
1. 核心容器组件 (Assistant Container)
========================================================================== */
/* 通用容器基础样式 */
.assistant-container-common {
/* 定位与布局 */
position: absolute;
display: flex;
align-items: center;
justify-content: flex-end;
/* 默认对齐 */
width: auto !important;
height: auto !important;
min-width: 0;
min-height: 0;
max-width: none;
box-sizing: border-box;
/* 视觉样式 */
padding: 2px;
/* background-color: color-mix(in srgb, var(--bg-color), transparent 50%); */
background-color: color-mix(in srgb, var(--node-component-header-surface), transparent 60%);
border: 1px solid color-mix(in srgb, var(--p-panel-border-color), transparent 60%);
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
/* 效果 */
z-index: 9999;
opacity: 0.95;
backdrop-filter: blur(4px);
/* 交互与状态*/
user-select: none;
overflow: hidden;
pointer-events: all;
cursor: default;
/* 移除抓手光标效果 */
/* 过渡动画 */
transition: width 0.3s cubic-bezier(0.25, 1, 0.5, 1),
height 0.3s cubic-bezier(0.25, 1, 0.5, 1),
opacity 0.3s cubic-bezier(0.25, 1, 0.5, 1),
background-color 0.3s,
border-color 0.3s,
backdrop-filter 0.3s,
box-shadow 0.3s;
}
/* 兼容性修复:覆盖 PrimeVue 或其他样式影响?*/
.assistant-container-common * {
box-sizing: border-box;
}
/* ==========================================================================
2. 状态样式 (States)
========================================================================== */
/* 展开状态 */
.assistant-container-common.expanded {
/* 展开状态下使用JS计算的动态宽高 */
width: var(--expanded-width, 28px) !important;
height: var(--expanded-height, 28px) !important;
}
/* 折叠状态 */
.assistant-container-common.collapsed {
/* 折叠状态下的固定尺寸*/
width: 28px !important;
height: 28px !important;
/* 隐形模式 */
background-color: transparent !important;
border-color: transparent !important;
backdrop-filter: none !important;
box-shadow: none !important;
/* 交互 */
pointer-events: none !important;
/* 允许点击穿透 */
}
/* 显示/隐藏辅助类 */
.assistant-show {
display: flex !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
/* ==========================================================================
3. 内部元素 (Internal Elements)
========================================================================== */
/* 悬停检测区域 */
.assistant-hover-area {
position: absolute;
top: -10px;
right: -10px;
bottom: -10px;
left: -10px;
z-index: -1;
pointer-events: auto;
/* 确保能接收鼠标事件 */
background: transparent;
}
/* 指示器图标 (折叠时显示) */
.assistant-indicator {
position: absolute;
width: 18px;
height: 18px;
z-index: 2;
pointer-events: none;
opacity: 0;
/* transform 仅用于缩放动画 */
transform: scale(1);
transition: opacity 0.45s cubic-bezier(0.34, 1.56, 0.64, 1), transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* 状态下的指示器表现 */
.assistant-container-common.collapsed .assistant-indicator {
opacity: var(--assistant-icon-opacity, 0.8);
pointer-events: auto;
filter: drop-shadow(0 0 2px rgba(255, 255, 255, 0.6)) drop-shadow(0 0 4px rgba(100, 200, 255, 0.5));
}
.assistant-container-common.expanded .assistant-indicator {
opacity: 0;
transform: scale(0);
}
/* ---指示器布局定位:固定在折叠状态的中心位置,不随容器尺寸变化--- */
/* 折叠状态容器尺寸为 28x28px,指示器 18x18px,居中偏移 = (28-18)/2 = 5px */
/* 左上角布局:指示器在左上角 */
.layout-top-left-h .assistant-indicator,
.layout-top-left-v .assistant-indicator {
top: 5px;
left: 5px;
}
/* 中上布局:指示器水平居中,垂直靠上 */
.layout-top-center-h .assistant-indicator {
top: 5px;
left: 50%;
margin-left: -9px;
/* 18px / 2 */
}
/* 右上角布局:指示器在右上角 */
.layout-top-right-h .assistant-indicator,
.layout-top-right-v .assistant-indicator {
top: 5px;
right: 5px;
}
/* 右中布局:指示器垂直居中,水平靠右 */
.layout-right-center-v .assistant-indicator {
top: 50%;
right: 5px;
margin-top: -9px;
}
/* 右下角布局:指示器在右下角 */
.layout-bottom-right-h .assistant-indicator,
.layout-bottom-right-v .assistant-indicator {
bottom: 5px;
right: 5px;
}
/* 中下布局:指示器水平居中,垂直靠下 */
.layout-bottom-center-h .assistant-indicator {
bottom: 5px;
left: 50%;
margin-left: -9px;
}
/* 左下角布局:指示器在左下角 */
.layout-bottom-left-h .assistant-indicator,
.layout-bottom-left-v .assistant-indicator {
bottom: 5px;
left: 5px;
}
/* 左中布局:指示器垂直居中,水平靠上?*/
.layout-left-center-v .assistant-indicator {
top: 50%;
left: 5px;
margin-top: -9px;
}
/* 内容区域 */
.assistant-content {
display: flex;
align-items: center;
gap: 0;
width: 100%;
height: 100%;
cursor: default;
/* 确保非按钮区域使用默认*/
transition: opacity 0.3s ease;
}
/* 状态下的内容表现 */
.assistant-container-common.collapsed .assistant-content {
opacity: 0;
pointer-events: none;
}
.assistant-container-common.expanded .assistant-content {
opacity: 1;
pointer-events: auto;
}
/* 内容布局方向 */
.assistant-content.flex-row {
flex-direction: row;
}
.assistant-content.flex-col {
flex-direction: column;
}
/* ---内容区域对齐方式:根据容器布局位置设置--- */
/* 注意:column-reverse 时主轴从下到上,flex-start 是底部,flex-end 是顶部 */
/* 横向布局 - 左侧:内容左对齐 */
.layout-top-left-h .assistant-content,
.layout-bottom-left-h .assistant-content {
justify-content: flex-start;
}
/* 横向布局 - 右侧:内容右对齐 */
.layout-top-right-h .assistant-content,
.layout-bottom-right-h .assistant-content {
justify-content: flex-end;
}
/* 横向布局 - 居中:内容居中对齐 */
.layout-top-center-h .assistant-content,
.layout-bottom-center-h .assistant-content {
justify-content: center;
}
/* 竖向布局 - 顶部 (column):内容顶对齐 */
.layout-top-left-v .assistant-content,
.layout-top-right-v .assistant-content {
justify-content: flex-start;
}
/* 竖向布局 - 底部:内容底对齐 */
/* .assistant-content 使用 column 方向,flex-end 是底部 */
.layout-bottom-left-v .assistant-content,
.layout-bottom-right-v .assistant-content {
justify-content: flex-end;
}
/* 竖向布局 - 垂直居中:内容居中对齐 */
.layout-left-center-v .assistant-content,
.layout-right-center-v .assistant-content {
justify-content: center;
}
/* SVG 图标通用样式 */
.svg-icon {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
position: relative;
z-index: 1;
}
.svg-icon svg {
width: 100%;
height: 100%;
fill: currentColor;
color: inherit;
transition: all 0.2s;
vertical-align: middle;
}
/* ==========================================================================
4. 按钮样式 (Buttons)
========================================================================== */
/* 按钮基础样式 */
.prompt-assistant-button,
.image-assistant-button {
display: inline-flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
padding: 0;
margin: 2px;
border: none;
border-radius: 3px;
background-color: transparent;
color: var(--p-dialog-color);
cursor: pointer;
opacity: 0;
flex-shrink: 0;
position: relative;
/* 递进动画:基于按钮索引计算延迟 */
--stagger-delay: calc(var(--button-index, 0) * 30ms);
transition: transform 0.15s,
opacity 0.8s cubic-bezier(0.25, 1, 0.5, 1) var(--stagger-delay),
background-color 0.2s;
}
/* 按钮图标调整 */
.prompt-assistant-button .svg-icon,
.image-assistant-button .svg-icon {
width: 18px;
height: 18px;
margin: 0;
}
/* 按钮交互状态 */
.prompt-assistant-button:hover,
.image-assistant-button:hover {
opacity: 1;
transform: scale(1.15);
background-color: rgba(255, 255, 255, 0.1);
box-shadow: 0 0 5px rgba(255, 255, 255, 0.2);
}
.prompt-assistant-button:active,
.image-assistant-button:active {
transform: scale(0.95);
}
/* 激活状态 */
.button-active {
opacity: 1;
transform: scale(1.15);
background-color: rgba(255, 255, 255, 0.1);
box-shadow: 0 0 5px rgba(255, 255, 255, 0.2);
color: var(--p-listbox-option-selected-color);
}
/* 处理中状态 */
.button-processing {
background-color: rgba(100, 100, 255, 0.15) !important;
opacity: 1 !important;
position: relative;
z-index: 1;
animation: buttonBreathing 1.5s infinite ease-in-out;
}
/* 禁用状态 */
.button-disabled {
opacity: 0.4 !important;
filter: grayscale(60%);
cursor: not-allowed !important;
pointer-events: none;
transform: none !important;
color: var(--p-text-muted-color);
}
.button-disabled:hover {
background-color: transparent !important;
box-shadow: none !important;
}
/* 折叠状态下隐藏按钮 (防止残留交互) */
.assistant-container-common.collapsed .prompt-assistant-button,
.assistant-container-common.collapsed .image-assistant-button {
opacity: 0 !important;
pointer-events: none !important;
/* 折叠时立即隐藏,无延迟 */
transition-delay: 0s !important;
}
/* 展开状态下按钮递进显示 */
.assistant-container-common.expanded .prompt-assistant-button,
.assistant-container-common.expanded .image-assistant-button {
opacity: 0.8;
pointer-events: auto;
}
/* 分割线 - 横向布局时为竖线 */
.prompt-assistant-divider,
.image-assistant-divider {
width: 1px;
height: 10px;
background-color: var(--p-content-border-color);
margin: 0 2px;
align-self: center;
flex-shrink: 0;
border-radius: 0.5px;
}
/* 垂直布局时分割线变成横线(宽高互换) */
.assistant-content.flex-col .prompt-assistant-divider,
.assistant-content.flex-col .image-assistant-divider {
width: 10px;
height: 1px;
margin: 2px 0;
}
/* 解决 Sortable 拖动时脱离父容器的问题:使用直接类名标记 */
.prompt-assistant-divider.divider-horizontal,
.image-assistant-divider.divider-horizontal {
width: 10px;
height: 1px;
margin: 2px 0;
}
.assistant-container-common.collapsed .prompt-assistant-divider,
.assistant-container-common.collapsed .image-assistant-divider {
opacity: 0 !important;
}
/* ==========================================================================
5. 布局定位 (Anchor Positions)
========================================================================== */
/* 左上 */
.layout-top-left-h {
top: 4px;
left: 4px;
transform-origin: top left;
flex-direction: row;
justify-content: flex-start;
}
.layout-top-left-v {
top: 4px;
left: 4px;
transform-origin: top left;
flex-direction: column;
justify-content: flex-start;
}
/* 中上 */
.layout-top-center-h {
top: 4px;
left: 50%;
transform: translateX(-50%) scale(var(--assistant-scale, 1));
transform-origin: top center;
flex-direction: row;
justify-content: center;
}
/* 右上 */
.layout-top-right-h {
top: 4px;
right: 4px;
transform-origin: top right;
flex-direction: row;
justify-content: flex-end;
}
.layout-top-right-v {
top: 4px;
right: 4px;
transform-origin: top right;
flex-direction: column;
justify-content: flex-start;
}
/* 右中 */
.layout-right-center-v {
top: 50%;
right: 4px;
transform: translateY(-50%) scale(var(--assistant-scale, 1));
transform-origin: center right;
flex-direction: column;
justify-content: center;
}
/* 右下 */
.layout-bottom-right-h {
bottom: 4px;
right: 4px;
transform-origin: bottom right;
flex-direction: row;
justify-content: flex-end;
}
.layout-bottom-right-v {
bottom: 4px;
right: 4px;
transform-origin: bottom right;
flex-direction: column-reverse;
justify-content: flex-start;
}
/* 中下 */
.layout-bottom-center-h {
bottom: 4px;
left: 50%;
transform: translateX(-50%) scale(var(--assistant-scale, 1));
transform-origin: bottom center;
flex-direction: row;
justify-content: center;
}
/* 左下 */
.layout-bottom-left-h {
bottom: 4px;
left: 4px;
transform-origin: bottom left;
flex-direction: row;
justify-content: flex-start;
}
.layout-bottom-left-v {
bottom: 4px;
left: 4px;
transform-origin: bottom left;
flex-direction: column-reverse;
justify-content: flex-start;
}
/* 左中 */
.layout-left-center-v {
top: 50%;
left: 4px;
transform: translateY(-50%) scale(var(--assistant-scale, 1));
transform-origin: center left;
flex-direction: column;
justify-content: center;
}
/* 缩放支持 - 非居中布局使用,居中布局在各自类中单独设置 */
.assistant-container-common:not(.layout-top-center-h):not(.layout-bottom-center-h):not(.layout-left-center-v):not(.layout-right-center-v) {
transform: scale(var(--assistant-scale, 1));
}
/* ==========================================================================
6. 状态提示 (Status Tips)
========================================================================== */
.statustip {
position: absolute;
padding: 4px 8px;
border-radius: 8px;
font-size: 14px;
font-weight: bold;
letter-spacing: 0.5px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
white-space: nowrap;
z-index: 10000;
pointer-events: none;
backdrop-filter: blur(8px);
transform-origin: center bottom;
will-change: transform, opacity;
}
.statustip.success {
color: color-mix(in srgb, var(--p-inputtext-color), rgb(18, 255, 18) 40%) !important;
background-color: color-mix(in srgb, var(--p-content-background), rgb(4, 58, 4) 30%);
}
.statustip.error {
color: color-mix(in srgb, var(--p-inputtext-color), rgb(255, 0, 0) 60%) !important;
background-color: color-mix(in srgb, var(--p-content-background), rgb(74, 12, 12) 30%);
}
.statustip.loading {
color: color-mix(in srgb, var(--p-inputtext-color), rgb(249, 255, 69) 30%) !important;
background-color: color-mix(in srgb, var(--p-content-background), rgb(114, 117, 22) 30%);
}
.statustip.info {
color: color-mix(in srgb, var(--p-inputtext-color), rgb(82, 70, 255) 60%) !important;
background-color: color-mix(in srgb, var(--p-content-background), rgb(55, 8, 113) 30%);
}
/* 状态提示动画类 */
.statustip-show {
animation: tipScaleIn 0.1s ease-out forwards !important;
}
.statustip-hide {
animation: tipFloatUp 0.4s ease-out forwards !important;
}
/* ==========================================================================
7. Sortable 拖拽样式
========================================================================== */
.sortable-ghost {
opacity: 0.4;
background: rgba(255, 255, 255, 0.2);
}
/* ==========================================================================
8. Vue Node 2.0 模式适配
========================================================================== */
/* 强制覆盖定位 */
.vue-node-mode.assistant-container-common {
position: absolute !important;
}
/* Vue组件内位置微调 */
[data-node-id] .assistant-container-common.prompt-assistant-container {
right: 4px;
bottom: 4px;
z-index: 10;
}
[data-node-id] .assistant-container-common.image-assistant-container {
left: 6px;
bottom: 6px;
z-index: 10;
transform: none;
/* Vue模式下不需要画布缩放 */
}
/* 确保FloatLabel容器定位上下文 */
.p-floatlabel:has(.assistant-container-common),
[class*="float"]:has(.assistant-container-common) {
position: relative;
}
/* 确保按钮在Vue模式下可点击 */
.vue-node-mode .prompt-assistant-button,
.vue-node-mode .image-assistant-button {
pointer-events: auto;
}
/* 确保按钮在Vue模式下可点击 */
.vue-node-mode .prompt-assistant-button,
.vue-node-mode .image-assistant-button {
pointer-events: auto;
}
/* ==========================================================================
9. 动画关键帧 (Animations)
========================================================================== */
/* 指示器入场动画 - 从小到大、淡入 */
@keyframes indicatorAppear {
0% {
opacity: 0;
transform: scale(0.3);
}
60% {
transform: scale(1.1);
}
100% {
opacity: var(--assistant-icon-opacity, 0.8);
transform: scale(1);
}
}
/* 指示器初始化 - 触发入场动画 */
.assistant-indicator.indicator-init {
animation: indicatorAppear 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}