wip(vscode-ide-companion): timelint

This commit is contained in:
yiliang114
2025-12-02 13:41:24 +08:00
parent 90fc53a9df
commit 2e449f4d45
11 changed files with 169 additions and 61 deletions

View File

@@ -477,7 +477,7 @@ export const App: React.FC = () => {
<div
ref={messagesContainerRef}
className="chat-messages flex-1 overflow-y-auto overflow-x-hidden pt-5 pr-5 pl-5 pb-[120px] flex flex-col relative min-w-0 focus:outline-none [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-white/20 [&::-webkit-scrollbar-thumb]:rounded-sm [&::-webkit-scrollbar-thumb:hover]:bg-white/30 [&>*]:flex [&>*]:gap-0 [&>*]:items-start [&>*]:text-left [&>*]:py-2 [&>*:not(:last-child)]:mb-[10px] [&>.message-item]:px-0 [&>.message-item]:py-0 [&>*]:flex-col [&>*]:relative [&>*]:animate-[fadeIn_0.2s_ease-in]"
className="chat-messages flex-1 overflow-y-auto overflow-x-hidden pt-5 pr-5 pl-5 pb-[120px] flex flex-col relative min-w-0 focus:outline-none [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-white/20 [&::-webkit-scrollbar-thumb]:rounded-sm [&::-webkit-scrollbar-thumb:hover]:bg-white/30 [&>*]:flex [&>*]:gap-0 [&>*]:items-start [&>*]:text-left [&>*]:py-2 [&>*:not(:last-child)]:pb-[10px] [&>.message-item]:px-0 [&>.message-item]:py-0 [&>*]:flex-col [&>*]:relative [&>*]:animate-[fadeIn_0.2s_ease-in]"
style={{ backgroundColor: 'var(--app-primary-background)' }}
>
{!hasContent ? (

View File

@@ -155,14 +155,7 @@ export const InProgressToolCall: React.FC<InProgressToolCallProps> = ({
return (
<div className="relative py-2 toolcall-container">
<div className="flex items-center gap-2 mb-1 relative">
{/* Pulsing bullet dot (Claude-style), vertically centered with header row */}
<span
aria-hidden
className="absolute -left-[20px] top-1/2 -translate-y-1/2 text-[10px] leading-none text-[#e1c08d] animate-[pulse_1.5s_ease-in-out_infinite]"
>
</span>
<div className="flex items-center gap-2 mb-1 relative before:content-['\25cf'] before:absolute before:left-[-22px] before:top-1/2 before:-translate-y-1/2 before:text-[10px] before:leading-none before:text-[#e1c08d] before:animate-pulse-slow">
<span className={`text-xs font-medium ${kindColorClass}`}>
{kindLabel}
</span>

View File

@@ -58,32 +58,3 @@
opacity: 0.5;
}
}
/* Timeline connector line using ::after pseudo-element */
/* Default: full height connector for middle items */
.assistant-message-container::after {
content: "";
position: absolute;
left: 12px;
top: 0;
bottom: 0;
width: 1px;
background-color: var(--app-primary-border-color);
opacity: 0.4;
z-index: 0;
}
/* First item: connector starts from bullet point position */
.assistant-message-container:first-child::after {
top: 12px; /* Start from around the bullet point position (8px padding + 4px offset) */
}
/* Last item: connector ends at bullet point position */
.assistant-message-container:last-child::after {
bottom: 12px; /* End at around the bullet point position */
}
/* First and last are the same item (single item): no connector */
.assistant-message-container:first-child:last-child::after {
content: none;
}

View File

@@ -7,6 +7,7 @@
import type React from 'react';
import { MessageContent } from '../MessageContent.js';
import './AssistantMessage.css';
import './SimpleTimeline.css';
interface AssistantMessageProps {
content: string;
@@ -55,7 +56,7 @@ export const AssistantMessage: React.FC<AssistantMessageProps> = ({
return (
<div
className={`assistant-message-container ${getStatusClass()}`}
className={`assistant-message-container simple-timeline-container ${getStatusClass()}`}
style={{
width: '100%',
alignItems: 'flex-start',

View File

@@ -0,0 +1,50 @@
/**
* @license
* Copyright 2025 Qwen Team
* SPDX-License-Identifier: Apache-2.0
*
* Simplified timeline styles for testing
*/
/* Basic timeline container */
.simple-timeline-container {
position: relative;
padding-left: 30px;
padding-top: 8px;
padding-bottom: 8px;
}
/* Timeline connector - simple version */
.simple-timeline-container::after {
content: '';
position: absolute;
left: 12px;
top: 0;
bottom: 0;
width: 1px;
background-color: var(--app-primary-border-color);
z-index: 1;
}
/* First item connector starts lower */
.simple-timeline-container:first-child::after {
top: 24px;
}
/* Last item connector ends higher */
.simple-timeline-container:last-child::after {
height: calc(100% - 24px);
top: 0;
bottom: auto;
}
/* Bullet point */
.simple-timeline-container::before {
content: '\25cf';
position: absolute;
left: 8px;
padding-top: 2px;
font-size: 10px;
color: var(--app-secondary-foreground);
z-index: 2;
}

View File

@@ -16,38 +16,33 @@
align-items: flex-start;
}
/* Timeline connector line using ::after pseudo-element */
/* Default: full height connector for middle items */
/* Default timeline connector line */
.toolcall-container::after {
content: "";
content: '';
position: absolute;
left: 12px;
top: 0;
bottom: 0;
width: 1px;
background-color: var(--app-primary-border-color);
opacity: 0.4;
z-index: 0;
z-index: 1;
}
/* First item: connector starts from bullet point position */
/* First item: connector starts from status point position */
.toolcall-container:first-child::after {
top: 12px; /* Start from around the bullet point position (8px padding + 4px offset) */
top: 24px;
}
/* Last item: connector ends at bullet point position */
/* Last item: connector shows only upper part */
.toolcall-container:last-child::after {
bottom: 12px; /* End at around the bullet point position */
}
/* First and last are the same item (single item): no connector */
.toolcall-container:first-child:last-child::after {
content: none;
height: calc(100% - 24px);
top: 0;
bottom: auto;
}
/* Status-specific styles using ::before pseudo-element for bullet points */
.toolcall-container.toolcall-status-default::before {
content: "\25cf";
content: '\25cf';
position: absolute;
left: 8px;
padding-top: 2px;
@@ -57,17 +52,16 @@
}
.toolcall-container.toolcall-status-success::before {
content: "\25cf";
content: '\25cf';
position: absolute;
left: 8px;
padding-top: 2px;
font-size: 10px;
color: #74c991;
z-index: 1;
}
.toolcall-container.toolcall-status-error::before {
content: "\25cf";
content: '\25cf';
position: absolute;
left: 8px;
padding-top: 2px;
@@ -77,7 +71,7 @@
}
.toolcall-container.toolcall-status-warning::before {
content: "\25cf";
content: '\25cf';
position: absolute;
left: 8px;
padding-top: 2px;
@@ -87,7 +81,7 @@
}
.toolcall-container.toolcall-status-loading::before {
content: "\25cf";
content: '\25cf';
position: absolute;
left: 8px;
padding-top: 2px;
@@ -158,4 +152,9 @@
flex-direction: column;
gap: 4px;
max-width: 100%;
}
}
/* Flex container with margin bottom */
.toolcall-header {
margin-bottom: 12px;
}

View File

@@ -10,6 +10,7 @@
import type React from 'react';
import { FileLink } from '../../ui/FileLink.js';
import './LayoutComponents.css';
import './SimpleTimeline.css';
/**
* Props for ToolCallContainer - Claude Code style layout
@@ -46,7 +47,7 @@ export const ToolCallContainer: React.FC<ToolCallContainerProps> = ({
>
{/* Timeline connector line using ::after pseudo-element */}
<div className="toolcall-content-wrapper flex flex-col gap-1 min-w-0 max-w-full">
<div className="flex items-center gap-2 relative min-w-0">
<div className="flex items-center gap-2 relative min-w-0 toolcall-header">
<span className="text-[14px] leading-none font-bold text-[var(--app-primary-foreground)]">
{label}
</span>

View File

@@ -0,0 +1,50 @@
/**
* @license
* Copyright 2025 Qwen Team
* SPDX-License-Identifier: Apache-2.0
*
* Simplified timeline styles for tool calls
*/
/* Basic timeline container */
.simple-toolcall-container {
position: relative;
padding-left: 30px;
padding-top: 8px;
padding-bottom: 8px;
}
/* Timeline connector - simple version */
.simple-toolcall-container::after {
content: '';
position: absolute;
left: 12px;
top: 0;
bottom: 0;
width: 1px;
background-color: var(--app-primary-border-color);
z-index: 1;
}
/* First item connector starts lower */
.simple-toolcall-container:first-child::after {
top: 24px;
}
/* Last item connector ends higher */
.simple-toolcall-container:last-child::after {
height: calc(100% - 24px);
top: 0;
bottom: auto;
}
/* Bullet point */
.simple-toolcall-container::before {
content: '\25cf';
position: absolute;
left: 8px;
padding-top: 2px;
font-size: 10px;
color: var(--app-secondary-foreground);
z-index: 2;
}

View File

@@ -12,6 +12,8 @@
@import '../components/PlanDisplay.css';
@import '../components/toolcalls/shared/DiffDisplay.css';
@import '../components/messages/AssistantMessage.css';
@import '../components/messages/SimpleTimeline.css';
@import '../components/toolcalls/shared/SimpleTimeline.css';
/* ===========================

View File

@@ -0,0 +1,35 @@
/**
* @license
* Copyright 2025 Qwen Team
* SPDX-License-Identifier: Apache-2.0
*
* CSS Selector Compatibility Test
*/
/* Test 1: Basic first-child and last-child selectors */
.test-container:first-child::after {
content: "FIRST";
color: red;
}
.test-container:last-child::after {
content: "LAST";
color: blue;
}
.test-container:first-child:last-child::after {
content: "ONLY";
color: green;
}
/* Test 2: Simple sibling selectors */
.test-container + .test-container::before {
content: "SIBLING";
color: orange;
}
/* Test 3: Not selector */
.test-container:not(.special)::after {
content: "NOT SPECIAL";
color: purple;
}

View File

@@ -29,9 +29,15 @@ export default {
'0%': { opacity: '0', transform: 'translateY(4px)' },
'100%': { opacity: '1', transform: 'translateY(0)' },
},
// Pulse animation for in-progress tool calls
'pulse-slow': {
'0%, 100%': { opacity: '1' },
'50%': { opacity: '0.5' },
},
},
animation: {
'completion-menu-enter': 'completion-menu-enter 150ms ease-out both',
'pulse-slow': 'pulse-slow 1.5s ease-in-out infinite',
},
colors: {
qwen: {