feat(ui): Semantic tokens refactor (#8087)

This commit is contained in:
Miguel Solorio
2025-09-10 10:57:07 -07:00
committed by GitHub
parent a3a0e981ee
commit b9b6fe1f73
57 changed files with 509 additions and 424 deletions
@@ -6,13 +6,13 @@
import React from 'react';
import { Text } from 'ink';
import { Colors } from '../colors.js';
import { theme } from '../semantic-colors.js';
import stringWidth from 'string-width';
// Constants for Markdown parsing
const BOLD_MARKER_LENGTH = 2; // For "**"
const ITALIC_MARKER_LENGTH = 1; // For "*" or "_"
const STRIKETHROUGH_MARKER_LENGTH = 2; // For "~~"
const STRIKETHROUGH_MARKER_LENGTH = 2; // For "~~")
const INLINE_CODE_MARKER_LENGTH = 1; // For "`"
const UNDERLINE_TAG_START_LENGTH = 3; // For "<u>"
const UNDERLINE_TAG_END_LENGTH = 4; // For "</u>"
@@ -24,7 +24,7 @@ interface RenderInlineProps {
const RenderInlineInternal: React.FC<RenderInlineProps> = ({ text }) => {
// Early return for plain text without markdown or URLs
if (!/[*_~`<[https?:]/.test(text)) {
return <Text>{text}</Text>;
return <Text color={theme.text.primary}>{text}</Text>;
}
const nodes: React.ReactNode[] = [];
@@ -96,7 +96,7 @@ const RenderInlineInternal: React.FC<RenderInlineProps> = ({ text }) => {
const codeMatch = fullMatch.match(/^(`+)(.+?)\1$/s);
if (codeMatch && codeMatch[2]) {
renderedNode = (
<Text key={key} color={Colors.AccentPurple}>
<Text key={key} color={theme.text.accent}>
{codeMatch[2]}
</Text>
);
@@ -113,7 +113,7 @@ const RenderInlineInternal: React.FC<RenderInlineProps> = ({ text }) => {
renderedNode = (
<Text key={key}>
{linkText}
<Text color={Colors.AccentBlue}> ({url})</Text>
<Text color={theme.text.link}> ({url})</Text>
</Text>
);
}
@@ -133,7 +133,7 @@ const RenderInlineInternal: React.FC<RenderInlineProps> = ({ text }) => {
);
} else if (fullMatch.match(/^https?:\/\//)) {
renderedNode = (
<Text key={key} color={Colors.AccentBlue}>
<Text key={key} color={theme.text.link}>
{fullMatch}
</Text>
);
@@ -168,6 +168,6 @@ export const getPlainTextLength = (text: string): number => {
.replace(/~~(.*?)~~/g, '$1')
.replace(/`(.*?)`/g, '$1')
.replace(/<u>(.*?)<\/u>/g, '$1')
.replace(/\[(.*?)\]\(.*?\)/g, '$1');
.replace(/.*\[(.*?)\]\(.*\)/g, '$1');
return stringWidth(cleanText);
};
+10 -8
View File
@@ -7,7 +7,7 @@
import React from 'react';
import { Text, Box } from 'ink';
import { EOL } from 'node:os';
import { Colors } from '../colors.js';
import { theme } from '../semantic-colors.js';
import { colorizeCode } from './CodeColorizer.js';
import { TableRenderer } from './TableRenderer.js';
import { RenderInline } from './InlineMarkdownRenderer.js';
@@ -174,14 +174,14 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({
switch (level) {
case 1:
headerNode = (
<Text bold color={Colors.AccentCyan}>
<Text bold color={theme.text.link}>
<RenderInline text={headerText} />
</Text>
);
break;
case 2:
headerNode = (
<Text bold color={Colors.AccentBlue}>
<Text bold color={theme.text.link}>
<RenderInline text={headerText} />
</Text>
);
@@ -195,14 +195,14 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({
break;
case 4:
headerNode = (
<Text italic color={Colors.Gray}>
<Text italic color={theme.text.secondary}>
<RenderInline text={headerText} />
</Text>
);
break;
default:
headerNode = (
<Text>
<Text color={theme.text.primary}>
<RenderInline text={headerText} />
</Text>
);
@@ -246,7 +246,7 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({
} else {
addContentBlock(
<Box key={key}>
<Text wrap="wrap">
<Text wrap="wrap" color={theme.text.primary}>
<RenderInline text={line} />
</Text>
</Box>,
@@ -315,7 +315,9 @@ const RenderCodeBlockInternal: React.FC<RenderCodeBlockProps> = ({
// Not enough space to even show the message meaningfully
return (
<Box paddingLeft={CODE_BLOCK_PREFIX_PADDING}>
<Text color={Colors.Gray}>... code is being written ...</Text>
<Text color={theme.text.secondary}>
... code is being written ...
</Text>
</Box>
);
}
@@ -331,7 +333,7 @@ const RenderCodeBlockInternal: React.FC<RenderCodeBlockProps> = ({
return (
<Box paddingLeft={CODE_BLOCK_PREFIX_PADDING} flexDirection="column">
{colorizedTruncatedCode}
<Text color={Colors.Gray}>... generating more ...</Text>
<Text color={theme.text.secondary}>... generating more ...</Text>
</Box>
);
}
+4 -4
View File
@@ -6,7 +6,7 @@
import React from 'react';
import { Text, Box } from 'ink';
import { Colors } from '../colors.js';
import { theme } from '../semantic-colors.js';
import { RenderInline, getPlainTextLength } from './InlineMarkdownRenderer.js';
interface TableRendererProps {
@@ -89,7 +89,7 @@ export const TableRenderer: React.FC<TableRendererProps> = ({
return (
<Text>
{isHeader ? (
<Text bold color={Colors.AccentCyan}>
<Text bold color={theme.text.link}>
<RenderInline text={cellContent} />
</Text>
) : (
@@ -112,7 +112,7 @@ export const TableRenderer: React.FC<TableRendererProps> = ({
const borderParts = adjustedWidths.map((w) => char.horizontal.repeat(w));
const border = char.left + borderParts.join(char.middle) + char.right;
return <Text>{border}</Text>;
return <Text color={theme.border.default}>{border}</Text>;
};
// Helper function to render a table row
@@ -123,7 +123,7 @@ export const TableRenderer: React.FC<TableRendererProps> = ({
});
return (
<Text>
<Text color={theme.text.primary}>
{' '}
{renderedCells.map((cell, index) => (
<React.Fragment key={index}>
+4 -4
View File
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import { Colors } from '../colors.js';
import { theme } from '../semantic-colors.js';
// --- Thresholds ---
export const TOOL_SUCCESS_RATE_HIGH = 95;
@@ -23,10 +23,10 @@ export const getStatusColor = (
options: { defaultColor?: string } = {},
) => {
if (value >= thresholds.green) {
return Colors.AccentGreen;
return theme.status.success;
}
if (value >= thresholds.yellow) {
return Colors.AccentYellow;
return theme.status.warning;
}
return options.defaultColor || Colors.AccentRed;
return options.defaultColor || theme.status.error;
};