Files
page-agent/packages/ui/src/Panel.module.css

598 lines
11 KiB
CSS

.wrapper {
position: fixed;
bottom: 100px;
left: 50%;
transform: translateX(-50%) translateY(20px);
opacity: 0;
z-index: 2147483642; /* 比 SimulatorMask 高一层 */
box-sizing: border-box;
overflow: visible;
* {
box-sizing: border-box;
}
--width: 360px;
--height: 40px;
--border-radius: 12px;
--side-space: 12px; /* 控制栏两侧的间距 */
--history-width: calc(var(--width) - var(--side-space) * 2);
--color-1: rgb(57, 182, 255);
--color-2: rgb(189, 69, 251);
--color-3: rgb(255, 87, 51);
--color-4: rgb(255, 214, 0);
width: var(--width);
height: var(--height);
transition: all 0.3s ease-in-out;
/* 响应式设计 */
@media (max-width: 480px) {
width: calc(100vw - 40px);
--width: calc(100vw - 40px);
}
.background {
position: absolute;
inset: -2px -8px;
border-radius: calc(var(--border-radius) + 4px);
filter: blur(16px);
overflow: hidden;
/* mix-blend-mode: lighten; */
/* display: none; */
&::before {
content: '';
z-index: -1;
pointer-events: none;
position: absolute;
width: 100%;
height: 100%;
/* left: -100%; */
left: 0;
top: 0;
background-image: linear-gradient(
to bottom left,
var(--color-1),
var(--color-2),
var(--color-1)
);
animation: mask-running 2s linear infinite;
}
&::after {
content: '';
z-index: -1;
pointer-events: none;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-image: linear-gradient(
to bottom left,
var(--color-2),
var(--color-1),
var(--color-2)
);
animation: mask-running 2s linear infinite;
animation-delay: 1s;
}
}
}
@keyframes mask-running {
from {
transform: translateX(-100%);
}
to {
transform: translateX(100%);
}
}
/* 控制栏 */
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 12px;
user-select: none;
position: absolute;
inset: 0;
cursor: pointer;
flex-shrink: 0; /* 防止 header 被压缩 */
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(10px);
border-radius: var(--border-radius);
background-clip: padding-box;
box-shadow:
0 0 0px 2px rgba(255, 255, 255, 0.4),
0 0 5px 1px rgba(255, 255, 255, 0.3);
.statusSection {
display: flex;
align-items: center;
gap: 8px;
flex: 1;
min-height: 24px; /* 确保垂直居中 */
.indicator {
width: 6px;
height: 6px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.5);
flex-shrink: 0;
animation: none; /* 默认无动画 */
/* 运行状态 - 有动画 */
&.thinking {
background: rgb(57, 182, 255);
animation: pulse 0.8s ease-in-out infinite;
}
&.tool_executing {
background: rgb(189, 69, 251);
animation: pulse 0.6s ease-in-out infinite;
}
&.retry {
background: rgb(255, 214, 0);
animation: retryPulse 1s ease-in-out infinite;
}
/* 静止状态 - 无动画 */
&.completed,
&.input,
&.output {
background: rgb(34, 197, 94);
animation: none;
}
&.error {
background: rgb(239, 68, 68);
animation: none;
}
}
.statusText {
color: white;
font-size: 12px;
line-height: 1;
font-weight: 500;
transition: all 0.3s ease-in-out;
position: relative;
overflow: hidden;
display: flex;
align-items: center;
min-height: 24px; /* 确保垂直居中 */
&.fadeOut {
animation: statusTextFadeOut 0.3s ease forwards;
}
&.fadeIn {
animation: statusTextFadeIn 0.3s ease forwards;
}
}
}
.controls {
display: flex;
align-items: center;
gap: 4px;
.controlButton {
width: 24px;
height: 24px;
border: none;
border-radius: 4px;
background: rgba(255, 255, 255, 0.1);
color: white;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
line-height: 1;
&:hover {
background: rgba(255, 255, 255, 0.2);
}
}
.pauseButton {
font-weight: 600;
&.paused {
background: rgba(34, 197, 94, 0.2); /* 绿色背景表示可以继续 */
color: rgb(34, 197, 94);
&:hover {
background: rgba(34, 197, 94, 0.3);
}
}
}
.stopButton {
background: rgba(239, 68, 68, 0.2);
color: rgb(255, 41, 41);
font-weight: 600;
&:hover {
background: rgba(239, 68, 68, 0.3);
}
}
}
}
@keyframes statusTextFadeIn {
0% {
opacity: 0;
transform: translateY(5px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
@keyframes statusTextFadeOut {
0% {
opacity: 1;
transform: translateY(0);
}
100% {
opacity: 0;
transform: translateY(-5px);
}
}
.historySectionWrapper {
position: absolute;
width: var(--history-width);
bottom: var(--height);
left: var(--side-space);
z-index: -2;
padding-top: 0px;
visibility: collapse;
overflow: hidden;
transition: all 0.2s;
background: rgba(2, 0, 20, 0.5);
/* background: rgba(186, 186, 186, 0.2); */
backdrop-filter: blur(10px);
text-shadow: 0 0 1px rgba(0, 0, 0, 0.2);
border-top-left-radius: calc(var(--border-radius) + 4px);
border-top-right-radius: calc(var(--border-radius) + 4px);
/* border: 2px solid rgba(255, 255, 255, 0.8); */
border: 2px solid rgba(255, 255, 255, 0.4);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6);
/* @media (prefers-color-scheme: dark) {
box-shadow:
0 8px 32px 0 rgba(0, 0, 0, 0.85),
0 2px 12px 0 rgba(57, 182, 255, 0.1);
} */
.expanded & {
padding-top: 8px;
visibility: visible;
}
.historySection {
position: relative;
overflow-y: auto;
overscroll-behavior: contain;
scrollbar-width: none;
max-height: 0;
padding-inline: 8px;
transition: max-height 0.2s;
.expanded & {
max-height: 400px;
}
.historyItem {
/* backdrop-filter: blur(10px); */
padding: 8px 10px;
margin-bottom: 6px;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.03));
border-radius: 8px;
border-left: 2px solid rgba(57, 182, 255, 0.5);
font-size: 12px;
color: white;
/* color: black; */
line-height: 1.3;
position: relative;
overflow: hidden;
/* 微妙的内阴影 */
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.1),
0 1px 3px rgba(0, 0, 0, 0.1);
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
}
&:hover {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.06));
/* transform: translateY(-1px); */
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.15),
0 2px 4px rgba(0, 0, 0, 0.15);
}
&:last-child {
margin-bottom: 10px;
}
&.completed,
&.input,
&.output {
border-left-color: rgb(34, 197, 94);
background: linear-gradient(135deg, rgba(34, 197, 94, 0.1), rgba(34, 197, 94, 0.05));
}
&.error {
border-left-color: rgb(239, 68, 68);
background: linear-gradient(135deg, rgba(239, 68, 68, 0.1), rgba(239, 68, 68, 0.05));
}
&.retry {
border-left-color: rgb(255, 214, 0);
background: linear-gradient(135deg, rgba(255, 214, 0, 0.1), rgba(255, 214, 0, 0.05));
}
/* 突出显示 done 成功结果 */
&.doneSuccess {
background: linear-gradient(
135deg,
rgba(34, 197, 94, 0.25),
rgba(34, 197, 94, 0.15),
rgba(34, 197, 94, 0.08)
);
border: none;
border-left: 4px solid rgb(34, 197, 94);
box-shadow:
0 4px 12px rgba(34, 197, 94, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.2),
0 0 20px rgba(34, 197, 94, 0.1);
font-weight: 600;
color: rgb(220, 252, 231);
padding: 10px 12px;
margin-bottom: 8px;
border-radius: 8px;
position: relative;
overflow: hidden;
&::before {
background: linear-gradient(90deg, transparent, rgba(34, 197, 94, 0.4), transparent);
}
&::after {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
animation: shimmer 2s ease-in-out infinite;
}
.historyContent {
.statusIcon {
font-size: 16px;
animation: celebrate 0.8s ease-in-out;
filter: drop-shadow(0 2px 4px rgba(34, 197, 94, 0.5));
}
}
}
/* 突出显示 done 失败结果 */
&.doneError {
background: linear-gradient(
135deg,
rgba(239, 68, 68, 0.25),
rgba(239, 68, 68, 0.15),
rgba(239, 68, 68, 0.08)
);
border: none;
border-left: 4px solid rgb(239, 68, 68);
box-shadow:
0 4px 12px rgba(239, 68, 68, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.2),
0 0 20px rgba(239, 68, 68, 0.1);
font-weight: 600;
color: rgb(254, 226, 226);
padding: 10px 12px;
margin-bottom: 8px;
border-radius: 8px;
position: relative;
overflow: hidden;
&::before {
background: linear-gradient(90deg, transparent, rgba(239, 68, 68, 0.4), transparent);
}
.historyContent {
.statusIcon {
font-size: 16px;
filter: drop-shadow(0 2px 4px rgba(239, 68, 68, 0.5));
}
}
}
.historyContent {
display: flex;
align-items: center;
gap: 8px;
word-break: break-all;
white-space: pre-wrap;
/* overflow-x: auto; */
.statusIcon {
font-size: 12px;
flex-shrink: 0;
line-height: 1;
transition: all 0.3s ease;
}
}
.historyMeta {
font-size: 10px;
color: rgba(255, 255, 255, 0.6);
/* color: rgb(61, 61, 61); */
margin-top: 8px;
line-height: 1;
}
}
}
}
/* 动画关键帧 - 更快的闪烁 */
@keyframes pulse {
0%,
100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.4;
transform: scale(1.3);
}
}
/* 重试动画 - 旋转脉冲 */
@keyframes retryPulse {
0%,
100% {
opacity: 1;
transform: scale(1) rotate(0deg);
}
25% {
opacity: 0.6;
transform: scale(1.2) rotate(90deg);
}
50% {
opacity: 0.8;
transform: scale(1.1) rotate(180deg);
}
75% {
opacity: 0.6;
transform: scale(1.2) rotate(270deg);
}
}
/* 庆祝动画 */
@keyframes celebrate {
0%,
100% {
transform: scale(1);
}
25% {
transform: scale(1.2) rotate(-5deg);
}
75% {
transform: scale(1.2) rotate(5deg);
}
}
/* done 卡片的光泽效果 */
@keyframes shimmer {
0% {
left: -100%;
}
100% {
left: 100%;
}
}
/* 输入区域样式 */
.inputSectionWrapper {
position: absolute;
width: var(--history-width);
top: var(--height);
left: var(--side-space);
z-index: -1;
visibility: visible;
overflow: hidden;
height: 48px;
transition: all 0.2s;
background: rgba(186, 186, 186, 0.2);
backdrop-filter: blur(10px);
border-bottom-left-radius: calc(var(--border-radius) + 4px);
border-bottom-right-radius: calc(var(--border-radius) + 4px);
border: 2px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 1px 16px rgba(0, 0, 0, 0.4);
&.hidden {
visibility: collapse;
height: 0;
}
.inputSection {
display: flex;
align-items: center;
gap: 4px;
padding: 8px 8px;
.taskInput {
flex: 1;
background: rgba(255, 255, 255, 0.4);
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 10px;
padding-inline: 10px;
color: rgb(20, 20, 20);
font-size: 12px;
height: 28px;
line-height: 1;
outline: none;
transition: all 0.2s ease;
/* text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); */
/* border-color: rgba(57, 182, 255, 0.3); */
&::placeholder {
color: rgb(53, 53, 53);
}
&:focus {
background: rgba(255, 255, 255, 0.8);
border-color: rgba(57, 182, 255, 0.6);
box-shadow: 0 0 0 2px rgba(57, 182, 255, 0.2);
}
}
}
}