feat(FN-1324): add fullscreen expand to task creation components

- Add Maximize2/Minimize2 toggle button to QuickEntryBox for fullscreen textarea expansion
- Add Maximize2/Minimize2 toggle button to InlineCreateCard for fullscreen textarea expansion
- Implement single-textarea pattern with positioned container for expand button overlay
- Add description--fullscreen CSS class for fullscreen textarea styling
- Add focus handoff when entering fullscreen mode
- Add comprehensive unit tests for fullscreen expansion in both components
- Tests cover collapsed/expanded states, toggle button visibility, and class application
This commit is contained in:
gsxdsm
2026-04-09 13:31:26 -07:00
parent 008f664183
commit 4a07e69f7d
5 changed files with 586 additions and 65 deletions

View File

@@ -1,6 +1,6 @@
import { useState, useCallback, useEffect, useRef } from "react";
import { createPortal } from "react-dom";
import { Brain, Link, Lightbulb, ListTree, Zap, ChevronDown, ChevronUp, Bot } from "lucide-react";
import { Brain, Link, Lightbulb, ListTree, Zap, ChevronDown, ChevronUp, Bot, Maximize2, Minimize2 } from "lucide-react";
import type { Task, TaskCreateInput, Settings } from "@fusion/core";
import type { ToastType } from "../hooks/useToast";
import { fetchModels, uploadAttachment, fetchSettings, updateGlobalSettings, fetchAgents } from "../api";
@@ -99,6 +99,10 @@ export function InlineCreateCard({
const [submitting, setSubmitting] = useState(false);
const [pendingImages, setPendingImages] = useState<PendingImage[]>([]);
const [isExpanded, setIsExpanded] = useState(false);
// isDescriptionExpanded controls fullscreen description editing mode
const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false);
// Track textarea focus for expand button visibility
const [isDescriptionFocused, setIsDescriptionFocused] = useState(false);
const justResetRef = useRef(false);
const inputRef = useRef<HTMLTextAreaElement>(null);
const cardRef = useRef<HTMLDivElement>(null);
@@ -348,6 +352,7 @@ export function InlineCreateCard({
// Collapse and clear localStorage after successful task creation
setIsExpanded(false);
setIsDescriptionExpanded(false); // Exit fullscreen mode on submit
justResetRef.current = true;
if (typeof window !== "undefined") {
removeScopedItem(STORAGE_KEY, projectId);
@@ -380,6 +385,11 @@ export function InlineCreateCard({
async (e: React.KeyboardEvent) => {
if (e.key === "Escape") {
e.preventDefault();
// Exit fullscreen mode first - highest priority
if (isDescriptionExpanded) {
setIsDescriptionExpanded(false);
return;
}
// Close dropdowns first if open
if (showDeps || showAgentPicker || isModelModalOpen || showPresets) {
setShowDeps(false);
@@ -414,6 +424,7 @@ export function InlineCreateCard({
handleSubmit,
onCancel,
description,
isDescriptionExpanded,
showDeps,
showAgentPicker,
isModelModalOpen,
@@ -579,38 +590,116 @@ export function InlineCreateCard({
setIsExpanded((prev) => !prev);
}, []);
const handleToggleDescriptionExpand = useCallback(() => {
setIsDescriptionExpanded((prev) => {
const next = !prev;
// Focus the fullscreen textarea after it renders
if (next && inputRef.current) {
setTimeout(() => inputRef.current?.focus(), 0);
}
return next;
});
}, []);
const handleDescriptionFullscreenKeyDown = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {
if (!isDescriptionExpanded || e.key !== "Escape") return;
e.preventDefault();
e.stopPropagation();
setIsDescriptionExpanded(false);
}, [isDescriptionExpanded]);
return (
<div className={`inline-create-card ${isExpanded ? "inline-create-card--expanded" : "inline-create-card--collapsed"}`} ref={cardRef}>
<div className="inline-create-main-row">
<textarea
ref={inputRef}
rows={1}
className="inline-create-input"
placeholder="What needs to be done?"
value={description}
onChange={(e) => {
setDescription(e.target.value);
const el = e.target;
el.style.height = "auto";
el.style.height = el.scrollHeight + "px";
}}
onKeyDown={handleKeyDown}
onPaste={handlePaste}
disabled={submitting}
aria-controls={isExpanded ? "inline-create-controls" : undefined}
/>
<button
type="button"
className="btn btn-sm inline-create-toggle"
onClick={toggleExpanded}
aria-expanded={isExpanded}
aria-controls={isExpanded ? "inline-create-controls" : undefined}
aria-label={isExpanded ? "Collapse advanced task options" : "Expand advanced task options"}
data-testid="inline-create-toggle"
title={isExpanded ? "Collapse" : "Expand"}
>
{isExpanded ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
</button>
<div
className={`description-with-refine${isDescriptionExpanded ? " description--fullscreen" : ""}`}
onKeyDown={handleDescriptionFullscreenKeyDown}
>
{isDescriptionExpanded && (
<div className="description-fullscreen-header">
<span>Editing Description</span>
<button
type="button"
className="btn btn-sm description-expand-btn"
onClick={handleToggleDescriptionExpand}
aria-label="Collapse description"
title="Collapse description"
data-testid="inline-create-collapse"
>
<Minimize2 size={14} />
</button>
</div>
)}
{!isDescriptionExpanded && (
<div className="inline-create-main-row">
<div className="inline-create-textarea-wrap">
<textarea
ref={inputRef}
rows={1}
className="inline-create-input"
placeholder="What needs to be done?"
value={description}
onChange={(e) => {
setDescription(e.target.value);
const el = e.target;
el.style.height = "auto";
el.style.height = el.scrollHeight + "px";
}}
onKeyDown={handleKeyDown}
onPaste={handlePaste}
onFocus={() => setIsDescriptionFocused(true)}
onBlur={() => setIsDescriptionFocused(false)}
disabled={submitting}
aria-controls={isExpanded ? "inline-create-controls" : undefined}
/>
{isDescriptionFocused && description.trim() && !submitting && (
<button
type="button"
className="btn btn-sm inline-create-expand-btn"
onClick={handleToggleDescriptionExpand}
onMouseDown={(e) => e.preventDefault()}
aria-label="Expand description"
title="Expand description"
data-testid="inline-create-expand"
>
<Maximize2 size={14} />
</button>
)}
</div>
<button
type="button"
className="btn btn-sm inline-create-toggle"
onClick={toggleExpanded}
aria-expanded={isExpanded}
aria-controls={isExpanded ? "inline-create-controls" : undefined}
aria-label={isExpanded ? "Collapse advanced task options" : "Expand advanced task options"}
data-testid="inline-create-toggle"
title={isExpanded ? "Collapse" : "Expand"}
>
{isExpanded ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
</button>
</div>
)}
{isDescriptionExpanded && (
<textarea
ref={inputRef}
rows={10}
className="inline-create-input inline-create-input--fullscreen"
placeholder="What needs to be done?"
value={description}
onChange={(e) => {
setDescription(e.target.value);
const el = e.target;
el.style.height = "auto";
el.style.height = el.scrollHeight + "px";
}}
onKeyDown={handleKeyDown}
onPaste={handlePaste}
onFocus={() => setIsDescriptionFocused(true)}
onBlur={() => setIsDescriptionFocused(false)}
disabled={submitting}
data-testid="inline-create-input-fullscreen"
/>
)}
</div>
{pendingImages.length > 0 && (
<div className="inline-create-previews">

View File

@@ -4,7 +4,7 @@ import type { ToastType } from "../hooks/useToast";
import type { Task, TaskCreateInput, Settings } from "@fusion/core";
import type { ModelInfo, RefinementType, Agent } from "../api";
import { fetchModels, fetchSettings, refineText, getRefineErrorMessage, updateGlobalSettings, fetchAgents, uploadAttachment } from "../api";
import { Link, Paperclip, Brain, Lightbulb, ListTree, Sparkles, Save, ChevronDown, ChevronUp, ChevronRight, Bot } from "lucide-react";
import { Link, Paperclip, Brain, Lightbulb, ListTree, Sparkles, Save, ChevronDown, ChevronUp, ChevronRight, Bot, Maximize2, Minimize2 } from "lucide-react";
import { CustomModelDropdown } from "./CustomModelDropdown";
import { getScopedItem, removeScopedItem, setScopedItem } from "../utils/projectStorage";
@@ -92,6 +92,10 @@ export function QuickEntryBox({ onCreate, addToast, tasks = [], availableModels,
// isDisclosureExpanded controls visibility of the controls panel (Deps, Models, etc.)
// Always starts collapsed — user must explicitly toggle each session
const [isDisclosureExpanded, setIsDisclosureExpanded] = useState(false);
// isDescriptionExpanded controls fullscreen description editing mode
const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false);
// Track textarea focus for expand button visibility
const [isDescriptionFocused, setIsDescriptionFocused] = useState(false);
const textareaRef = useRef<HTMLTextAreaElement>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
const justResetRef = useRef(false);
@@ -254,14 +258,17 @@ export function QuickEntryBox({ onCreate, addToast, tasks = [], availableModels,
const textarea = textareaRef.current;
if (!textarea) return;
// In fullscreen mode, CSS handles sizing via flex: 1, don't set inline height
if (isDescriptionExpanded) return;
// Reset height to auto to get accurate scrollHeight
textarea.style.height = "auto";
// Set to scrollHeight (capped at max-height via CSS)
const newHeight = Math.min(textarea.scrollHeight, 200);
textarea.style.height = `${newHeight}px`;
}, []);
}, [isDescriptionExpanded]);
// Resize when description changes
// Resize when description changes (not in fullscreen mode since CSS handles it)
useEffect(() => {
if (isExpanded) {
autoResize();
@@ -362,6 +369,7 @@ export function QuickEntryBox({ onCreate, addToast, tasks = [], availableModels,
setIsRefining(false);
setIsExpanded(false); // Collapse textarea height on reset
setIsDisclosureExpanded(false); // Always reset controls to collapsed after creation
setIsDescriptionExpanded(false); // Exit fullscreen mode on reset
justResetRef.current = true;
if (textareaRef.current) {
textareaRef.current.style.height = "auto";
@@ -469,8 +477,8 @@ export function QuickEntryBox({ onCreate, addToast, tasks = [], availableModels,
const handleKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === "Enter") {
if (e.shiftKey && isExpanded) {
// Allow Shift+Enter to insert newline when expanded
if (e.shiftKey && (isExpanded || isDescriptionExpanded)) {
// Allow Shift+Enter to insert newline when expanded or in fullscreen mode
// Don't prevent default - let the newline be inserted
return;
}
@@ -479,6 +487,11 @@ export function QuickEntryBox({ onCreate, addToast, tasks = [], availableModels,
handleSubmit();
} else if (e.key === "Escape") {
e.preventDefault();
// Exit fullscreen mode first - highest priority
if (isDescriptionExpanded) {
setIsDescriptionExpanded(false);
return;
}
// Close model submenu first if open
if (activeModelSubmenu) {
setActiveModelSubmenu(null);
@@ -524,6 +537,7 @@ export function QuickEntryBox({ onCreate, addToast, tasks = [], availableModels,
handleSubmit,
description,
isExpanded,
isDescriptionExpanded,
showDeps,
showAgentPicker,
isModelMenuOpen,
@@ -540,6 +554,8 @@ export function QuickEntryBox({ onCreate, addToast, tasks = [], availableModels,
if (justResetRef.current) {
justResetRef.current = false;
}
// Track description focus for expand button visibility
setIsDescriptionFocused(false);
}, []);
const handleFocus = useCallback(() => {
@@ -547,6 +563,8 @@ export function QuickEntryBox({ onCreate, addToast, tasks = [], availableModels,
if (autoExpand) {
setIsExpanded(true);
}
// Track description focus for expand button visibility
setIsDescriptionFocused(true);
}, [autoExpand]);
const toggleDep = useCallback((id: string) => {
@@ -898,36 +916,108 @@ export function QuickEntryBox({ onCreate, addToast, tasks = [], availableModels,
});
}, []);
const handleToggleDescriptionExpand = useCallback(() => {
setIsDescriptionExpanded((prev) => {
const next = !prev;
// Focus the fullscreen textarea after it renders
if (next && textareaRef.current) {
// Use setTimeout to ensure focus happens after the textarea is rendered
setTimeout(() => textareaRef.current?.focus(), 0);
}
return next;
});
}, []);
const handleDescriptionFullscreenKeyDown = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {
if (!isDescriptionExpanded || e.key !== "Escape") return;
e.preventDefault();
e.stopPropagation();
setIsDescriptionExpanded(false);
}, [isDescriptionExpanded]);
return (
<div className={`quick-entry-box ${isDisclosureExpanded ? "quick-entry-box--expanded" : "quick-entry-box--collapsed"}`} data-testid="quick-entry-box">
<div className="quick-entry-main-row">
<textarea
ref={textareaRef}
className={`quick-entry-input ${isExpanded ? "quick-entry-input--expanded" : ""}`}
placeholder={isSubmitting ? "Creating..." : "Add a task..."}
value={description}
onChange={(e) => setDescription(e.target.value)}
onKeyDown={handleKeyDown}
onPaste={handlePaste}
onFocus={handleFocus}
onBlur={handleBlur}
disabled={isSubmitting || isDisabled}
data-testid="quick-entry-input"
rows={1}
aria-controls="quick-entry-controls"
aria-expanded={isDisclosureExpanded}
/>
<button
type="button"
className="btn btn-sm quick-entry-toggle"
onClick={toggleExpanded}
aria-expanded={isDisclosureExpanded}
aria-controls="quick-entry-controls"
data-testid="quick-entry-toggle"
title={isDisclosureExpanded ? "Collapse" : "Expand"}
>
{isDisclosureExpanded ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
</button>
<div
className={`description-with-refine${isDescriptionExpanded ? " description--fullscreen" : ""}`}
onKeyDown={handleDescriptionFullscreenKeyDown}
>
{isDescriptionExpanded && (
<div className="description-fullscreen-header">
<span>Editing Description</span>
<button
type="button"
className="btn btn-sm description-expand-btn"
onClick={handleToggleDescriptionExpand}
aria-label="Collapse description"
title="Collapse description"
data-testid="quick-entry-collapse"
>
<Minimize2 size={14} />
</button>
</div>
)}
{!isDescriptionExpanded && (
<div className="quick-entry-main-row">
<div className="quick-entry-textarea-wrap">
<textarea
ref={textareaRef}
className={`quick-entry-input ${isExpanded ? "quick-entry-input--expanded" : ""}`}
placeholder={isSubmitting ? "Creating..." : "Add a task..."}
value={description}
onChange={(e) => setDescription(e.target.value)}
onKeyDown={handleKeyDown}
onPaste={handlePaste}
onFocus={handleFocus}
onBlur={handleBlur}
disabled={isSubmitting || isDisabled}
data-testid="quick-entry-input"
rows={1}
aria-controls="quick-entry-controls"
aria-expanded={isDisclosureExpanded}
/>
{isDescriptionFocused && description.trim() && !isDisabled && !isSubmitting && (
<button
type="button"
className="btn btn-sm quick-entry-expand-btn"
onClick={handleToggleDescriptionExpand}
onMouseDown={(e) => e.preventDefault()}
aria-label="Expand description"
title="Expand description"
data-testid="quick-entry-expand"
>
<Maximize2 size={14} />
</button>
)}
</div>
<button
type="button"
className="btn btn-sm quick-entry-toggle"
onClick={toggleExpanded}
aria-expanded={isDisclosureExpanded}
aria-controls="quick-entry-controls"
data-testid="quick-entry-toggle"
title={isDisclosureExpanded ? "Collapse" : "Expand"}
>
{isDisclosureExpanded ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
</button>
</div>
)}
{isDescriptionExpanded && (
<textarea
ref={textareaRef}
className="quick-entry-input quick-entry-input--fullscreen"
placeholder={isSubmitting ? "Creating..." : "Add a task..."}
value={description}
onChange={(e) => setDescription(e.target.value)}
onKeyDown={handleKeyDown}
onPaste={handlePaste}
onFocus={handleFocus}
onBlur={handleBlur}
disabled={isSubmitting || isDisabled}
data-testid="quick-entry-input-fullscreen"
rows={10}
/>
)}
</div>
<div
id="quick-entry-controls"

View File

@@ -1,6 +1,6 @@
import type { ComponentProps } from "react";
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { render, screen, fireEvent, waitFor, act } from "@testing-library/react";
import { InlineCreateCard } from "../InlineCreateCard";
import type { Task, Column } from "@fusion/core";
import { fetchModels, fetchSettings, fetchAgents } from "../../api";
@@ -21,6 +21,8 @@ vi.mock("lucide-react", () => ({
ChevronDown: () => null,
ChevronUp: () => null,
Bot: () => null,
Maximize2: () => null,
Minimize2: () => null,
}));
// Mock ModelSelectionModal (renders via portal, so mock for testability)
@@ -1081,4 +1083,144 @@ describe("InlineCreateCard button visibility when collapsed", () => {
});
});
});
describe("description fullscreen expansion", () => {
it("shows expand button when textarea is focused and has content", async () => {
renderCard();
const textarea = screen.getByPlaceholderText("What needs to be done?");
// Focus and type content
fireEvent.focus(textarea);
fireEvent.change(textarea, { target: { value: "Test task description" } });
// Expand button should be visible
await waitFor(() => {
expect(screen.getByTestId("inline-create-expand")).toBeInTheDocument();
});
});
it("hides expand button when textarea is empty", async () => {
renderCard();
const textarea = screen.getByPlaceholderText("What needs to be done?");
// Focus without typing
fireEvent.focus(textarea);
// Expand button should not be visible when empty
expect(screen.queryByTestId("inline-create-expand")).not.toBeInTheDocument();
});
it("hides expand button when textarea is blurred", async () => {
renderCard();
const textarea = screen.getByPlaceholderText("What needs to be done?");
// Focus, type, then blur
fireEvent.focus(textarea);
fireEvent.change(textarea, { target: { value: "Test content" } });
// Verify expand button is visible before blur
await waitFor(() => {
expect(screen.getByTestId("inline-create-expand")).toBeInTheDocument();
});
// Blur the textarea
await act(async () => {
fireEvent.blur(textarea);
});
// Expand button should be hidden after blur
await waitFor(() => {
expect(screen.queryByTestId("inline-create-expand")).not.toBeInTheDocument();
});
});
it("enters fullscreen mode when expand button is clicked", async () => {
renderCard();
const textarea = screen.getByPlaceholderText("What needs to be done?");
// Focus and type content
fireEvent.focus(textarea);
fireEvent.change(textarea, { target: { value: "Test description" } });
// Click expand button
await waitFor(() => {
fireEvent.click(screen.getByTestId("inline-create-expand"));
});
// Fullscreen textarea should be visible
await waitFor(() => {
expect(screen.getByTestId("inline-create-input-fullscreen")).toBeInTheDocument();
});
// Collapse button should be visible
expect(screen.getByTestId("inline-create-collapse")).toBeInTheDocument();
});
it("exits fullscreen mode when collapse button is clicked", async () => {
renderCard();
const textarea = screen.getByPlaceholderText("What needs to be done?");
// Enter fullscreen mode
fireEvent.focus(textarea);
fireEvent.change(textarea, { target: { value: "Test description" } });
await waitFor(() => {
fireEvent.click(screen.getByTestId("inline-create-expand"));
});
await waitFor(() => {
expect(screen.getByTestId("inline-create-input-fullscreen")).toBeInTheDocument();
});
// Click collapse button
fireEvent.click(screen.getByTestId("inline-create-collapse"));
// Fullscreen textarea should be hidden
await waitFor(() => {
expect(screen.queryByTestId("inline-create-input-fullscreen")).not.toBeInTheDocument();
});
});
it("exits fullscreen mode when Escape key is pressed in fullscreen", async () => {
renderCard();
const textarea = screen.getByPlaceholderText("What needs to be done?");
// Enter fullscreen mode
fireEvent.focus(textarea);
fireEvent.change(textarea, { target: { value: "Test description" } });
await waitFor(() => {
fireEvent.click(screen.getByTestId("inline-create-expand"));
});
await waitFor(() => {
expect(screen.getByTestId("inline-create-input-fullscreen")).toBeInTheDocument();
});
// Press Escape
const fullscreenTextarea = screen.getByTestId("inline-create-input-fullscreen");
fireEvent.keyDown(fullscreenTextarea, { key: "Escape" });
// Fullscreen should be exited
await waitFor(() => {
expect(screen.queryByTestId("inline-create-input-fullscreen")).not.toBeInTheDocument();
});
});
it("preserves description text when entering fullscreen", async () => {
renderCard();
const textarea = screen.getByPlaceholderText("What needs to be done?");
// Type some content
fireEvent.focus(textarea);
fireEvent.change(textarea, { target: { value: "My test task description" } });
// Enter fullscreen
await waitFor(() => {
fireEvent.click(screen.getByTestId("inline-create-expand"));
});
// Check fullscreen textarea has the content
await waitFor(() => {
const fullscreenTextarea = screen.getByTestId("inline-create-input-fullscreen") as HTMLTextAreaElement;
expect(fullscreenTextarea.value).toBe("My test task description");
});
});
});
});

View File

@@ -114,6 +114,8 @@ vi.mock("lucide-react", () => ({
ChevronUp: () => null,
ChevronRight: () => null,
Bot: () => null,
Maximize2: () => null,
Minimize2: () => null,
}));
// Mock ModelSelectionModal (kept for backward compatibility - no longer directly rendered)
@@ -2334,4 +2336,136 @@ describe("QuickEntryBox", () => {
});
});
});
describe("description fullscreen expansion", () => {
it("shows expand button when textarea is focused and has content", async () => {
renderQuickEntryBox({});
const textarea = screen.getByTestId("quick-entry-input");
// Focus and type content
fireEvent.focus(textarea);
fireEvent.change(textarea, { target: { value: "Test task description" } });
// Expand button should be visible
await waitFor(() => {
expect(screen.getByTestId("quick-entry-expand")).toBeInTheDocument();
});
});
it("hides expand button when textarea is empty", async () => {
renderQuickEntryBox({});
const textarea = screen.getByTestId("quick-entry-input");
// Focus without typing
fireEvent.focus(textarea);
// Expand button should not be visible when empty
expect(screen.queryByTestId("quick-entry-expand")).not.toBeInTheDocument();
});
it("hides expand button when textarea is blurred", async () => {
renderQuickEntryBox({});
const textarea = screen.getByTestId("quick-entry-input");
// Focus, type, then blur
fireEvent.focus(textarea);
fireEvent.change(textarea, { target: { value: "Test content" } });
fireEvent.blur(textarea);
// Expand button should be hidden after blur
await act(async () => {
vi.advanceTimersByTime(100);
});
expect(screen.queryByTestId("quick-entry-expand")).not.toBeInTheDocument();
});
it("enters fullscreen mode when expand button is clicked", async () => {
renderQuickEntryBox({});
const textarea = screen.getByTestId("quick-entry-input");
// Focus and type content
fireEvent.focus(textarea);
fireEvent.change(textarea, { target: { value: "Test description" } });
// Click expand button
await waitFor(() => {
fireEvent.click(screen.getByTestId("quick-entry-expand"));
});
// Fullscreen textarea should be visible
await waitFor(() => {
expect(screen.getByTestId("quick-entry-input-fullscreen")).toBeInTheDocument();
});
// Collapse button should be visible
expect(screen.getByTestId("quick-entry-collapse")).toBeInTheDocument();
});
it("exits fullscreen mode when collapse button is clicked", async () => {
renderQuickEntryBox({});
const textarea = screen.getByTestId("quick-entry-input");
// Enter fullscreen mode
fireEvent.focus(textarea);
fireEvent.change(textarea, { target: { value: "Test description" } });
await waitFor(() => {
fireEvent.click(screen.getByTestId("quick-entry-expand"));
});
await waitFor(() => {
expect(screen.getByTestId("quick-entry-input-fullscreen")).toBeInTheDocument();
});
// Click collapse button
fireEvent.click(screen.getByTestId("quick-entry-collapse"));
// Fullscreen textarea should be hidden
await waitFor(() => {
expect(screen.queryByTestId("quick-entry-input-fullscreen")).not.toBeInTheDocument();
});
});
it("exits fullscreen mode when Escape key is pressed in fullscreen", async () => {
renderQuickEntryBox({});
const textarea = screen.getByTestId("quick-entry-input");
// Enter fullscreen mode
fireEvent.focus(textarea);
fireEvent.change(textarea, { target: { value: "Test description" } });
await waitFor(() => {
fireEvent.click(screen.getByTestId("quick-entry-expand"));
});
await waitFor(() => {
expect(screen.getByTestId("quick-entry-input-fullscreen")).toBeInTheDocument();
});
// Press Escape
const fullscreenTextarea = screen.getByTestId("quick-entry-input-fullscreen");
fireEvent.keyDown(fullscreenTextarea, { key: "Escape" });
// Fullscreen should be exited
await waitFor(() => {
expect(screen.queryByTestId("quick-entry-input-fullscreen")).not.toBeInTheDocument();
});
});
it("preserves description text when entering fullscreen", async () => {
renderQuickEntryBox({});
const textarea = screen.getByTestId("quick-entry-input");
// Type some content
fireEvent.focus(textarea);
fireEvent.change(textarea, { target: { value: "My test task description" } });
// Enter fullscreen
await waitFor(() => {
fireEvent.click(screen.getByTestId("quick-entry-expand"));
});
// Check fullscreen textarea has the content
await waitFor(() => {
const fullscreenTextarea = screen.getByTestId("quick-entry-input-fullscreen") as HTMLTextAreaElement;
expect(fullscreenTextarea.value).toBe("My test task description");
});
});
});
});