feat(webui): enhance ChatViewer and AssistantMessage with timeline positioning

- Update ChatViewer to calculate and pass timeline positions (isFirst/isLast) to messages
- Enhance AssistantMessage with timeline connector visualization
- Add storybook stories for AssistantMessage component
- Update SearchToolCall and LayoutComponents for improved UI consistency
- Export new adapters in main index file
- Add timeline styling to components

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
yiliang114 2026-01-20 21:33:49 +08:00
parent 1861557d15
commit df787fff64
12 changed files with 1287 additions and 328 deletions

View file

@ -7,7 +7,35 @@
* Pseudo-elements (::before) for bullet points and (::after) for timeline connectors
*/
/* Bullet point indicator using ::before pseudo-element */
/* Base assistant message styles */
.assistant-message-container {
position: relative;
padding-left: 30px;
padding-top: 8px;
padding-bottom: 8px;
transition: background-color 0.15s ease;
border-radius: 6px;
}
/* Hover effect */
.assistant-message-container:hover {
background-color: rgba(255, 255, 255, 0.02);
}
/* Light theme hover */
.light-theme .assistant-message-container:hover {
background-color: rgba(0, 0, 0, 0.02);
}
/*
* Timeline positioning calculation (same as ToolCallContainer):
* - Container padding-top: 8px
* - Bullet font-size: 10px, line-height ~10px
* - Bullet vertical center: 8px + 5px = 13px from top
* - Line left: 12px (centered under bullet at left: 8px + ~4px offset)
*/
/* Bullet point indicator - all states use same position */
.assistant-message-container.assistant-message-default::before,
.assistant-message-container.assistant-message-success::before,
.assistant-message-container.assistant-message-error::before,
@ -16,37 +44,66 @@
content: '\25cf';
position: absolute;
left: 8px;
padding-top: 2px;
top: 8px;
font-size: 10px;
line-height: 10px;
z-index: 1;
}
/* Default state - secondary foreground color */
/* Status colors */
.assistant-message-container.assistant-message-default::before {
color: var(--app-secondary-foreground);
}
/* Success state - green bullet (maps to .ge) */
.assistant-message-container.assistant-message-success::before {
color: #74c991;
}
/* Error state - red bullet (maps to .be) */
.assistant-message-container.assistant-message-error::before {
color: #c74e39;
}
/* Warning state - yellow/orange bullet (maps to .ue) */
.assistant-message-container.assistant-message-warning::before {
color: #e1c08d;
}
/* Loading state - static bullet (maps to .he) */
.assistant-message-container.assistant-message-loading::before {
color: var(--app-secondary-foreground);
background-color: var(--app-secondary-background);
animation: assistantPulse 1s linear infinite;
}
@keyframes assistantPulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
/* Timeline connector line - full height by default */
.assistant-message-container::after {
content: '';
position: absolute;
left: 12px;
top: 0;
bottom: 0;
width: 1px;
background-color: var(--app-primary-border-color, rgba(255, 255, 255, 0.15));
}
/* First item in sequence: connector starts from bullet center */
.assistant-message-container[data-first="true"]::after {
top: 13px;
}
/* Last item in sequence: connector ends at bullet center */
.assistant-message-container[data-last="true"]::after {
bottom: calc(100% - 13px);
}
/* Single item (both first and last): no connector */
.assistant-message-container[data-first="true"][data-last="true"]::after {
display: none;
}
/* Loading state doesn't show timeline */
.assistant-message-container.assistant-message-loading::after {
display: none;
}