+
+
{items.map(item => (
-
-
-
+
+
+
{item.content}
))}
- )}
+
)
})}
diff --git a/web/src/index.css b/web/src/index.css
index 4997e93..5f8339d 100644
--- a/web/src/index.css
+++ b/web/src/index.css
@@ -258,6 +258,60 @@ body {
.animate-fade-in { animation: fade-in 0.2s ease-out; }
.animate-scale-in { animation: scale-in 0.3s ease-out; }
+/* ============================================
+ TodoPanel animations
+ ============================================ */
+@keyframes todo-card-in {
+ from {
+ opacity: 0;
+ transform: scale(0.92) translateY(-8px);
+ }
+ to {
+ opacity: 1;
+ transform: scale(1) translateY(0);
+ }
+}
+
+@keyframes todo-item-in {
+ from {
+ opacity: 0;
+ transform: translateX(-6px);
+ max-height: 0;
+ }
+ to {
+ opacity: 1;
+ transform: translateX(0);
+ max-height: 40px;
+ }
+}
+
+@keyframes todo-ring-pulse {
+ 0%, 100% {
+ box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.4);
+ }
+ 50% {
+ box-shadow: 0 0 0 6px rgba(245, 158, 11, 0);
+ }
+}
+
+.animate-todo-card-in { animation: todo-card-in 0.25s cubic-bezier(0.34, 1.56, 0.64, 1); }
+.animate-todo-item-in { animation: todo-item-in 0.2s ease-out forwards; }
+.animate-todo-ring-pulse { animation: todo-ring-pulse 2s ease-in-out infinite; }
+
+/* 分组折叠内容展开/收起 */
+.todo-group-body {
+ overflow: hidden;
+ transition: max-height 0.25s ease, opacity 0.2s ease;
+}
+.todo-group-body-open {
+ max-height: 600px;
+ opacity: 1;
+}
+.todo-group-body-closed {
+ max-height: 0;
+ opacity: 0;
+}
+
@keyframes thinking-reveal {
from { max-height: 0; opacity: 0; }
to { max-height: 300px; opacity: 1; }