mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
style(vscode-ide-companion/ui): improve component styling and layout
This commit is contained in:
@@ -20,7 +20,7 @@ export const InterruptedMessage: React.FC<InterruptedMessageProps> = ({
|
|||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
alignItems: 'flex-start',
|
alignItems: 'flex-start',
|
||||||
paddingLeft: '30px', // keep alignment with other assistant messages, but no status icon
|
paddingLeft: '10px', // keep alignment with other assistant messages, but no status icon
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
paddingTop: '8px',
|
paddingTop: '8px',
|
||||||
paddingBottom: '8px',
|
paddingBottom: '8px',
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ const parseTodoEntries = (textOutputs: string[]): TodoEntry[] => {
|
|||||||
const lines = text.split(/\r?\n/);
|
const lines = text.split(/\r?\n/);
|
||||||
const entries: TodoEntry[] = [];
|
const entries: TodoEntry[] = [];
|
||||||
|
|
||||||
const todoRe = /^(?:\s*(?:[-*]|\d+[.)])\s*)?\[( |x|X|-)\]\s+(.*)$/;
|
// Accept [ ], [x]/[X] and in-progress markers [-] or [*]
|
||||||
|
const todoRe = /^(?:\s*(?:[-*]|\d+[.)])\s*)?\[( |x|X|-|\*)\]\s+(.*)$/;
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
const m = line.match(todoRe);
|
const m = line.match(todoRe);
|
||||||
if (m) {
|
if (m) {
|
||||||
@@ -51,7 +52,7 @@ const parseTodoEntries = (textOutputs: string[]): TodoEntry[] => {
|
|||||||
const status: EntryStatus =
|
const status: EntryStatus =
|
||||||
mark === 'x' || mark === 'X'
|
mark === 'x' || mark === 'X'
|
||||||
? 'completed'
|
? 'completed'
|
||||||
: mark === '-'
|
: mark === '-' || mark === '*'
|
||||||
? 'in_progress'
|
? 'in_progress'
|
||||||
: 'pending';
|
: 'pending';
|
||||||
if (title) {
|
if (title) {
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ const parsePlanEntries = (textOutputs: string[]): PlanEntry[] => {
|
|||||||
const lines = text.split(/\r?\n/);
|
const lines = text.split(/\r?\n/);
|
||||||
const entries: PlanEntry[] = [];
|
const entries: PlanEntry[] = [];
|
||||||
|
|
||||||
const todoRe = /^(?:\s*(?:[-*]|\d+[.)])\s*)?\[( |x|X|-)\]\s+(.*)$/;
|
// Accept [ ], [x]/[X] and in-progress markers [-] or [*]
|
||||||
|
const todoRe = /^(?:\s*(?:[-*]|\d+[.)])\s*)?\[( |x|X|-|\*)\]\s+(.*)$/;
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
const m = line.match(todoRe);
|
const m = line.match(todoRe);
|
||||||
if (m) {
|
if (m) {
|
||||||
@@ -51,7 +52,7 @@ const parsePlanEntries = (textOutputs: string[]): PlanEntry[] => {
|
|||||||
const status: EntryStatus =
|
const status: EntryStatus =
|
||||||
mark === 'x' || mark === 'X'
|
mark === 'x' || mark === 'X'
|
||||||
? 'completed'
|
? 'completed'
|
||||||
: mark === '-'
|
: mark === '-' || mark === '*'
|
||||||
? 'in_progress'
|
? 'in_progress'
|
||||||
: 'pending';
|
: 'pending';
|
||||||
if (title) {
|
if (title) {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const CheckboxDisplay: React.FC<CheckboxDisplayProps> = ({
|
|||||||
// Pseudo-elements do not reliably render on <input> in Chromium (VS Code webviews),
|
// Pseudo-elements do not reliably render on <input> in Chromium (VS Code webviews),
|
||||||
// which caused the missing icon. This version is font-free and uses borders.
|
// which caused the missing icon. This version is font-free and uses borders.
|
||||||
const showCheck = !!checked && !indeterminate;
|
const showCheck = !!checked && !indeterminate;
|
||||||
const showDash = !!indeterminate;
|
const showInProgress = !!indeterminate;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
@@ -66,16 +66,18 @@ export const CheckboxDisplay: React.FC<CheckboxDisplayProps> = ({
|
|||||||
].join(' ')}
|
].join(' ')}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{showDash ? (
|
{showInProgress ? (
|
||||||
<span
|
<span
|
||||||
aria-hidden
|
aria-hidden
|
||||||
className={[
|
className={[
|
||||||
'absolute block',
|
'absolute inline-block',
|
||||||
'left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',
|
'left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',
|
||||||
'w-2 h-[2px] rounded-sm',
|
// Use a literal star; no icon font needed
|
||||||
'bg-[#e1c08d]',
|
'text-[11px] leading-none text-[#e1c08d] select-none',
|
||||||
].join(' ')}
|
].join(' ')}
|
||||||
/>
|
>
|
||||||
|
*
|
||||||
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
=========================== */
|
=========================== */
|
||||||
:root {
|
:root {
|
||||||
/* Qwen Brand Colors */
|
/* Qwen Brand Colors */
|
||||||
--app-qwen-orange: #615fff;
|
--app-qwen-theme: #615fff;
|
||||||
--app-qwen-clay-button-orange: #4f46e5;
|
--app-qwen-clay-button-orange: #4f46e5;
|
||||||
--app-qwen-ivory: #f5f5ff;
|
--app-qwen-ivory: #f5f5ff;
|
||||||
--app-qwen-slate: #141420;
|
--app-qwen-slate: #141420;
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
--app-input-placeholder-foreground: var(--vscode-input-placeholderForeground);
|
--app-input-placeholder-foreground: var(--vscode-input-placeholderForeground);
|
||||||
--app-input-secondary-background: var(--vscode-menu-background);
|
--app-input-secondary-background: var(--vscode-menu-background);
|
||||||
/* Input Highlight (focus ring/border) */
|
/* Input Highlight (focus ring/border) */
|
||||||
--app-input-highlight: var(--app-qwen-orange);
|
--app-input-highlight: var(--app-qwen-theme);
|
||||||
|
|
||||||
/* Code Highlighting */
|
/* Code Highlighting */
|
||||||
--app-code-background: var(--vscode-textCodeBlock-background, rgba(0, 0, 0, 0.05));
|
--app-code-background: var(--vscode-textCodeBlock-background, rgba(0, 0, 0, 0.05));
|
||||||
@@ -211,7 +211,7 @@ button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.input-field:focus {
|
.input-field:focus {
|
||||||
border-color: var(--app-qwen-orange);
|
border-color: var(--app-qwen-theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-field:disabled {
|
.input-field:disabled {
|
||||||
@@ -355,7 +355,7 @@ button {
|
|||||||
=========================== */
|
=========================== */
|
||||||
.permission-request-card {
|
.permission-request-card {
|
||||||
background: var(--app-input-background);
|
background: var(--app-input-background);
|
||||||
border: 1px solid var(--app-qwen-orange);
|
border: 1px solid var(--app-qwen-theme);
|
||||||
border-radius: var(--corner-radius-medium);
|
border-radius: var(--corner-radius-medium);
|
||||||
margin: var(--app-spacing-medium) 0;
|
margin: var(--app-spacing-medium) 0;
|
||||||
margin-bottom: var(--app-spacing-xlarge);
|
margin-bottom: var(--app-spacing-xlarge);
|
||||||
@@ -500,18 +500,10 @@ button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.permission-option.selected {
|
.permission-option.selected {
|
||||||
border-color: var(--app-qwen-orange);
|
border-color: var(--app-qwen-theme);
|
||||||
background: rgba(97, 95, 255, 0.1);
|
background: rgba(97, 95, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.permission-option.allow {
|
|
||||||
/* Allow options */
|
|
||||||
}
|
|
||||||
|
|
||||||
.permission-option.reject {
|
|
||||||
/* Reject options */
|
|
||||||
}
|
|
||||||
|
|
||||||
.permission-radio {
|
.permission-radio {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
@@ -540,7 +532,7 @@ button {
|
|||||||
|
|
||||||
.permission-option.selected .permission-option-number {
|
.permission-option.selected .permission-option-number {
|
||||||
color: var(--app-qwen-ivory);
|
color: var(--app-qwen-ivory);
|
||||||
background-color: var(--app-qwen-orange);
|
background-color: var(--app-qwen-theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
.permission-always-badge {
|
.permission-always-badge {
|
||||||
|
|||||||
@@ -51,7 +51,8 @@
|
|||||||
.composer-form:focus-within {
|
.composer-form:focus-within {
|
||||||
/* match existing highlight behavior */
|
/* match existing highlight behavior */
|
||||||
border-color: var(--app-input-highlight);
|
border-color: var(--app-input-highlight);
|
||||||
box-shadow: 0 1px 2px color-mix(in srgb, var(--app-input-highlight), transparent 80%);
|
box-shadow: 0 1px 2px
|
||||||
|
color-mix(in srgb, var(--app-input-highlight), transparent 80%);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Composer: input editable area */
|
/* Composer: input editable area */
|
||||||
@@ -62,7 +63,11 @@
|
|||||||
font-size: var(--vscode-chat-font-size, 13px);
|
font-size: var(--vscode-chat-font-size, 13px);
|
||||||
color: var(--app-input-foreground);
|
color: var(--app-input-foreground);
|
||||||
}
|
}
|
||||||
.composer-input:empty:before {
|
/* Show placeholder when truly empty OR when flagged as empty via data attribute.
|
||||||
|
The data attribute is needed because some browsers insert a <br> in
|
||||||
|
contentEditable, which breaks :empty matching. */
|
||||||
|
.composer-input:empty:before,
|
||||||
|
.composer-input[data-empty='true']::before {
|
||||||
content: attr(data-placeholder);
|
content: attr(data-placeholder);
|
||||||
color: var(--app-input-placeholder-foreground);
|
color: var(--app-input-placeholder-foreground);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
@@ -76,7 +81,7 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
.composer-input:disabled,
|
.composer-input:disabled,
|
||||||
.composer-input[contenteditable="false"] {
|
.composer-input[contenteditable='false'] {
|
||||||
color: #999;
|
color: #999;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
@@ -105,7 +110,8 @@
|
|||||||
filter: brightness(1.1);
|
filter: brightness(1.1);
|
||||||
}
|
}
|
||||||
.btn-text-compact > svg {
|
.btn-text-compact > svg {
|
||||||
height: 1em; /* match font size */
|
height: 1em;
|
||||||
|
width: 1em;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
.btn-text-compact > span {
|
.btn-text-compact > span {
|
||||||
@@ -119,7 +125,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 300px) {
|
@media screen and (max-width: 300px) {
|
||||||
.btn-text-compact > svg { display: none; }
|
.btn-text-compact > svg {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Icon-only button, compact square (26x26) */
|
/* Icon-only button, compact square (26x26) */
|
||||||
@@ -173,3 +181,16 @@
|
|||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===========================
|
||||||
|
Utilities
|
||||||
|
=========================== */
|
||||||
|
@layer utilities {
|
||||||
|
/* Multi-line clamp with ellipsis (Chromium-based webview supported) */
|
||||||
|
.q-line-clamp-3 {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 3;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user