feat: add streaming state to markdown quick actions

- Pass isStreaming prop through message components to disable actions during streaming
- Improve action button styling with icons and better spacing
- Disable buttons while streaming to prevent concurrent actions
This commit is contained in:
KevIsDev 2025-05-26 17:57:10 +01:00
parent 74605e96e3
commit de0a41b5f1
3 changed files with 30 additions and 5 deletions

View File

@ -16,6 +16,7 @@ interface AssistantMessageProps {
append?: (message: Message) => void;
chatMode?: 'discuss' | 'build';
setChatMode?: (mode: 'discuss' | 'build') => void;
isStreaming?: boolean;
}
function openArtifactInWorkbench(filePath: string) {
@ -43,7 +44,17 @@ function normalizedFilePath(path: string) {
}
export const AssistantMessage = memo(
({ content, annotations, messageId, onRewind, onFork, append, chatMode, setChatMode }: AssistantMessageProps) => {
({
content,
annotations,
messageId,
onRewind,
onFork,
append,
chatMode,
setChatMode,
isStreaming,
}: AssistantMessageProps) => {
const filteredAnnotations = (annotations?.filter(
(annotation: JSONValue) =>
annotation && typeof annotation === 'object' && Object.keys(annotation).includes('type'),
@ -141,7 +152,7 @@ export const AssistantMessage = memo(
</div>
</div>
</>
<Markdown append={append} chatMode={chatMode} setChatMode={setChatMode} html>
<Markdown append={append} chatMode={chatMode} setChatMode={setChatMode} isStreaming={isStreaming} html>
{content}
</Markdown>
</div>

View File

@ -18,10 +18,11 @@ interface MarkdownProps {
append?: (message: Message) => void;
chatMode?: 'discuss' | 'build';
setChatMode?: (mode: 'discuss' | 'build') => void;
isStreaming?: boolean;
}
export const Markdown = memo(
({ children, html = false, limitedMarkdown = false, append, setChatMode }: MarkdownProps) => {
({ children, html = false, limitedMarkdown = false, append, setChatMode, isStreaming }: MarkdownProps) => {
logger.trace('Render');
const components = useMemo(() => {
@ -44,7 +45,7 @@ export const Markdown = memo(
}
if (className?.includes('__boltQuickAction__') || dataProps?.dataBoltQuickAction) {
return <div className="w-full grid grid-cols-2 gap-4">{children}</div>;
return <div className="flex items-center gap-2 flex-wrap mt-3.5">{children}</div>;
}
return (
@ -84,13 +85,24 @@ export const Markdown = memo(
const path = dataProps['data-path'] || dataProps.dataPath;
const href = dataProps['data-href'] || dataProps.dataHref;
const iconClassMap: Record<string, string> = {
file: 'i-ph:file',
message: 'i-ph:chats',
implement: 'i-ph:code',
link: 'i-ph:link',
};
const safeType = typeof type === 'string' ? type : '';
const iconClass = iconClassMap[safeType] ?? 'i-ph:question';
return (
<button
className=" p-2 rounded-md bg-bolt-elements-item-backgroundAccent hover:opacity-50 text-bolt-elements-item-contentAccent"
className="rounded-md justify-center px-3 py-1.5 text-xs bg-bolt-elements-item-backgroundAccent text-bolt-elements-item-contentAccent opacity-90 hover:opacity-100 flex items-center gap-2 cursor-pointer"
data-type={type}
data-message={message}
data-path={path}
data-href={href}
disabled={isStreaming}
onClick={() => {
if (type === 'file') {
openArtifactInWorkbench(path);
@ -118,6 +130,7 @@ export const Markdown = memo(
}
}}
>
<div className={`text-lg ${iconClass}`} />
{children}
</button>
);

View File

@ -100,6 +100,7 @@ export const Messages = forwardRef<HTMLDivElement, MessagesProps>(
append={props.append}
chatMode={props.chatMode}
setChatMode={props.setChatMode}
isStreaming={isStreaming}
/>
)}
</div>