Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 82 additions & 9 deletions web/src/index.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
/* ==========================================================================
* Kimi Code CLI Web UI - Design System
*
*
* Structure:
* 1) Tailwind & plugins
* 2) Custom variant (dark mode)
* 3) Design Tokens (CSS variables)
* 4) @theme inline: Token → Tailwind mapping
* 5) @layer base: Semantic HTML defaults
* 6) @layer components: Reusable UI patterns
* ========================================================================== */

/* 1. Tailwind & Plugins */
Expand Down Expand Up @@ -435,3 +426,85 @@ body {
opacity: 1 !important;
}
}

/* ==========================================================================
* 7. User Message Contrast Enhancement
* ========================================================================== */

/*
* High-contrast styling for user messages to improve visual distinction
* from assistant messages in conversation history.
*/

/* User message bubble styling */
.is-user [class*="rounded-2xl"][class*="bg-secondary"] {
background: linear-gradient(135deg,
oklch(0.55 0.15 250) 0%,
oklch(0.65 0.12 250) 100%
) !important;
color: white !important;
border: 1px solid oklch(0.5 0.15 250) !important;
box-shadow: 0 2px 8px rgba(37, 99, 235, 0.2) !important;
}

/* Ensure all text inside user message is white */
.is-user [class*="rounded-2xl"] * {
color: white !important;
}

/* Dark mode adjustments */
.dark .is-user [class*="rounded-2xl"][class*="bg-secondary"] {
background: linear-gradient(135deg,
oklch(0.6 0.18 250) 0%,
oklch(0.7 0.15 250) 100%
) !important;
border-color: oklch(0.55 0.18 250) !important;
box-shadow: 0 2px 12px rgba(37, 99, 235, 0.3) !important;
}

/* "You" label indicator - uses padding-top to preserve dynamic spacing */
.is-user {
position: relative;
padding-top: 20px;
}

.is-user::before {
content: "You";
position: absolute;
top: 0;
right: 12px;
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: oklch(0.55 0.15 250);
background: oklch(0.95 0.01 250 / 0.9);
padding: 2px 8px;
border-radius: 4px;
white-space: nowrap;
pointer-events: none;
z-index: 10;
border: 1px solid oklch(0.8 0.05 250);
}

.dark .is-user::before {
color: oklch(0.75 0.2 250);
background: oklch(0.2 0.02 250 / 0.9);
border-color: oklch(0.4 0.1 250);
}

/* Entrance animation */
@keyframes user-message-appear {
from {
opacity: 0;
transform: translateY(4px) scale(0.98);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}

.is-user {
animation: user-message-appear 200ms ease-out;
}
Comment on lines +508 to +510
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 User message entrance animation replays on every scroll in virtualized list

The CSS animation user-message-appear applied to .is-user replays every time a user message scrolls back into the viewport, causing a distracting visual flicker during normal scrolling.

Root Cause

The app uses react-virtuoso (web/src/features/chat/components/virtualized-message-list.tsx:26) for rendering the message list. Virtuoso unmounts DOM elements when they scroll out of the viewport and remounts them when they scroll back in. Each remount creates a fresh DOM element, which re-triggers the CSS animation.

At web/src/index.css:525-526, the animation is unconditionally applied to all .is-user elements:

.is-user {
  animation: user-message-appear 200ms ease-out;
}

This means every time a user scrolls up and then back down through a conversation, user messages will fade-in and scale-up as if they were newly sent. In a long conversation with many user messages, this creates a visually jarring experience where messages appear to "pop in" repeatedly.

Impact: Degraded user experience during scrolling in any conversation with user messages. The animation was intended only for newly sent messages but fires on every scroll-driven remount.

Prompt for agents
The animation should only play when a user message is first added to the conversation, not on every virtualized remount. Since this is a CSS-only change, the cleanest fix would be to remove the animation entirely (lines 514-527 of web/src/index.css), or alternatively, add a JS-driven approach: add a temporary class like `is-new` to the Message component when a message is first created, and only apply the animation to `.is-user.is-new`. The temporary class should be removed after the animation completes. This requires changes in both the CSS file and the virtualized-message-list.tsx component.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.