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:
Fusion
2026-05-03 06:49:04 -07:00
committed by gsxdsm
parent 59f2868f24
commit fa16b953c0
4 changed files with 34 additions and 11 deletions

View File

@@ -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
![Chat view](./screenshots/chat-view.png) ![Chat view](./screenshots/chat-view.png)

View File

@@ -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">

View File

@@ -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));

View File

@@ -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/);
}); });