Skip to content

Commit 6bf2aa4

Browse files
秦奇qwencoder
andcommitted
fix(tui): address review findings for spacing PR
- Add useIsScreenReaderEnabled() guard in UserMessage to skip decorative half-block characters for screen reader users - Add width <= 0 guard to prevent RangeError on narrow terminals - Remove unused HalfLinePaddedBox component (dead code) - Cache supportsTrueColor() result at module scope - Add unit tests for interpolateColor, subtleBandColor, supportsTrueColor Generated with AI Co-authored-by: Qwen-Coder <[email protected]>
1 parent 6ab88a3 commit 6bf2aa4

4 files changed

Lines changed: 86 additions & 106 deletions

File tree

packages/cli/src/ui/components/messages/ConversationMessages.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import type React from 'react';
8-
import { Box, Text } from 'ink';
8+
import { Box, Text, useIsScreenReaderEnabled } from 'ink';
99
import stringWidth from 'string-width';
1010
import {
1111
MarkdownDisplay,
@@ -192,6 +192,8 @@ const ContinuationMarkdownMessage: React.FC<
192192
};
193193

194194
export const UserMessage: React.FC<UserMessageProps> = ({ text, width }) => {
195+
const isScreenReaderEnabled = useIsScreenReaderEnabled();
196+
195197
const fallback = (
196198
<PrefixedTextMessage
197199
text={text}
@@ -203,7 +205,12 @@ export const UserMessage: React.FC<UserMessageProps> = ({ text, width }) => {
203205
/>
204206
);
205207

206-
if (width === undefined || !supportsTrueColor()) {
208+
if (
209+
width === undefined ||
210+
width <= 0 ||
211+
isScreenReaderEnabled ||
212+
!supportsTrueColor()
213+
) {
207214
return fallback;
208215
}
209216

@@ -221,8 +228,8 @@ export const UserMessage: React.FC<UserMessageProps> = ({ text, width }) => {
221228
<Text color={bandColor}>{'▄'.repeat(width)}</Text>
222229
{lines.map((line, i) => {
223230
const linePrefix = i === 0 ? prefix : ' ';
224-
const contentWidth = stringWidth(linePrefix + line);
225-
const pad = Math.max(0, width - contentWidth);
231+
const lineWidth = stringWidth(linePrefix + line);
232+
const pad = Math.max(0, width - lineWidth);
226233
return (
227234
<Text
228235
key={i}

packages/cli/src/ui/components/shared/HalfLinePaddedBox.tsx

Lines changed: 0 additions & 98 deletions
This file was deleted.

packages/cli/src/ui/themes/color-utils.test.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
import { describe, it, expect } from 'vitest';
88
import {
9+
interpolateColor,
10+
subtleBandColor,
11+
supportsTrueColor,
912
isValidColor,
1013
resolveColor,
1114
CSS_NAME_TO_HEX_MAP,
@@ -218,4 +221,69 @@ describe('Color Utils', () => {
218221
}
219222
});
220223
});
224+
225+
describe('interpolateColor', () => {
226+
it('returns color1 when factor <= 0', () => {
227+
expect(interpolateColor('#000000', '#ffffff', 0)).toBe('#000000');
228+
expect(interpolateColor('#000000', '#ffffff', -1)).toBe('#000000');
229+
});
230+
231+
it('returns color2 when factor >= 1', () => {
232+
expect(interpolateColor('#000000', '#ffffff', 1)).toBe('#ffffff');
233+
expect(interpolateColor('#000000', '#ffffff', 2)).toBe('#ffffff');
234+
});
235+
236+
it('blends two hex colors at 50%', () => {
237+
expect(interpolateColor('#000000', '#ffffff', 0.5)).toBe('#808080');
238+
});
239+
240+
it('blends with a small factor', () => {
241+
const result = interpolateColor('#000000', '#ffffff', 0.06);
242+
expect(result).toMatch(/^#[0-9a-f]{6}$/);
243+
expect(result).not.toBe('#000000');
244+
});
245+
246+
it('handles 3-digit hex shorthand', () => {
247+
expect(interpolateColor('#000', '#fff', 0.5)).toBe('#808080');
248+
});
249+
250+
it('handles Ink color names', () => {
251+
expect(interpolateColor('black', 'white', 0.5)).toBe('#808080');
252+
});
253+
254+
it('returns empty string for unparseable input', () => {
255+
expect(interpolateColor('notacolor', '#ffffff', 0.5)).toBe('');
256+
expect(interpolateColor('#ffffff', 'notacolor', 0.5)).toBe('');
257+
});
258+
});
259+
260+
describe('subtleBandColor', () => {
261+
it('shifts dark background toward white', () => {
262+
const result = subtleBandColor('#000000');
263+
expect(result).toMatch(/^#[0-9a-f]{6}$/);
264+
expect(result).not.toBe('#000000');
265+
const r = parseInt(result.slice(1, 3), 16);
266+
expect(r).toBeGreaterThan(0);
267+
expect(r).toBeLessThan(30);
268+
});
269+
270+
it('shifts light background toward black', () => {
271+
const result = subtleBandColor('#ffffff');
272+
expect(result).toMatch(/^#[0-9a-f]{6}$/);
273+
expect(result).not.toBe('#ffffff');
274+
const r = parseInt(result.slice(1, 3), 16);
275+
expect(r).toBeGreaterThan(225);
276+
expect(r).toBeLessThan(255);
277+
});
278+
279+
it('returns empty string for unparseable input', () => {
280+
expect(subtleBandColor('notacolor')).toBe('');
281+
});
282+
});
283+
284+
describe('supportsTrueColor', () => {
285+
it('returns a boolean', () => {
286+
expect(typeof supportsTrueColor()).toBe('boolean');
287+
});
288+
});
221289
});

packages/cli/src/ui/themes/color-utils.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,19 +328,22 @@ export function subtleBandColor(bgColor: string, factor = 0.06): string {
328328

329329
/**
330330
* Detects whether the terminal supports 24-bit (true) color, required for the
331-
* blended half-line background band.
331+
* blended half-line background band. Result is cached at module scope since
332+
* terminal color capability does not change during the process lifetime.
332333
*/
334+
let _supportsTrueColor: boolean | undefined;
333335
export function supportsTrueColor(): boolean {
336+
if (_supportsTrueColor !== undefined) return _supportsTrueColor;
334337
const colorterm = process.env['COLORTERM'];
335338
if (
336339
colorterm === 'truecolor' ||
337340
colorterm === '24bit' ||
338341
colorterm === 'kmscon'
339342
) {
340-
return true;
343+
return (_supportsTrueColor = true);
341344
}
342345
if (process.stdout.getColorDepth && process.stdout.getColorDepth() >= 24) {
343-
return true;
346+
return (_supportsTrueColor = true);
344347
}
345-
return false;
348+
return (_supportsTrueColor = false);
346349
}

0 commit comments

Comments
 (0)