mirror of
https://github.com/stackblitz-labs/bolt.diy
synced 2025-06-26 18:26:38 +00:00
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:
parent
74605e96e3
commit
de0a41b5f1
@ -16,6 +16,7 @@ interface AssistantMessageProps {
|
|||||||
append?: (message: Message) => void;
|
append?: (message: Message) => void;
|
||||||
chatMode?: 'discuss' | 'build';
|
chatMode?: 'discuss' | 'build';
|
||||||
setChatMode?: (mode: 'discuss' | 'build') => void;
|
setChatMode?: (mode: 'discuss' | 'build') => void;
|
||||||
|
isStreaming?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function openArtifactInWorkbench(filePath: string) {
|
function openArtifactInWorkbench(filePath: string) {
|
||||||
@ -43,7 +44,17 @@ function normalizedFilePath(path: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const AssistantMessage = memo(
|
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(
|
const filteredAnnotations = (annotations?.filter(
|
||||||
(annotation: JSONValue) =>
|
(annotation: JSONValue) =>
|
||||||
annotation && typeof annotation === 'object' && Object.keys(annotation).includes('type'),
|
annotation && typeof annotation === 'object' && Object.keys(annotation).includes('type'),
|
||||||
@ -141,7 +152,7 @@ export const AssistantMessage = memo(
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
<Markdown append={append} chatMode={chatMode} setChatMode={setChatMode} html>
|
<Markdown append={append} chatMode={chatMode} setChatMode={setChatMode} isStreaming={isStreaming} html>
|
||||||
{content}
|
{content}
|
||||||
</Markdown>
|
</Markdown>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -18,10 +18,11 @@ interface MarkdownProps {
|
|||||||
append?: (message: Message) => void;
|
append?: (message: Message) => void;
|
||||||
chatMode?: 'discuss' | 'build';
|
chatMode?: 'discuss' | 'build';
|
||||||
setChatMode?: (mode: 'discuss' | 'build') => void;
|
setChatMode?: (mode: 'discuss' | 'build') => void;
|
||||||
|
isStreaming?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Markdown = memo(
|
export const Markdown = memo(
|
||||||
({ children, html = false, limitedMarkdown = false, append, setChatMode }: MarkdownProps) => {
|
({ children, html = false, limitedMarkdown = false, append, setChatMode, isStreaming }: MarkdownProps) => {
|
||||||
logger.trace('Render');
|
logger.trace('Render');
|
||||||
|
|
||||||
const components = useMemo(() => {
|
const components = useMemo(() => {
|
||||||
@ -44,7 +45,7 @@ export const Markdown = memo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (className?.includes('__boltQuickAction__') || dataProps?.dataBoltQuickAction) {
|
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 (
|
return (
|
||||||
@ -84,13 +85,24 @@ export const Markdown = memo(
|
|||||||
const path = dataProps['data-path'] || dataProps.dataPath;
|
const path = dataProps['data-path'] || dataProps.dataPath;
|
||||||
const href = dataProps['data-href'] || dataProps.dataHref;
|
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 (
|
return (
|
||||||
<button
|
<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-type={type}
|
||||||
data-message={message}
|
data-message={message}
|
||||||
data-path={path}
|
data-path={path}
|
||||||
data-href={href}
|
data-href={href}
|
||||||
|
disabled={isStreaming}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (type === 'file') {
|
if (type === 'file') {
|
||||||
openArtifactInWorkbench(path);
|
openArtifactInWorkbench(path);
|
||||||
@ -118,6 +130,7 @@ export const Markdown = memo(
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<div className={`text-lg ${iconClass}`} />
|
||||||
{children}
|
{children}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -100,6 +100,7 @@ export const Messages = forwardRef<HTMLDivElement, MessagesProps>(
|
|||||||
append={props.append}
|
append={props.append}
|
||||||
chatMode={props.chatMode}
|
chatMode={props.chatMode}
|
||||||
setChatMode={props.setChatMode}
|
setChatMode={props.setChatMode}
|
||||||
|
isStreaming={isStreaming}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user