feat: support customizing TTD welcome screen (#10719)

* feat: support customizing TTD welcome screen

* remove debug
This commit is contained in:
David Luzar
2026-01-30 16:28:36 +01:00
committed by GitHub
parent f5cf81ce42
commit 802cde3501
7 changed files with 44 additions and 19 deletions
@@ -48,14 +48,14 @@ $verticalBreakpoint: 861px;
}
}
&__empty-state {
&__welcome-screen {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
min-height: 200px;
&-content {
&__welcome-message {
text-align: center;
h3 {
@@ -6,6 +6,8 @@ import { InlineIcon } from "../../InlineIcon";
import { t } from "../../../i18n";
import { TTDWelcomeMessage } from "../TTDWelcomeMessage";
import { ChatMessage } from "./ChatMessage";
import type { TChat, TTTDDialog } from "../types";
@@ -20,13 +22,13 @@ export const ChatInterface = ({
onGenerate,
isGenerating,
rateLimits,
placeholder,
onAbort,
onMermaidTabClick,
onAiRepairClick,
onDeleteMessage,
onInsertMessage,
onRetry,
renderWelcomeScreen,
renderWarning,
}: {
chatId: string;
@@ -41,17 +43,13 @@ export const ChatInterface = ({
} | null;
onViewAsMermaid?: () => void;
generatedResponse?: string | null;
placeholder: {
title: string;
description: string;
hint: string;
};
onAbort?: () => void;
onMermaidTabClick?: (message: TChat.ChatMessage) => void;
onAiRepairClick?: (message: TChat.ChatMessage) => void;
onDeleteMessage?: (messageId: string) => void;
onInsertMessage?: (message: TChat.ChatMessage) => void;
onRetry?: (message: TChat.ChatMessage) => void;
renderWelcomeScreen?: TTTDDialog.renderWelcomeScreen;
renderWarning?: TTTDDialog.renderWarning;
}) => {
const messagesEndRef = useRef<HTMLDivElement>(null);
@@ -113,12 +111,12 @@ export const ChatInterface = ({
<div className="chat-interface">
<div className="chat-interface__messages">
{messages.length === 0 ? (
<div className="chat-interface__empty-state">
<div className="chat-interface__empty-state-content">
<h3>{placeholder.title}</h3>
<p>{placeholder.description}</p>
<p>{placeholder.hint}</p>
</div>
<div className="chat-interface__welcome-screen">
{renderWelcomeScreen ? (
renderWelcomeScreen({ rateLimits: rateLimits ?? null })
) : (
<TTDWelcomeMessage />
)}
</div>
) : (
messages.map((message, index) => (
@@ -40,6 +40,7 @@ export const TTDChatPanel = ({
onInsertMessage,
onRetry,
onViewAsMermaid,
renderWelcomeScreen,
renderWarning,
}: {
chatId: string;
@@ -68,6 +69,7 @@ export const TTDChatPanel = ({
onViewAsMermaid: () => void;
renderWelcomeScreen?: TTTDDialog.renderWelcomeScreen;
renderWarning?: TTTDDialog.renderWarning;
}) => {
const [rateLimits] = useAtom(rateLimitsAtom);
@@ -151,11 +153,7 @@ export const TTDChatPanel = ({
onInsertMessage={onInsertMessage}
onRetry={onRetry}
rateLimits={rateLimits}
placeholder={{
title: t("chat.placeholder.title"),
description: t("chat.placeholder.description"),
hint: t("chat.placeholder.hint"),
}}
renderWelcomeScreen={renderWelcomeScreen}
renderWarning={renderWarning}
/>
</TTDDialogPanel>
@@ -15,6 +15,8 @@ import { TTDDialogTab } from "./TTDDialogTab";
import "./TTDDialog.scss";
import { TTDWelcomeMessage } from "./TTDWelcomeMessage";
import type {
MermaidToExcalidrawLibProps,
TTDPersistenceAdapter,
@@ -25,6 +27,7 @@ export const TTDDialog = (
props:
| {
onTextSubmit: TTTDDialog.onTextSubmit;
renderWelcomeScreen?: TTTDDialog.renderWelcomeScreen;
renderWarning?: TTTDDialog.renderWarning;
persistenceAdapter: TTDPersistenceAdapter;
}
@@ -39,6 +42,8 @@ export const TTDDialog = (
return <TTDDialogBase {...props} tab={appState.openDialog.tab} />;
};
TTDDialog.WelcomeMessage = TTDWelcomeMessage;
/**
* Text to diagram (TTD) dialog
*/
@@ -54,6 +59,7 @@ const TTDDialogBase = withInternalFallback(
onTextSubmit(
props: TTTDDialog.OnTextSubmitProps,
): Promise<TTTDDialog.OnTextSubmitRetValue>;
renderWelcomeScreen?: TTTDDialog.renderWelcomeScreen;
renderWarning?: TTTDDialog.renderWarning;
persistenceAdapter: TTDPersistenceAdapter;
}
@@ -110,6 +116,7 @@ const TTDDialogBase = withInternalFallback(
<TextToDiagram
mermaidToExcalidrawLib={mermaidToExcalidrawLib}
onTextSubmit={rest.onTextSubmit}
renderWelcomeScreen={rest.renderWelcomeScreen}
renderWarning={rest.renderWarning}
persistenceAdapter={rest.persistenceAdapter}
/>
@@ -0,0 +1,11 @@
import { t } from "../../i18n";
export const TTDWelcomeMessage = () => {
return (
<div className="chat-interface__welcome-screen__welcome-message">
<h3>{t("chat.placeholder.title")}</h3>
<p>{t("chat.placeholder.description")}</p>
<p>{t("chat.placeholder.hint")}</p>
</div>
);
};
@@ -35,6 +35,7 @@ import type {
const TextToDiagramContent = ({
mermaidToExcalidrawLib,
onTextSubmit,
renderWelcomeScreen,
renderWarning,
persistenceAdapter,
}: {
@@ -42,6 +43,7 @@ const TextToDiagramContent = ({
onTextSubmit: (
props: TTTDDialog.OnTextSubmitProps,
) => Promise<TTTDDialog.OnTextSubmitRetValue>;
renderWelcomeScreen?: TTTDDialog.renderWelcomeScreen;
renderWarning?: TTTDDialog.renderWarning;
persistenceAdapter: TTDPersistenceAdapter;
}) => {
@@ -220,6 +222,7 @@ const TextToDiagramContent = ({
onRetry={handleRetry}
onViewAsMermaid={onViewAsMermaid}
renderWarning={renderWarning}
renderWelcomeScreen={renderWelcomeScreen}
/>
{showPreview && (
<TTDPreviewPanel
@@ -237,6 +240,7 @@ const TextToDiagramContent = ({
export const TextToDiagram = ({
mermaidToExcalidrawLib,
onTextSubmit,
renderWelcomeScreen,
renderWarning,
persistenceAdapter,
}: {
@@ -244,6 +248,7 @@ export const TextToDiagram = ({
onTextSubmit(
props: TTTDDialog.OnTextSubmitProps,
): Promise<TTTDDialog.OnTextSubmitRetValue>;
renderWelcomeScreen?: TTTDDialog.renderWelcomeScreen;
renderWarning?: TTTDDialog.renderWarning;
persistenceAdapter: TTDPersistenceAdapter;
}) => {
@@ -251,6 +256,7 @@ export const TextToDiagram = ({
<TextToDiagramContent
mermaidToExcalidrawLib={mermaidToExcalidrawLib}
onTextSubmit={onTextSubmit}
renderWelcomeScreen={renderWelcomeScreen}
renderWarning={renderWarning}
persistenceAdapter={persistenceAdapter}
/>
@@ -116,4 +116,9 @@ export namespace TTTDDialog {
export type renderWarning = (
chatMessage: TChat.ChatMessage,
) => React.ReactNode | undefined;
export type renderWelcomeScreen = (props: {
/** null if not rate limit data currently available */
rateLimits: RateLimits | null;
}) => React.ReactNode | undefined;
}