feat(FN-3242): add documentation for compact mobile chat dialogs
Adds documentation for the compact mobile chat dialogs feature (FN-3242) to the dashboard guide. Fusion-Task-Id: FN-3242
This commit is contained in:
@@ -37,6 +37,7 @@ Features:
|
|||||||
Chat view provides project-scoped conversations with agents.
|
Chat view provides project-scoped conversations with agents.
|
||||||
|
|
||||||
- Entering `/clear` (exact match after trimming) in the composer starts a fresh thread for the current chat target instead of sending the literal command to the model
|
- Entering `/clear` (exact match after trimming) in the composer starts a fresh thread for the current chat target instead of sending the literal command to the model
|
||||||
|
- On mobile, the New Chat and Delete Conversation dialogs use a compact inset treatment (centered, viewport-bounded, internally scrollable) instead of the app's default full-height mobile modal chrome.
|
||||||
- Full Chat and Quick Chat both consume the same streamed `/api/chat/sessions/:id/messages` response contract, so assistant text/chunk/done events are restored consistently across both surfaces
|
- Full Chat and Quick Chat both consume the same streamed `/api/chat/sessions/:id/messages` response contract, so assistant text/chunk/done events are restored consistently across both surfaces
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -445,8 +445,8 @@ function NewChatDialog({ projectId, onClose, onCreate }: NewChatDialogProps) {
|
|||||||
chatMode === "agent" ? !selectedAgentId : !selectedModel;
|
chatMode === "agent" ? !selectedAgentId : !selectedModel;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="chat-new-dialog-backdrop" onClick={onClose} role="dialog" aria-modal="true">
|
<div className="chat-new-dialog-backdrop chat-view-dialog-backdrop" onClick={onClose} role="dialog" aria-modal="true">
|
||||||
<div className="chat-new-dialog" onClick={(e) => e.stopPropagation()}>
|
<div className="chat-new-dialog chat-view-dialog" onClick={(e) => e.stopPropagation()}>
|
||||||
<h3>New Chat</h3>
|
<h3>New Chat</h3>
|
||||||
<div className="chat-new-dialog-mode-toggle" data-testid="chat-new-dialog-mode-toggle">
|
<div className="chat-new-dialog-mode-toggle" data-testid="chat-new-dialog-mode-toggle">
|
||||||
<button
|
<button
|
||||||
@@ -1652,10 +1652,10 @@ export function ChatView({ projectId, addToast }: ChatViewProps) {
|
|||||||
|
|
||||||
{/* Confirm Delete Dialog */}
|
{/* Confirm Delete Dialog */}
|
||||||
{confirmDelete && (
|
{confirmDelete && (
|
||||||
<div className="chat-new-dialog-backdrop" onClick={() => setConfirmDelete(null)}>
|
<div className="chat-new-dialog-backdrop chat-view-dialog-backdrop" onClick={() => setConfirmDelete(null)}>
|
||||||
<div className="chat-new-dialog" onClick={(e) => e.stopPropagation()}>
|
<div className="chat-new-dialog chat-view-dialog" onClick={(e) => e.stopPropagation()}>
|
||||||
<h3>Delete Conversation?</h3>
|
<h3>Delete Conversation?</h3>
|
||||||
<p style={{ fontSize: "14px", color: "var(--text-secondary)", marginBottom: "16px" }}>
|
<p className="chat-view-delete-dialog-copy">
|
||||||
This action cannot be undone. All messages in this conversation will be permanently deleted.
|
This action cannot be undone. All messages in this conversation will be permanently deleted.
|
||||||
</p>
|
</p>
|
||||||
<div className="chat-new-dialog-actions">
|
<div className="chat-new-dialog-actions">
|
||||||
|
|||||||
@@ -225,7 +225,13 @@
|
|||||||
.chat-new-dialog-actions {
|
.chat-new-dialog-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
gap: 8px;
|
gap: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-view-delete-dialog-copy {
|
||||||
|
margin: 0 0 var(--space-lg);
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: calc(var(--space-sm) + var(--space-xs) * 1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* New Chat dialog model selector */
|
/* New Chat dialog model selector */
|
||||||
@@ -309,17 +315,17 @@
|
|||||||
height: min(520px, calc(100dvh - 120px));
|
height: min(520px, calc(100dvh - 120px));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep regular chat New Chat + Delete confirmation dialogs compact on mobile.
|
/* ChatView New Chat + Delete dialogs should stay inset/compact on mobile.
|
||||||
styles.css sets .chat-new-dialog-backdrop align-items: stretch globally on
|
styles.css intentionally stretches .chat-new-dialog-backdrop for full-screen
|
||||||
mobile; override here so this modal does not become full-height. */
|
overlays, so scope the compact override to ChatView's modifier class only. */
|
||||||
.chat-new-dialog-backdrop {
|
.chat-view-dialog-backdrop {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: var(--space-md);
|
padding: var(--space-md);
|
||||||
padding-top: max(var(--space-md), env(safe-area-inset-top, 0px));
|
padding-top: max(var(--space-md), env(safe-area-inset-top, 0px));
|
||||||
padding-bottom: max(var(--space-md), env(safe-area-inset-bottom, 0px));
|
padding-bottom: max(var(--space-md), env(safe-area-inset-bottom, 0px));
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-new-dialog {
|
.chat-view-dialog {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: min(100%, calc(var(--space-xl) * 16));
|
max-width: min(100%, calc(var(--space-xl) * 16));
|
||||||
max-height: calc(100dvh - (var(--space-md) * 2) - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
|
max-height: calc(100dvh - (var(--space-md) * 2) - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
|
||||||
|
|||||||
@@ -2878,6 +2878,22 @@ describe("ChatView mobile CSS contract", () => {
|
|||||||
expect(mobileRuleNotContains(".chat-message-render-toggle", "display: inline-flex")).toBe(true);
|
expect(mobileRuleNotContains(".chat-message-render-toggle", "display: inline-flex")).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("mobile keeps ChatView dialog backdrop centered with safe-area padding", () => {
|
||||||
|
expect(mobileRuleContains(".chat-view-dialog-backdrop", "align-items: center")).toBe(true);
|
||||||
|
expect(mobileRuleContains(".chat-view-dialog-backdrop", "padding-top: max(var(--space-md), env(safe-area-inset-top, 0px))")).toBe(true);
|
||||||
|
expect(mobileRuleContains(".chat-view-dialog-backdrop", "padding-bottom: max(var(--space-md), env(safe-area-inset-bottom, 0px))")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("mobile constrains ChatView dialog height and allows internal scrolling", () => {
|
||||||
|
expect(mobileRuleContains(".chat-view-dialog", "max-height: calc(100dvh - (var(--space-md) * 2) - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px))")).toBe(true);
|
||||||
|
expect(mobileRuleContains(".chat-view-dialog", "overflow-y: auto")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("mobile ChatView dialog rules do not set full-screen heights", () => {
|
||||||
|
expect(mobileRuleNotContains(".chat-view-dialog", "height: 100vh")).toBe(true);
|
||||||
|
expect(mobileRuleNotContains(".chat-view-dialog", "height: 100dvh")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("mobile includes keyboard-aware chat-thread height rule", () => {
|
it("mobile includes keyboard-aware chat-thread height rule", () => {
|
||||||
expect(css).toMatch(/\.chat-thread\[style\*=\"--keyboard-overlap\"\]\s*\{[^}]*--vv-height/);
|
expect(css).toMatch(/\.chat-thread\[style\*=\"--keyboard-overlap\"\]\s*\{[^}]*--vv-height/);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user